Convert True/False value read from file to boolean - python

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

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.

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)

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).

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.

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

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

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

pip install str2bool
>>> from str2bool import str2bool
>>> str2bool('Yes')
True
>>> str2bool('FaLsE')
False

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

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

Unfortunately, strtobool is now deprecated.
Here is an implementation based on configparser which you can use instead of your bool:
import configparser
def strtobool(s):
try:
return configparser.ConfigParser.BOOLEAN_STATES[s.lower()]
except KeyError as e:
raise ValueError('Not a boolean: %s' % s) from e

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

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,))

Ternary operator one-liner:
var_x = True if str_x == 'True' else False

Related

Difference between if not: and if False:

I have a probably quite simple question but was wondering between the difference of these two statements:
if not os.path.isfile(file):
#Do some stuff
if os.path.isfile(file) is False:
#Do some stuff
What are the differences (if any) between the two? To my understanding they both return a True or False value, so is it just a matter of preference or are there any significant differences?
In python (and other dynamic languages) there is the concept of truthy/falsy value. True/False are not the only things that evaluate as true/false
if not []:
print("this will be printed")
if [] is False:
print("this won't")
Another problem is that you should compare with x == False, and not x is False. The False is a singleton object in the current implementation of CPython, but this is not guaranteed by the specification.
In your case, since we know os.path.isfile returns True or False, there is no difference.
In general, there are a lot of objects in python which, when interpreted as boolean, will evaluate to False.
Think of this:
empty_list = []
if not empty_list:
print('List is not empty')
if empty_list is False:
print('List is False')
Among the others, None, "" and [] will evaluate to False.
So testing with not variable is usually the preferred way.
It's usually better to use the first, since it works even if you're not checking an actual boolean value in a Python implementation where False is a singleton object.
Uniformity is good, and so is portability.
>>> if 0 is False: print "false"
>>> if not 0: print "false"
false
>>> if [] is False: print "false"
>>> if not []: print "false"
false
>>> if "" is False: print "false"
>>> if not "": print "false"
false
It also protects against mishaps like this:
>>> False = 1
>>> True == False
True
You should know: False == 0 == None in case of if condition. If you use if not, you can cover all version of False (zero value). If you use == False you cannot handle the 0 or None. if not is recommended. The is operator is a different story (is not same as ==) but you can read more details on this link: Understanding Python's "is" operator

How to test if a value is falsy in Python 3

In Javascript, there is == operator to test if a value is falsy:
'' == false // true
In Python, == corresponds to === in Javascript, which is an exact equation (value & type).
So how to find out if a value is Falsy in Python?
You can obtain the truthiness of a value, by using the bool(..) function:
>>> bool('')
False
>>> bool('foo')
True
>>> bool(1)
True
>>> bool(None)
False
In an if statement, the truthiness is calculated implicitly. You can use the not keyword, to invert the truthiness. For example:
>>> not ''
True
>>> not 'foo'
False
>>> not 1
False
>>> not None
True
To get implicit conversion you can just use not - or (for "truthy") just use the variable in place:
if not None:
print('None')
if not False:
print('False')
if not '':
print('empty string')
if not 0:
print('zero')
if not {}:
print('empty/zero length container')
if 'hello':
print('non empty string, truthy test')
What worked was using ternary:
True if '' else False # False
More verbose than in Javascript, but works.
Even tho this question is old, but there is a not not (kinda hacky), but this is the faster than bool(..) and probably the fastest that's possible, you can do it by:
print(not not '')
print(not not 0)
print(not not 'bar')
Output:
False
False
True

Empty String Boolean Logic

I just stumbled across this and I couldn't find a sufficient answer:
x = ""
Why then is:
x == True
False
x == False
False
x != True
True
x != False
True
Am I supposed to conclude that x is neither True nor False?
to check if x is True of False:
bool("")
> False
bool("x")
> True
for details on the semantics of is and == see this question
Am I supposed to conclude that x is neither True nor False?
That's right. x is neither True nor False, it is "". The differences start with the type:
>>> print(type(""), type("x"), type(True), type(False))
builtins.str, builtins.str, builtins.bool, builtins.bool
Python is a highly object oriented language. Hence, strings are objects. The nice thing with python is that they can have a boolean representation for if x: print("yes"), e. g.. For strings this representation is len(x)!=0.
In a Boolean context, null / empty strings are false (Falsy). If you use
testString = ""
if not testString:
print("NULL String")
else:
print(testString)
As snakecharmerb said, if you pass the string to the bool() function it will return True or False based
>>> testString = ""
>>> bool(testString)
False
>>> testString = "Not an empty string"
>>> bool(testString)
True
See this doc on Truth Value Testing to learn more about this:
Python 2:
https://docs.python.org/2/library/stdtypes.html#truth-value-testing
Python 3:
https://docs.python.org/3/library/stdtypes.html#truth-value-testing
In python '==' tests for equality. The empty string is not equal to True, so the result of your comparison is False.
You can determine the 'truthiness' of the empty string by passing it to the bool function:
>>> x = ''
>>> bool(x)
False

Check if object is a number or boolean

Design a logical expression equivalent to the following statement:
x is a list of three or five elements, the second element of which is
the string 'Hip' and the first of which is not a number or Boolean.
What I have:
x = ['Head', 'Hip', 10]
print x[1] is 'Hip'
My question: How do you check for whether or not it is a Boolean or a number?
To answer the specific question:
isinstance(x[0], (int, float))
This checks if x[0] is an instance of any of the types in the tuple (int, float).
You can add bool in there, too, but it's not necessary, because bool is itself a subclass of int.
Doc reference:
isinstance()
built-in numeric types
To comment on your current code, you shouldn't rely on interning of short strings. You are supposed to compare strings with the == operator:
x[1] == 'Hip'
Easiest i would say:
type(x) == type(True)
In python3 this would be: type(x)==bool see example.
Python 2
import types
x = False
print(type(x) == types.BooleanType) # True
Python 3
# No need to import types module
x = False
print(type(x) == bool) # True
You should compare the type of x to the bool class:
type(x) == bool
or:
type(x) == type(True)
Here is more on the type method
From Data model docs:
Booleans (bool)
These represent the truth values False and True. The two objects representing the values False and True are the only Boolean objects. The Boolean type is a subtype of the integer type, and Boolean values behave like the values 0 and 1, respectively, in almost all contexts, the exception being that when converted to a string, the strings "False" or "True" are returned, respectively.
I follow the recent answer who tell to use type and it seems to be the incorrect way according to pylint validation:
I got the message:
C0123: Using type() instead of isinstance() for a typecheck.
(unidiomatic-typecheck)
Even if it's an old answer, the correct one is the accepted answer of #Lev Levitsky:
isinstance(x[0], (int, float))
Python 3:
Use assert to check is some statement is True or False. If False, it will raise an AssertionError.
assert(isinstance(x[0], (int, float)))
You can then catch the error like that:
except AssertionError as error:
print(error)
# do stuff...
I like to keep it simple to read..
This will accept bool, string, number and read it to a bool
def var2bool(v):
if type(v) == type(True):
res = v
elif type(v) == type(0):
if v == 0:
res = False
else:
res = True
elif v.lower() in ("yes", "true", "t", "1"):
res = True
else:
res = False
return res

Is it safe to replace '==' with 'is' to compare Boolean-values

I did several Boolean Comparisons:
>>> (True or False) is True
True
>>> (True or False) == True
True
It sounds like == and is are interchangeable for Boolean-values.
Sometimes it's more clear to use is
I want to know that:
Are True and False pre-allocated in python?
Is bool(var) always return the same True(or False) with the pre-allocated True(or False)?
Is it safe to replace == with is to compare Boolean-values?
It's not about Best-Practice.
I just want to know the Truth.
You probably shouldn't ever need to compare booleans. If you are doing something like:
if some_bool == True:
...
...just change it to:
if some_bool:
...
No is or == needed.
As commenters have pointed out, there are valid reasons to compare booleans. If both booleans are unknown and you want to know if one is equal to the other, you should use == or != rather than is or is not (the reason is explained below). Note that this is logically equivalent to xnor and xor respectively, which don't exist as logical operators in Python.
Internally, there should only ever be two boolean literal objects (see also the C API), and bool(x) is True should be True if bool(x) == True for any Python program. Two caveats:
This does not mean that x is True if x == True, however (eg. x = 1).
This is true for the usual implementation of Python (CPython) but might not be true in other implementations. Hence == is a more reliable comparison.
Watch out for what else you may be comparing.
>>> 1 == True
True
>>> 1 is True
False
True and False will have stable object ids for their lifetime in your python instance.
>>> id(True)
4296106928
>>> id(True)
4296106928
is compares the id of an object
EDIT: adding or
Since OP is using or in question it may be worth pointing this out.
or that evaluates True: returns the first 'True' object.
>>> 1 or True
1
>>> 'a' or True
'a'
>>> True or 1
True
or that evaluates False: returns the last 'False' object
>>> False or ''
''
>>> '' or False
False
and that evaluates to True: returns the last 'True' object
>>> True and 1
1
>>> 1 and True
True
and that evaluates to False: returns the first 'False' object
>>> '' and False
''
>>> False and ''
False
This is an important python idiom and it allows concise and compact code for dealing with boolean logic over regular python objects.
>>> bool([])
False
>>> bool([0])
True
>>> bool({})
False
>>> bool({False: False})
True
>>> bool(0)
False
>>> bool(-1)
True
>>> bool('False')
True
>>> bool('')
False
Basically 'empty' objects are False, 'non empty' are True.
Combining this with #detly's and the other answers should provide some insight into how to use if and bools in python.
Yes. There are guaranteed to be exactly two bools, True and False:
Class bool cannot be subclassed
further. Its only instances are False
and True.
That means if you know both operands are bool, == and is are equivalent. However, as detly notes, there's usually no reason to use either in this case.
It seems that all answers deal with True and False as defined after an interpreter startup. Before booleans became part of Python they were often defined as part of a program. Even now (Python 2.6.6) they are only names that can be pointed to different objects:
>>> True = 1
>>> (2 > 1)
True
>>> (2 > 1) == True
True
>>> (2 > 1) is True
False
If you have to deal with older software, be aware of that.
The == operator tests for equality The is keyword tests for object identity. Whether we are talking about the same object. Note, that more variables may refer to the same object.
== and is are both comparison operators, which would return a boolean value - True or False. True has a numeric value of 1 and False has a numeric value of 0.
The operator == compare the values of two objects and objects compared are most often are the same types (int vs int, float vs float), If you compare objects of different types, then they are unequal. The operator is tests for object identity, 'x is y' is true if both x and y have the same id. That is, they are same objects.
So, when you are comparing if you comparing the return values of same type, use == and if you are comparing if two objects are same (be it boolean or anything else), you can use is.
42 is 42 is True and is same as 42 == 42.
Another reason to compare values using == is that both None and False are “falsy” values. And sometimes it’s useful to use None to mark a value as “not defined” or “no value” while considering True and False values to work with:
def some_function(val = None):
"""This function does an awesome thing."""
if val is None:
# Values was not defined.
elif val == False:
# User passed boolean value.
elif val == True:
# User passed boolean value.
else:
# Quack quack.
Somewhat related question: Python != operation vs “is not”.

Categories

Resources