[python] Convert True/False value read from file to boolean

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?

This question is related to python string boolean

The answer is


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

If your data is from json, you can do that

import json

json.loads('true')

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

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.


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

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)

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

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

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


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.


pip install str2bool

>>> from str2bool import str2bool
>>> str2bool('Yes')
True
>>> str2bool('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).


Examples related to python

programming a servo thru a barometer Is there a way to view two blocks of code from the same file simultaneously in Sublime Text? python variable NameError Why my regexp for hyphenated words doesn't work? Comparing a variable with a string python not working when redirecting from bash script is it possible to add colors to python output? Get Public URL for File - Google Cloud Storage - App Engine (Python) Real time face detection OpenCV, Python xlrd.biffh.XLRDError: Excel xlsx file; not supported Could not load dynamic library 'cudart64_101.dll' on tensorflow CPU-only installation

Examples related to string

How to split a string in two and store it in a field String method cannot be found in a main class method Kotlin - How to correctly concatenate a String Replacing a character from a certain index Remove quotes from String in Python Detect whether a Python string is a number or a letter How does String substring work in Swift How does String.Index work in Swift swift 3.0 Data to String? How to parse JSON string in Typescript

Examples related to boolean

Convert string to boolean in C# In c, in bool, true == 1 and false == 0? Syntax for an If statement using a boolean Truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all() Ruby: How to convert a string to boolean Casting int to bool in C/C++ Radio Buttons ng-checked with ng-model How to compare Boolean? Convert True/False value read from file to boolean Logical operators for boolean indexing in Pandas