How do I convert a string into a boolean in Python? This attempt returns True:
>>> bool("False")
True
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)
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.
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.
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
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
my_string == "True" does the exact same thing, yet both options don't deal with incorrect input (i.e. "true").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
x in 'True true', which is much shorter. but still bad, because it accepts 'ue tr' as True...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.
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)
# ...
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'>
#\nshutil.rmtree('/someImportantDirectory')? (Don't try it!)eval for something this simple is just asking for a vulnerability.eval those strings might help someone to take over the whole system.
bool("string")it always returnsTrue...except for the empty stringbool("")