1356

How do I convert a string into a boolean in Python? This attempt returns True:

>>> bool("False")
True
1
  • But when trying bool("string") it always returns True...except for the empty string bool("") Commented Mar 14, 2022 at 15:08

43 Answers 43

1
2
1

I realize this is an old post, but some of the solutions require quite a bit of code, here's what I ended up using:

def str2bool(value):
    return {"True": True, "true": True}.get(value, False)
Sign up to request clarification or add additional context in comments.

1 Comment

That's functionally equivalent to, and more complex than: return value in ('True', 'true')
1

Use package str2bool pip install str2bool

Comments

1

I was also required to change the input to bool for a function and the main input was only True or False in string. So, I just coded it like this:

def string_to_bool(s):
    bool_flag = True
    if s == "False":
        bool_flag = False
    elif s == "True":
        bool_flag = True
    else:
        print("Invalid Input")
    return bool_flag

You can also check it for more shortened for True and False like Y/N or y/n etc.

3 Comments

The extra bool_flag variable is so useless
@BlakBat How? Can you explain why it is useless?
Just return the value: if s == "False": return False. etc.
0

here's a hairy, built in way to get many of the same answers. Note that although python considers "" to be false and all other strings to be true, TCL has a very different idea about things.

>>> import Tkinter
>>> tk = Tkinter.Tk()
>>> var = Tkinter.BooleanVar(tk)
>>> var.set("false")
>>> var.get()
False
>>> var.set("1")
>>> var.get()
True
>>> var.set("[exec 'rm -r /']")
>>> var.get()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python2.5/lib-tk/Tkinter.py", line 324, in get
    return self._tk.getboolean(self._tk.globalgetvar(self._name))
_tkinter.TclError: 0expected boolean value but got "[exec 'rm -r /']"
>>> 

A good thing about this is that it is fairly forgiving about the values you can use. It's lazy about turning strings into values, and it's hygenic about what it accepts and rejects(notice that if the above statement were given at a tcl prompt, it would erase the users hard disk).

the bad thing is that it requires that Tkinter be available, which is usually, but not universally true, and more significantly, requires that a Tk instance be created, which is comparatively heavy.

What is considered true or false depends on the behavior of the Tcl_GetBoolean, which considers 0, false, no and off to be false and 1, true, yes and on to be true, case insensitive. Any other string, including the empty string, cause an exception.

Comments

0
def str2bool(str):
  if isinstance(str, basestring) and str.lower() in ['0','false','no']:
    return False
  else:
    return bool(str)

idea: check if you want the string to be evaluated to False; otherwise bool() returns True for any non-empty string.

Comments

0

Here's something I threw together to evaluate the truthiness of a string:

def as_bool(val):
 if val:
  try:
   if not int(val): val=False
  except: pass
  try:
   if val.lower()=="false": val=False
  except: pass
 return bool(val)

more-or-less same results as using eval but safer.

Comments

0

I just had to do this... so maybe late to the party - but someone may find it useful

def str_to_bool(input, default):
    """
    | Default | not_default_str | input   | result
    | T       |  "false"        | "true"  |  T
    | T       |  "false"        | "false" |  F
    | F       |  "true"         | "true"  |  T
    | F       |  "true"         | "false" |  F

    """
    if default:
        not_default_str = "false"
    else:
        not_default_str = "true"

    if input.lower() == not_default_str:
        return not default
    else:
        return default

Comments

0

I like to use the ternary operator for this, since it's a bit more succinct for something that feels like it shouldn't be more than 1 line.

True if my_string=="True" else False

3 Comments

How is it more succinct than my_string == 'True'?
my_string == "True" does the exact same thing, yet both options don't deal with incorrect input (i.e. "true").
Not sure what to say, 10 years ago I was clearly an idiot...
0

we may need to catch 'true' case insensitive, if so:

>>> x="TrUE"  
>>> x.title() == 'True'  
True  

>>> x="false"  
>>> x.title() == 'True'  
False  

also note, it will return False for any other input which is neither true or false

2 Comments

You could also just do x in 'True true', which is much shorter. but still bad, because it accepts 'ue tr' as True...
@Neuron good point. edited.
0

The top-rated answer is fine for limited cases or situations where you can make strong assumptions about the data you are processing. However, because custom objects can override __eq__ equality checking in Python, there is a significant pitfall. Consider the deliberately over-simplified toy example below:

In [1]: class MyString: 
   ...:     def __init__(self, value): 
   ...:         self.value = value 
   ...:     def __eq__ (self, obj): 
   ...:         if hasattr(obj, 'value'): 
   ...:             return obj.value == self.value 
   ...:         return False 
   ...:                                                                                                                                           

In [2]: v = MyString("True")                                                                                                                      

In [3]: v == "True"                                                                                                                               
Out[3]: False

If you imagine someone inheriting from a string type for MyString or implementing all kinds of native string methods, repr, etc., so that MyString instances mostly behave exactly like strings, but have the special extra value step in equality checking, then simple use of == 'True' would fail, and most likely it would be a silent failure from the user's perspective.

This is why it's good practice to coerce type into the exact nature of equality checking you want to perform, put that encapsulated into a helper function, and be pedantic about relying on that kind of "registered" way to validate things. For example with MyString you might write something like this,

def validate(s):
    if isinstance(s, str):
        return s == 'True'
    elif isinstance(s, MyString):
        return s.value == 'True' # <-- business logic
    ...
    raise ValueError(f"Type {type(s)} not supported for validation.")

Or another often used pattern is the reverse perspective where you define exactly one behavior for validation but you have a helper function that forces coercion into a type amenable for that single validation behavior, such as

def to_str(s):
    if isinstance(s, str):
        return s
    elif isinstance(s, MyString):
        return s.value
    ...
    raise ValueError(f"Unsupported type {type(s)}")

def validate(s):
    return to_str(s) == 'True'
    

It might look like we're adding a lot of boilerplate and verbosity. We could glibly express critique by saying, "why write all that if you can just write s == 'True'?" - But it misses the point that when you are validating something, you need to make sure all of your preconditions hold for the validation logic to be applied. If you can assume some data is a plain str type and you don't need to do any of that precondition (such as type) checking, great - but that's a very rare situation and it can be misleading to characterize the general situation for this question as being amenable to one super short and concise equality check.

Comments

0

This is an answer that uses code from the Django Rest Framework (DRF) 3.14.

You can either:

from rest_framework.fields import BooleanField
f = BooleanField(allow_null=True)
test_values = [ True, "True", "1", 1, -1, 1.0, "true", "t", "on",
         None, "null", "NULL",
         False, "False", "0", 0, "false", "f", 0.0, "off" ]
for item in test_values:
    r = f.to_internal_value(item)
    print(r)
   
# a shorter version
from rest_framework.fields import BooleanField
test_values = [ True, "True", "1", 1, -1, 1.0, "true", "t", "on",
         None, "null", "NULL",
         False, "False", "0", 0, "false", "f", 0.0, "off" ]
for item in test_values:
    print(BooleanField(allow_null=True).to_internal_value(item))

Or you could adapt the code of the BooleanField so that it suits your need. Here is the actual code of the class BooleanField as in DRF 3.x

# from rest_framework.fields 
# ...

class BooleanField(Field):
    default_error_messages = {
        'invalid': _('Must be a valid boolean.')
    }
    default_empty_html = False
    initial = False
    TRUE_VALUES = {
        't', 'T',
        'y', 'Y', 'yes', 'Yes', 'YES',
        'true', 'True', 'TRUE',
        'on', 'On', 'ON',
        '1', 1,
        True
    }
    FALSE_VALUES = {
        'f', 'F',
        'n', 'N', 'no', 'No', 'NO',
        'false', 'False', 'FALSE',
        'off', 'Off', 'OFF',
        '0', 0, 0.0,
        False
    }
    NULL_VALUES = {'null', 'Null', 'NULL', '', None}
    
    def to_internal_value(self, data):
        try:
            if data in self.TRUE_VALUES:
                return True
            elif data in self.FALSE_VALUES:
                return False
            elif data in self.NULL_VALUES and self.allow_null:
                return None
        except TypeError:  # Input is an unhashable type
            pass
        self.fail('invalid', input=data)
    
    def to_representation(self, value):
        if value in self.TRUE_VALUES:
            return True
        elif value in self.FALSE_VALUES:
            return False
        if value in self.NULL_VALUES and self.allow_null:
            return None
        return bool(value)

# ...

Comments

0

I feel the simplest way is to check the value.

bool_value = "false"
convert_to_bool = True if bool_value.lower() == 'true' else False

Comments

-8

By using Python's built-in eval() function and the .capitalize() method, you can convert any "true" / "false" string (regardless of initial capitalization) to a true Python boolean.

For example:

true_false = "trUE"
type(true_false)

# OUTPUT: <type 'str'>

true_false = eval(true_false.capitalize())
type(true_false)

# OUTPUT: <type 'bool'>

10 Comments

What happens, if the string contains #\nshutil.rmtree('/someImportantDirectory')? (Don't try it!)
@mastov - ridiculous downvote. Obviously if you don't have control of the incoming string, you need to put precautions in place, as you would with any code. But if you do control the workflow, this is a simple solution that works. Don't confuse a solution that isn't perfect in every way with a bad answer.
Apart from not mentioning the dangers (which already makes this a bad answer): You are proposing to sanitize the input beforehand? That's going to kill the simplicity of this method, which was its main plus.
Using eval for something this simple is just asking for a vulnerability.
Not all code. But especially code that converts strings to other types usually is out of your control. Often you might not even realize it. You might say: "It's my database (or config file), it's part of my system, under my control." Then you give some other module access to a database because: "What's the harm? It's only some tables with strings." But with eval those strings might help someone to take over the whole system.
|
1
2

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.