Convert True/False value read from file to boolean

162,398

Solution 1

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

Solution 2

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.

Solution 3

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)

Solution 4

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

Solution 5

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
Share:
162,398
Gabriel
Author by

Gabriel

Updated on April 29, 2021

Comments

  • Gabriel
    Gabriel about 3 years

    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?

  • SethMMorton
    SethMMorton about 10 years
    You could make it a "heroic" ValueError by doing raise ValueError("Cannot covert {} to a bool".format(s)).
  • Gabriel
    Gabriel about 10 years
    Selecting this one since it uses no extra packages. Thanks guys!
  • SethMMorton
    SethMMorton about 10 years
    What's wrong with "extra packages"? Are you referring to ast? It's part of the standard library, so it's not really extra.
  • Charlie Parker
    Charlie Parker almost 8 years
    it might be a silly question but why does bool just not convert the strings True and False to the boolean values True and False? Seems to be inconsistent behaviour from what int does. I just genuinely curious why my reasoning is wrong and why the other option was the decision.
  • Charlie Parker
    Charlie Parker almost 8 years
    it might be a silly question but why does bool just not convert the strings True and False to the boolean values True and False? Seems to be inconsistent behaviour from what int does. I just genuinely curious why my reasoning is wrong and why the other option was the decision.
  • Bill Kidd
    Bill Kidd almost 8 years
    Whenever comparing strings I like to flatten the case, (where applicable). for example I would use: if s.upper() == 'TRUE': return True elif s.upper() == 'FALSE' return False
  • M07
    M07 over 7 years
    @samyi It is dangerous to use the eval method. stackoverflow.com/questions/1832940/…
  • Alex
    Alex about 7 years
    Even better, do bool(strtobool(my_string)) to cast the output as a boolean True / False variable
  • Chris
    Chris over 6 years
    ast.literal_eval('false') throws an exception, which I think makes it less desirable
  • Ashwini Chaudhary
    Ashwini Chaudhary over 6 years
    @Chris You can always wrap it around try-except in a custom function instead of using it directly then.
  • Nostalg.io
    Nostalg.io about 6 years
    FYI. This is a terrible idea and you should never use eval(). In my opinion, it should be removed from the language.
  • Keith Ripley
    Keith Ripley about 6 years
    This is VERY VERY BAD because it is a security flaw. If you use eval() on raw data from a file then it means that anyone with write access to that file can execute code at the same permissions level as your script.
  • kev
    kev about 6 years
    Additionally, if values have not the exact python spelling, e.g. eval('false'), eval('FALSE') it will error.
  • Ashwini Chaudhary
    Ashwini Chaudhary over 4 years
    @HewwoCraziness It parses only expressions not any random code.
  • dericke
    dericke about 4 years
    @AlexG crazy that a function called strtobool() does not, in fact, return a bool
  • Ari
    Ari over 3 years
    This doesn't work unless the input value can actually be a boolean, otherwise, it seems to throw a value error. The only thing I can think of is to add a try/except to your function and on ValueError return false.
  • Ben
    Ben about 2 years
    This gives a JSON Decode Error when the string is 'True' or 'False' i.e. title-format. Use json.loads('False'.lower) in that case.