Convert True/False value read from file to boolean
Question:
I’m reading a True - False
value from a file and I need to convert it to boolean. Currently it always converts it to True
even if the value is set to False
.
Here’s a MWE
of what I’m trying to do:
with open('file.dat', mode="r") as f:
for line in f:
reader = line.split()
# Convert to boolean <-- Not working?
flag = bool(reader[0])
if flag:
print 'flag == True'
else:
print 'flag == False'
The file.dat
file basically consists of a single string with the value True
or False
written inside. The arrangement looks very convoluted because this is a minimal example from a much larger code and this is how I read parameters into it.
Why is flag
always converting to True
?
Answers:
bool('True')
and bool('False')
always return True
because strings ‘True’ and ‘False’ are not empty.
To quote a great man (and Python documentation):
5.1. Truth Value Testing
Any object can be tested for truth value, for use in an if or while
condition or as operand of the Boolean operations below. The
following values are considered false:
- …
- zero of any numeric type, for example,
0
, 0L
, 0.0
, 0j
.
- any empty sequence, for example,
''
, ()
, []
.
- …
All other values are considered true — so objects of many types
are always true.
The built-in bool
function uses the standard truth testing procedure. That’s why you’re always getting True
.
To convert a string to boolean you need to do something like this:
def str_to_bool(s):
if s == 'True':
return True
elif s == 'False':
return False
else:
raise ValueError # evil ValueError that doesn't tell you what the wrong value was
Use ast.literal_eval
:
>>> import ast
>>> ast.literal_eval('True')
True
>>> ast.literal_eval('False')
False
Why is flag always converting to True?
Non-empty strings are always True in Python.
Related: Truth Value Testing
If NumPy is an option, then:
>>> import StringIO
>>> import numpy as np
>>> s = 'True - False - True'
>>> c = StringIO.StringIO(s)
>>> np.genfromtxt(c, delimiter='-', autostrip=True, dtype=None) #or dtype=bool
array([ True, False, True], dtype=bool)
I’m not suggested this as the best answer, just an alternative but you can also do something like:
flag = reader[0] == "True"
flag will be True
id reader[0] is “True”, otherwise it will be False
.
You can use dict to convert string to boolean. Change this line flag = bool(reader[0])
to:
flag = {'True': True, 'False': False}.get(reader[0], False) # default is False
you can use distutils.util.strtobool
>>> from distutils.util import strtobool
>>> strtobool('True')
1
>>> strtobool('False')
0
True
values are y
, yes
, t
, true
, on
and 1
; False
values are n
, no
, f
, false
, off
and 0
. Raises ValueError
if val is anything else.
Currently, it is evaluating to True
because the variable has a value. There is a good example found here of what happens when you evaluate arbitrary types as a boolean.
In short, what you want to do is isolate the 'True'
or 'False'
string and run eval
on it.
>>> eval('True')
True
>>> eval('False')
False
The cleanest solution that I’ve seen is:
from distutils.util import strtobool
def string_to_bool(string):
return bool(strtobool(str(string)))
Sure, it requires an import, but it has proper error handling and requires very little code to be written (and tested).
pip install str2bool
>>> from str2bool import str2bool
>>> str2bool('Yes')
True
>>> str2bool('FaLsE')
False
If you want to be case-insensitive, you can just do:
b = True if bool_str.lower() == 'true' else False
Example usage:
>>> bool_str = 'False'
>>> b = True if bool_str.lower() == 'true' else False
>>> b
False
>>> bool_str = 'true'
>>> b = True if bool_str.lower() == 'true' else False
>>> b
True
If your data is from json, you can do that
import json
json.loads(‘true’)
True
You can do with json
.
In [124]: import json
In [125]: json.loads('false')
Out[125]: False
In [126]: json.loads('true')
Out[126]: True
If you need quick way to convert strings into bools (that functions with most strings) try.
def conv2bool(arg):
try:
res= (arg[0].upper()) == "T"
except Exception,e:
res= False
return res # or do some more processing with arg if res is false
Just to add that if your truth value can vary, for instance if it is an input from different programming languages or from different types, a more robust method would be:
flag = value in ['True','true',1,'T','t','1'] # this can be as long as you want to support
And a more performant variant would be (set lookup is O(1)):
TRUTHS = set(['True','true',1,'T','t','1'])
flag = value in truths
Using dicts to convert "True" in True:
def str_to_bool(s: str):
status = {"True": True,
"False": False}
try:
return status[s]
except KeyError as e:
#logging
If you have
>>> my_value = "False"
then either do
>>> my_value in "False"
True
>>> my_value in "True"
False
or
>>> "False" in my_value
True
>>> "True" in my_value
False
def strtobool(val):
"""Convert a string representation of truth to true (1) or false (0).
True values are 'y', 'yes', 't', 'true', 'on', and '1'; false values
are 'n', 'no', 'f', 'false', 'off', and '0'. Raises ValueError if
'val' is anything else.
"""
val = val.lower()
if val in ('y', 'yes', 't', 'true', 'on', '1'):
return True
elif val in ('n', 'no', 'f', 'false', 'off', '0'):
return False
else:
raise ValueError("invalid truth value %r" % (val,))
I’m reading a True - False
value from a file and I need to convert it to boolean. Currently it always converts it to True
even if the value is set to False
.
Here’s a MWE
of what I’m trying to do:
with open('file.dat', mode="r") as f:
for line in f:
reader = line.split()
# Convert to boolean <-- Not working?
flag = bool(reader[0])
if flag:
print 'flag == True'
else:
print 'flag == False'
The file.dat
file basically consists of a single string with the value True
or False
written inside. The arrangement looks very convoluted because this is a minimal example from a much larger code and this is how I read parameters into it.
Why is flag
always converting to True
?
bool('True')
and bool('False')
always return True
because strings ‘True’ and ‘False’ are not empty.
To quote a great man (and Python documentation):
5.1. Truth Value Testing
Any object can be tested for truth value, for use in an if or while
condition or as operand of the Boolean operations below. The
following values are considered false:
- …
- zero of any numeric type, for example,
0
,0L
,0.0
,0j
.- any empty sequence, for example,
''
,()
,[]
.- …
All other values are considered true — so objects of many types
are always true.
The built-in bool
function uses the standard truth testing procedure. That’s why you’re always getting True
.
To convert a string to boolean you need to do something like this:
def str_to_bool(s):
if s == 'True':
return True
elif s == 'False':
return False
else:
raise ValueError # evil ValueError that doesn't tell you what the wrong value was
Use ast.literal_eval
:
>>> import ast
>>> ast.literal_eval('True')
True
>>> ast.literal_eval('False')
False
Why is flag always converting to True?
Non-empty strings are always True in Python.
Related: Truth Value Testing
If NumPy is an option, then:
>>> import StringIO
>>> import numpy as np
>>> s = 'True - False - True'
>>> c = StringIO.StringIO(s)
>>> np.genfromtxt(c, delimiter='-', autostrip=True, dtype=None) #or dtype=bool
array([ True, False, True], dtype=bool)
I’m not suggested this as the best answer, just an alternative but you can also do something like:
flag = reader[0] == "True"
flag will be True
id reader[0] is “True”, otherwise it will be False
.
You can use dict to convert string to boolean. Change this line flag = bool(reader[0])
to:
flag = {'True': True, 'False': False}.get(reader[0], False) # default is False
you can use distutils.util.strtobool
>>> from distutils.util import strtobool
>>> strtobool('True')
1
>>> strtobool('False')
0
True
values are y
, yes
, t
, true
, on
and 1
; False
values are n
, no
, f
, false
, off
and 0
. Raises ValueError
if val is anything else.
Currently, it is evaluating to True
because the variable has a value. There is a good example found here of what happens when you evaluate arbitrary types as a boolean.
In short, what you want to do is isolate the 'True'
or 'False'
string and run eval
on it.
>>> eval('True')
True
>>> eval('False')
False
The cleanest solution that I’ve seen is:
from distutils.util import strtobool
def string_to_bool(string):
return bool(strtobool(str(string)))
Sure, it requires an import, but it has proper error handling and requires very little code to be written (and tested).
pip install str2bool
>>> from str2bool import str2bool
>>> str2bool('Yes')
True
>>> str2bool('FaLsE')
False
If you want to be case-insensitive, you can just do:
b = True if bool_str.lower() == 'true' else False
Example usage:
>>> bool_str = 'False'
>>> b = True if bool_str.lower() == 'true' else False
>>> b
False
>>> bool_str = 'true'
>>> b = True if bool_str.lower() == 'true' else False
>>> b
True
If your data is from json, you can do that
import json
json.loads(‘true’)
True
You can do with json
.
In [124]: import json
In [125]: json.loads('false')
Out[125]: False
In [126]: json.loads('true')
Out[126]: True
If you need quick way to convert strings into bools (that functions with most strings) try.
def conv2bool(arg):
try:
res= (arg[0].upper()) == "T"
except Exception,e:
res= False
return res # or do some more processing with arg if res is false
Just to add that if your truth value can vary, for instance if it is an input from different programming languages or from different types, a more robust method would be:
flag = value in ['True','true',1,'T','t','1'] # this can be as long as you want to support
And a more performant variant would be (set lookup is O(1)):
TRUTHS = set(['True','true',1,'T','t','1'])
flag = value in truths
Using dicts to convert "True" in True:
def str_to_bool(s: str):
status = {"True": True,
"False": False}
try:
return status[s]
except KeyError as e:
#logging
If you have
>>> my_value = "False"
then either do
>>> my_value in "False"
True
>>> my_value in "True"
False
or
>>> "False" in my_value
True
>>> "True" in my_value
False
def strtobool(val):
"""Convert a string representation of truth to true (1) or false (0).
True values are 'y', 'yes', 't', 'true', 'on', and '1'; false values
are 'n', 'no', 'f', 'false', 'off', and '0'. Raises ValueError if
'val' is anything else.
"""
val = val.lower()
if val in ('y', 'yes', 't', 'true', 'on', '1'):
return True
elif val in ('n', 'no', 'f', 'false', 'off', '0'):
return False
else:
raise ValueError("invalid truth value %r" % (val,))