1227

How do I convert a string into a boolean in Python? This attempt returns True:

>>> bool("False")
True
Mateen Ulhaq
  • 24,552
  • 19
  • 101
  • 135
Joan Venge
  • 315,713
  • 212
  • 479
  • 689
  • 4
    i have created a micro-library just for this which also included some foreign words e.g. "tak" for Polish, "'是的" in Mandarin-Chinese will evaluate to __True__. If not explicitly true-ish will evaluate to __False__. Suggestions are welcome. Github link: https://github.com/kmonsoor/str2bool – kmonsoor Aug 25 '15 at 12:30
  • But when trying `bool("string")` it always returns `True`...except for the empty string `bool("")` – FiddleStix Mar 14 '22 at 15:08
  • You're thinking of Perl ! :-D – MikeW Mar 28 '23 at 11:23

39 Answers39

1290

Really, you just compare the string to whatever you expect to accept as representing true, so you can do this:

s == 'True'

Or to checks against a whole bunch of values:

s.lower() in ['true', '1', 't', 'y', 'yes', 'yeah', 'yup', 'certainly', 'uh-huh']

Be cautious when using the following:

>>> bool("foo")
True
>>> bool("")
False

Empty strings evaluate to False, but everything else evaluates to True. So this should not be used for any kind of parsing purposes.

Keith Gaughan
  • 21,367
  • 3
  • 32
  • 30
  • 67
    +1: Not much could be simpler than `s == "True"`. But I've seen people make a real mess of this. def convert(s): if s == "True": return True; return False. – S.Lott Apr 03 '09 at 20:11
  • 40
    I prefer return s == "True" over the if/else – Dana Apr 03 '09 at 20:35
  • 2
    @Dana: everyone should. if x: return True is a terrible thing. The only thing worse is if x: return False. – S.Lott Apr 03 '09 at 23:10
  • 39
    if s == "True": return True elif s=="False": return False else: return raise – Unknown Jul 11 '09 at 21:43
  • 1
    You are missing the false part. False is not the same as "not True" when parsing, as you will be parsing all errors to false. – estani Nov 26 '12 at 09:34
  • 4
    @estani: No, I didn't miss the false part. You're missing the point of my answer, which was to demonstrate the basic principle of simply checking if the string provided is amongst the valid values. You'll notice that I didn't provide a function to do the complete job: that was on purpose. – Keith Gaughan Nov 26 '12 at 10:41
  • @Keith don't take it wrong, but I still think that in order to answer the question posted here, you need to clarify that when parsing a string, you should parse both values and fail otherwise. IMHO you are missing the point of the question. – estani Nov 26 '12 at 10:44
  • 19
    Parsing strings to booleans is already implemented in distutils.util.strtobool: http://stackoverflow.com/a/18472142/923599 – jzwiener Aug 28 '13 at 10:04
  • 1
    Yeah, I know about that, and it's possibly one of the oddest places to put something like that. In fact, that whole module is a grab-bag of stuff that would be better off elsewhere, and that's one of the reasons I don't use it: that whole module is the kind of thing that's likely to be deprecated at some point in the future. – Keith Gaughan Aug 28 '13 at 10:46
  • 2
    apparently you should use a `set` rather than `list` for the truthy strings... http://stackoverflow.com/a/7110296/202168 – Anentropic Dec 22 '14 at 05:37
  • 2
    That depends. For something very short, it can be faster to scan a list or tuple. It's a trade-off between the length of time it takes to scan the list/tuple vs the time taken to hash the object look it up, and you also have to factor in the time needed to create the set object itself. It's not something I'd worry about too much unless it's really something that needs optimising. Profile, then optimise. – Keith Gaughan Dec 23 '14 at 01:54
  • 36
    I know this is a REALLY old topic, but I wanted to attest that I have just spent 4 hours trying to debug my code. My mistake was trying to cast `bool("False")`. It will always cast to `True`. – Ev. Sep 02 '16 at 12:37
  • 2
    I suggest adding the boolean `True` in your list of true values. This way if `s` was already converted to a boolean previously, the result will be True instead of False. `s in ['true', '1', 't', 'y', 'yes', 'yeah', 'yup', 'certainly', 'uh-huh', True]` – user2023861 Jun 17 '19 at 15:26
  • 1
    I'll add a dissenting opinion on this one. This is an issue with Python design, not users overcomplicating things. It bools down to a case when type safety is sincerely needed. Checking `s == 'True'` is a bad way to solve it because the type of `s` can be anything, and people are free to implement screwball overrides of equality checking. To be safe then, you have to start putting in assert statements and attempts to do type casting before the equality check and very quickly you can sympathize with what @S.Lott calls "a real mess" because the naive 'easy' way often breaks. – ely Aug 14 '19 at 14:50
  • @ely Your complaint boils down to "Python is dynamically typed, and that's bad". @S.Lott's note had nothing to do with type safety, but that people use unnecessary if-statements. `s == 'True'` evaluates to a boolean object, so including an if-statement whose clauses are `return True` and `return False` is an overcomplication. – Keith Gaughan Aug 15 '19 at 14:47
  • @KeithGaughan you are incorrect. I happen to love Python's dynamic typing and have used it happily for many years. But we can't have rose colored glasses to the fact that some aspects of Python are designed badly. On your last point I think you misunderstood my comment. I totally understand the extra `return True` type thing is strictly not needed, I am saying that using `s == 'True'` is bad for a bunch of reasons and so people don't use `s == 'True'` in practice and end up needing lots of other complications like `my_converter_func(s) is True` where `my_converter_func` really is needed. – ely Aug 16 '19 at 13:28
  • @ely I think you're misunderstanding my point, and the point @S.Lott was making. Maybe if I phrase it in terms of Java rather than Python, it'll make more sense. We were saying that writing something like `bool isOdd(int n) { if (n % 2 == 1) { return true; } else { return false; }}` is bad when you can just write `bool isOdd(int n) { return n % 2 == 1; }`. Your stuff about types was irrelevant to the point. Also, your 'badly designed' stuff is true of every dynamically typed language, and Python is less 'bad' than most because it's also strongly typed. – Keith Gaughan Aug 19 '19 at 13:44
  • @KeithGaughan I encourage you to re-read my comments. The specific details about an extraneous `return True` when you could just return the evaluation of the boolean condition itself ... that is not related to my comment or to the original from S.Lott that I was responding to. That's just some ancillary detail about one particular inefficient way to deal with it in novice implementations, and is not related at all to the bigger point. – ely Aug 19 '19 at 14:10
  • @ely, I fail to see the point you're trying to make. 'the type of `s` can be anything' is a consequence of Python being dynamically typed. I fail to see how your comments relate to anything @S.Lott wrote. What exactly is it that makes `s == 'True'` bad? What's the context? If one is reading from a configuration file and checking if a field contains a boolean token, something like this would be fine. I mean, you can do 'stringly typing' in just about any language. Are you saying the strings 'true' and 'false' should be treated as booleans? I'm not clear what point you're trying to make. – Keith Gaughan Aug 21 '19 at 09:47
  • 1
    Note that using a set instead of a list as done in this answer, seems to make it much faster... This is based on both timing this operation as well as the time complexity: https://wiki.python.org/moin/TimeComplexity – Moot Jan 16 '20 at 08:22
  • 1
    This answer is really nice when trying to interpret environment variables since they get passed in as string, you can just use ```my_var = os.environ["MY_ENV_VAR"]=="True"``` – BLang Jun 01 '20 at 22:04
  • Add `s.strip().lower()` to trim excess whitespace. – Darren Weber Jul 10 '20 at 22:27
  • You could add that too and, in a real-world situation to clean up the input, should, but it's tangential to the point I'm trying to make, which is not to complicate things and just use comparisons. – Keith Gaughan Jul 11 '20 at 23:50
  • Here is a good overview of values that will yield False: https://www.w3schools.com/python/python_booleans.asp False, None, 0, "", (), [], {} – Sigmatics Jan 11 '21 at 09:45
  • @KeithGaughan Just coming back to this thread. I still feel you missed the point of my examples. The key point is that `s == 'True'` hinges on the definition of `__eq__`, so it's not in general safe to compare with a string on the RHS. That's not "a consequence of dynamic typing" - it's a consequence of Python's data model. Because someone might need to compare `s` with `'True'`, and they can't control what type `s` is or how `__eq__` may have been overridden, it virtually always necessitates using formatters / validators as helpers, like `some_converter_func(s) is True`, to "handle" `__eq__` – ely Mar 04 '21 at 21:42
  • @ely I didn't miss anything in your examples. If you have your own answer you want to post, post your own answer. – Keith Gaughan Mar 09 '21 at 21:07
  • @KeithGaughan the main thing is just to ensure there is a strong signal about the pitfall for relying on `__eq__` in _this_ answer. It's a perfectly fine answer as long as that caveat is noted strongly, as in these comments. – ely Mar 09 '21 at 21:20
  • 1
    @ely I'm not seeing the need. Look, this answer is ten years old. If you feel like there could be a better answer, feel free to write your own rather than trying to debate with me. – Keith Gaughan Mar 10 '21 at 15:13
  • What would be your list of False booleans equivalent to `s.lower() in ['true', '1', 't', 'y', 'yes', 'yeah', 'yup', 'certainly', 'uh-huh']` ? :) – Dr_Zaszuś Sep 10 '21 at 08:09
  • @Dr_Zaszuś That's entirely up to you and what you expect to be treated as `False`. – Keith Gaughan Dec 02 '21 at 14:07
  • @KeithGaughan seeing this thread again a while later, I did [write an answer](https://stackoverflow.com/a/74030588/567620) that demonstrates the pitfall I tried to explain and the reason why encapsulating separate validator logic is usually the right thing to choose even from the very start with problems like this. – ely Oct 11 '22 at 15:36
  • @ely - look, it's a year and a half since you last commented. Something like this shouldn't be dominating your mind for _this_ long. I don't disagree that encapsulating something like this in a function isn't a perfectly fine idea, but the question is just about how you do the thing in the first place. Let's not overthink things. – Keith Gaughan Oct 12 '22 at 17:39
  • I occasionally look back at unresolved threads. No need for you to worry or estimate how much it is occupying my mind. I have only given it a tiny bit of attention and it was valuable to write up the alternative in a new answer, so at least that should wrap it up. Thank you for your perspective on it. – ely Oct 12 '22 at 18:56
  • I've considered this pretty much wrapped up for the last decade. – Keith Gaughan Oct 18 '22 at 07:35
  • Well it is not True when ANYTHING is True beside you want only false/False to be False – Sion C Dec 04 '22 at 14:45
540

Warning: This answer will no longer work as of Python 3.12 (it's deprecated as of 3.10)

Use:

bool(distutils.util.strtobool(some_string))

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.

Be aware that distutils.util.strtobool() returns integer representations and thus it needs to be wrapped with bool() to get Boolean values.

Given that distutils will no longer be part of the standard library, here is the code for distutils.util.strtobool() (see the source code for 3.11.2).

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 1
    elif val in ('n', 'no', 'f', 'false', 'off', '0'):
        return 0
    else:
        raise ValueError("invalid truth value %r" % (val,))
Cristian Ciupitu
  • 20,270
  • 7
  • 50
  • 76
jzwiener
  • 8,182
  • 4
  • 21
  • 23
  • 6
    That function is tantalizing. It would be perfect if it handled integers and `None` and `str(None)` as input. – MarkHu Dec 04 '14 at 06:50
  • 29
    I much prefer this to the higher voted answers... it's from stdlib and does exactly what's required. There is generally no reason to need an actual `bool` instead of `1`/`0` as long as you're not doing bad stuff like `if x == False`... and if you're dealing with `int`s and `None`s you don't need a special function, you can just check them directly `if myint:` or `if not maybe_none_var:` – Anentropic Dec 22 '14 at 05:41
  • 6
    @Secator `bool` is a sub-class of `int` – Anentropic Dec 22 '14 at 05:45
  • 25
    To save someone some Googling of errors: import distutils and import distutils.util for this to work. – Edward B. May 14 '20 at 20:11
  • Add a `some_string.strip()` to remove excess whitespace or it can throw a ValueError. – Darren Weber Jul 10 '20 at 22:33
  • 2
    If `import distutils.util` fails with _AttributeError: module 'distutils' has no attribute 'util'_, following statement could help: `from distutils.util import strtobool`. It is strange but I met this situation at one. – and1er Nov 25 '20 at 10:23
  • 1
    so much work just to convert to boolean? really? – WestCoastProjects Dec 10 '20 at 14:35
  • 16
    Be aware, that the distutils package is deprecated since python 3.10 and will be removed in version 3.12. – jan-di Nov 07 '21 at 01:25
  • 3
    To expand @jan-di 's comment, `distutils.util.strtobool` is explicitly called out in [PEP 632](https://peps.python.org/pep-0632/) as not getting an equivalent implementation in Python 3.12: > For these functions, and any others not mentioned here, you will need to reimplement the functionality yourself. The legacy documentation can be found at https://docs.python.org/3.9/distutils/apiref.html > > distutils.dir_util.create_tree > distutils.util.change_root > distutils.util.strtobool Unfortunate, as this has been my go-to function for this purpose for a long time. – John Crawford Apr 08 '22 at 15:07
  • 1
    My big issue with the strtobool method is " Raises ValueError if val is anything else." You don't have to have to handling exceptions here. Just have it return false. While this answer is not wrong, there are other solutions that are better in my opinion, like the custom str2bool method that check for a list of values. – Mike Pone Jun 03 '22 at 15:29
  • as of python 3.12 `distutils` is moved from python standard library to python module `setuptools`, the `strtobool` is still there... but only available via `import setuptools._distutils.util`. Note that there is a leading underscore which indicates that code is not meant to be used publicly (i.e. [encapsulation](https://en.wikipedia.org/wiki/Encapsulation_(computer_programming))) ... therefore i can't recommend using `strtobool` in it's new home. – Trevor Boyd Smith Oct 06 '22 at 12:23
  • Too bad [`configparser.ConfigParser.getboolean`](https://docs.python.org/3/library/configparser.html#configparser.ConfigParser.getboolean) can't be reused somehow. Or the [JSON](https://docs.python.org/3/library/json.html) or [TOML](https://docs.python.org/3/library/tomllib.html) parsers, although these are less liberal with their input. – Cristian Ciupitu Mar 15 '23 at 20:28
351
def str2bool(v):
  return v.lower() in ("yes", "true", "t", "1")

Then call it like so:

>>> str2bool("yes")
True
>>> str2bool("no")
False
>>> str2bool("stuff")
False
>>> str2bool("1")
True
>>> str2bool("0")
False

Handling true and false explicitly:

You could also make your function explicitly check against a True list of words and a False list of words. Then if it is in neither list, you could throw an exception.

vvvvv
  • 25,404
  • 19
  • 49
  • 81
Brian R. Bondy
  • 339,232
  • 124
  • 596
  • 636
  • 48
    little enhancement can be made using, **str(v).lower()** instead of **v.lower()**. Then, it can work even it is not string, e.g. 1, 0 – kmonsoor Jan 05 '15 at 14:30
  • RE: handling true/false explicitly, you could also provide a default value if the string isn't matched, much like how true/false command-line prompts work: Continue? (y/N) – Johnus Mar 03 '16 at 03:16
185

The JSON parser is also useful for in general converting strings to reasonable python types.

>>> import json
>>> json.loads("false".lower())
False
>>> json.loads("True".lower())
True
Nam G VU
  • 33,193
  • 69
  • 233
  • 372
Alan Marchiori
  • 1,997
  • 1
  • 11
  • 2
  • 2
    Be careful though, no validation are done that the return type is a boolean. `json.loads("[42]".lower()) -> [42]` – selle Jun 08 '22 at 14:41
  • why is `.lower()` needed? When I don't use it, for example `x = "False"` `j = json.loads(x)`, I get the error `json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)` – Ambassador Kosh Jul 14 '22 at 13:16
  • @AmbassadorKosh because JSON only recognizes literal `true` and `false` values; see https://json-schema.org/understanding-json-schema/reference/boolean.html – Luis Sep 12 '22 at 19:41
  • This one worked like magic! Thanks a lot – Orkhan Shirin Oct 13 '22 at 12:34
129

Since Python 2.6 you can use ast.literal_eval, and it's still available in Python 3.

Evaluate an expression node or a string containing only a Python literal or container display. The string or node provided may only consist of the following Python literal structures: strings, bytes, numbers, tuples, lists, dicts, sets, booleans, None and Ellipsis.

This can be used for evaluating strings containing Python values without the need to parse the values oneself. It is not capable of evaluating arbitrarily complex expressions, for example involving operators or indexing.

This function had been documented as “safe” in the past without defining what that meant. That was misleading. This is specifically designed not to execute Python code, unlike the more general eval(). There is no namespace, no name lookups, or ability to call out. But it is not free from attack: A relatively small input can lead to memory exhaustion or to C stack exhaustion, crashing the process. There is also the possibility for excessive CPU consumption denial of service on some inputs. Calling it on untrusted data is thus not recommended.

Which seems to work, as long as you're sure your strings are going to be either "True" or "False":

>>> ast.literal_eval("True")
True
>>> ast.literal_eval("False")
False
>>> ast.literal_eval("F")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/opt/Python-2.6.1/lib/python2.6/ast.py", line 68, in literal_eval
    return _convert(node_or_string)
  File "/opt/Python-2.6.1/lib/python2.6/ast.py", line 67, in _convert
    raise ValueError('malformed string')
ValueError: malformed string
>>> ast.literal_eval("'False'")
'False'

I wouldn't normally recommend this, but it is completely built-in and could be the right thing depending on your requirements.

Cristian Ciupitu
  • 20,270
  • 7
  • 50
  • 76
Jacob Gabrielson
  • 34,800
  • 15
  • 46
  • 64
  • 2
    Not sure of the general applicability of this solution, but it's very nice, in a general sort of way. +1! – SingleNegationElimination Jul 11 '09 at 21:04
  • 5
    Gaah, that's horrifying! Then again, you _did_ say you don't recommend it, and it _does_ answer the question neatly. Good find! – Vanessa Phipps Dec 17 '13 at 22:19
  • 9
    Unfortunately it doesn't handle this case >>>ast.literal_eval('true') or ast.literal_eval('TRUE') Raises >>> raise ValueError('malformed string') The fix is simple though ast.literal_eval(to_test.title()) – Bhushan May 08 '14 at 03:13
  • Not a great solution to this particular question, but... Wow, literal_eval is damn useful! String to list, dict, ect. – travc Oct 25 '14 at 23:48
  • Does it work on unicodes to? In my Django view I have an incoming value which I want to change to boolean, it is giving a malformed string exception. – praxmon Sep 08 '15 at 05:11
  • Unfortunately title() will capitalize every key in the object such as ast.literal_eval('{"hi": true}'.title()) to {"Hi": True}. Another way is to use `from rest_framework.utils import json` and then `json.loads('{"hi": true}')` – xjlin0 Oct 10 '21 at 20:41
89

WARNING: Do not use the following code unless you actually know what you are doing with it. Please read the attached disclaimers and make sure you trust your inputs as using this on untrusted inputs could destroy your data and/or cost you your job.

If you know the string will be either "True" or "False", you could just use eval(s).

>>> eval("True")
True
>>> eval("False")
False

Only use this if you are sure of the contents of the string though, as it will throw an exception if the string does not contain valid Python, and will also execute code contained in the string.

Joel Croteau
  • 1,682
  • 12
  • 17
  • 20
    that string will come from somewhere. `if eval(os.environ["LOL"]): #might never reach here. Might also charge your company's credit card. ` – nurettin Jan 23 '19 at 16:10
  • 4
    @nurettin, hence my comment about only using it if you're sure of the contents of the string. – Joel Croteau Feb 24 '19 at 16:28
  • 10
    please please please, there are a LOT safer options above, why would you want to use `eval` for a simple string comparison you can never be 100% certain that a piece of code is going to stay the same and behave the same over time but there's a slight chance that you leave the `eval` in there then the disaster soup is ready – slajma Sep 25 '20 at 20:52
  • 2
    This is the correct answer I was googling for. eval("True") = True and eval("False") = False. Simple. I use it to ping a config file for booleans. – Kris M Jan 03 '21 at 14:18
  • 1
    @KrisM, please make sure you trust the source of that config file. Any Python code you put into an `eval` will be executed, so it is a potential entry point for malicious code, or even just badly-formed code to get into your system. – Joel Croteau Jan 26 '22 at 18:41
  • 3
    Part of me says capital letter "WARNING" is in order. On the other hand the other part says if someone is dumb enough to copy-paste the answer without thinking what it really does, they kinda deserved to be hacked – MuhsinFatih May 12 '22 at 23:58
  • @MuhsinFatih, hopefully I have now added a large enough warning. – Joel Croteau Oct 23 '22 at 03:25
  • I almost implemented this (with a suitable check to make sure the value is legit), only to realize that it's case-sensitive. – Ilya Jun 14 '23 at 18:35
27

NOTE: DON'T EVER USE eval() if it takes an input directly or indirectly from the user because it is highly subject to abuse:

eval('os.system(‘rm -rf /’)')

But cheers! Study finds also that eval() is not evil and it is perfectly OK for TRUSTED CODE. You can use it to convert a boolean string such as "False" and "True" to a boolean type.


I would like to share my simple solution: use the eval(). It will convert the string True and False to proper boolean type IF the string is exactly in title format True or False always first letter capital or else the function will raise an error.

e.g.

>>> eval('False')
False

>>> eval('True')
True

Of course for dynamic variable you can simple use the .title() to format the boolean string.

>>> x = 'true'
>>> eval(x.title())
True

This will throw an error.

>>> eval('true')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<string>", line 1, in <module>
NameError: name 'true' is not defined

>>> eval('false')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<string>", line 1, in <module>
NameError: name 'false' is not defined
Neuron
  • 5,141
  • 5
  • 38
  • 59
Shift 'n Tab
  • 8,808
  • 12
  • 73
  • 117
  • 11
    wow, for anyone finding this: do NOT use this for anything else than simple scripts. If you use this in any serious application you will open yourself up to all kinds of unwanted code execution. Imagine a scenario where you parse input from a user and to convert a string to a boolean you use this. In this scenario an attacker can basically do anything that your code does. Don't trust me? Try this: import os eval("os.getcwd()") – Martin Braun Jun 20 '20 at 20:26
  • 2
    @MartinBraun Ah yes study finds that you can execute this `eval('os.system(‘rm -rf /’)')` and it deletes all the files in that directory. However `eval()` are perfectly OK for a trusted code it is not really evil. So I better put a note to be careful. – Shift 'n Tab Jun 21 '20 at 19:48
  • How about `literal_eval`? – Nishant Apr 18 '22 at 11:24
20

This version keeps the semantics of constructors like int(value) and provides an easy way to define acceptable string values.

valid = {'true': True, 't': True, '1': True,
         'false': False, 'f': False, '0': False,
         }

def to_bool(value):
    """Convert string value to boolean."""

    if isinstance(value, bool):
        return value

    if not isinstance(value, basestring):
        raise ValueError('invalid literal for boolean. Not a string.')

    lower_value = value.lower()
    if lower_value in valid:
        return valid[lower_value]
    else:
        raise ValueError('invalid literal for boolean: "%s"' % value)


# Test cases
assert to_bool('true'), '"true" is True' 
assert to_bool('True'), '"True" is True' 
assert to_bool('TRue'), '"TRue" is True' 
assert to_bool('TRUE'), '"TRUE" is True' 
assert to_bool('T'), '"T" is True' 
assert to_bool('t'), '"t" is True' 
assert to_bool('1'), '"1" is True' 
assert to_bool(True), 'True is True' 
assert to_bool(u'true'), 'unicode "true" is True'

assert to_bool('false') is False, '"false" is False' 
assert to_bool('False') is False, '"False" is False' 
assert to_bool('FAlse') is False, '"FAlse" is False' 
assert to_bool('FALSE') is False, '"FALSE" is False' 
assert to_bool('F') is False, '"F" is False' 
assert to_bool('f') is False, '"f" is False' 
assert to_bool('0') is False, '"0" is False' 
assert to_bool(False) is False, 'False is False'
assert to_bool(u'false') is False, 'unicode "false" is False'

# Expect ValueError to be raised for invalid parameter...
try:
    to_bool('')
    to_bool(12)
    to_bool([])
    to_bool('yes')
    to_bool('FOObar')
except ValueError, e:
    pass
  • 6
    Nit: Your last "test case" will error out on the first call and not test the others. Also, it will not fail if an error is *not* raised. – augurar Mar 14 '17 at 07:35
  • 1
    The definition of `valid` should be placed outside the function, or the `dict` will be rebuilt on every call, removing the majority of the performance benefit of using a `dict` in the first place. – ShadowRanger Jul 01 '22 at 01:39
18

There is an elegant solution with pydantic:

import pydantic

>>> pydantic.parse_obj_as(bool, "true")
True

>>> pydantic.parse_obj_as(bool, "off")
False
Yann
  • 3,841
  • 1
  • 22
  • 14
17

you could always do something like

my_string = "false"
val = (my_string == "true")

the bit in parens would evaluate to False. This is just another way to do it without having to do an actual function call.

Neuron
  • 5,141
  • 5
  • 38
  • 59
helloandre
  • 10,541
  • 8
  • 47
  • 64
  • 1
    What is the `val = "false"` line doing on this example? Why is it there? What does it mean? – S.Lott Apr 03 '09 at 20:13
  • this exactly what I was looking for, evaluating an input field from a file and based on the outcome storing a boolean. thank you. – jimh Mar 02 '17 at 00:41
15

Here's is my version. It checks against both positive and negative values lists, raising an exception for unknown values. And it does not receive a string, but any type should do.

def to_bool(value):
    """
       Converts 'something' to boolean. Raises exception for invalid formats
           Possible True  values: 1, True, "1", "TRue", "yes", "y", "t"
           Possible False values: 0, False, None, [], {}, "", "0", "faLse", "no", "n", "f", 0.0, ...
    """
    if str(value).lower() in ("yes", "y", "true",  "t", "1"): return True
    if str(value).lower() in ("no",  "n", "false", "f", "0", "0.0", "", "none", "[]", "{}"): return False
    raise Exception('Invalid value for boolean conversion: ' + str(value))

Sample runs:

>>> to_bool(True)
True
>>> to_bool("tRUe")
True
>>> to_bool("1")
True
>>> to_bool(1)
True
>>> to_bool(2)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 9, in to_bool
Exception: Invalid value for boolean conversion: 2
>>> to_bool([])
False
>>> to_bool({})
False
>>> to_bool(None)
False
>>> to_bool("Wasssaaaaa")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 9, in to_bool
Exception: Invalid value for boolean conversion: Wasssaaaaa
>>>
Petrucio
  • 5,491
  • 1
  • 34
  • 33
  • One could get bitten by this: `to_bool(["hello"])` which should be a perfectly valid call, if `[]` is supported – Rafael T Mar 04 '13 at 00:06
  • 1
    Returns "Exception: Invalid value for boolean conversion: ['hello']", which is expected and documented. In my opinion an empty list was clearly a false, but ['false'] wasn't clearly anything, so I left it out intentionally - that's a feature not a bug. Should be easy to add support for returning true for non-empty lists if that's what you want. – Petrucio Mar 05 '13 at 07:39
  • 1
    shure you documented it. But in real live one would never call `to_bool([])`. Instead he would do something along these lines: `myList=someFunctionThatReturnAList` `if (is_bool(myList)):...´ so one have a list and want to know if this list is None or empty. – Rafael T Mar 05 '13 at 16:12
  • Why not try this: >>> def a2b(arg): ... default = bool(arg) ... if isinstance(arg, str): ... return arg.lower() in ['true', 't', 'yes', 'y', '1'] ... else: ... return default – ThePracticalOne Jun 12 '13 at 19:12
  • 5
    Minor point: you should probably prefer [ValueError](https://docs.python.org/3/library/exceptions.html#ValueError) over a plain Exception. – dshepherd Apr 07 '15 at 14:25
  • @RafaelT Actually, I imagine they would be more likely to do `if my_list:` than `if to_bool(my_list):`. I do tend to agree that trying to support `list` and `dict` is probably a bad idea. I can't actually leverage that support unless I already *know* it is empty because a non-empty one will throw an error, but if I already know that, I don't even need this function. The other asymmetries are a bit iffy, too. The string `'NONE'` is converted to `False` (inconsistent with normal Python), and supporting the `float` `0.0` has a lot of the same problems as `list`/`dict`. – jpmc26 Sep 21 '15 at 22:40
13

A cool, simple trick (based on what @Alan Marchiori posted), but using yaml:

import yaml

parsed = yaml.load("true")
print bool(parsed)

If this is too wide, it can be refined by testing the type result. If the yaml-returned type is a str, then it can't be cast to any other type (that I can think of anyway), so you could handle that separately, or just let it be true.

I won't make any guesses at speed, but since I am working with yaml data under Qt gui anyway, this has a nice symmetry.

Neuron
  • 5,141
  • 5
  • 38
  • 59
Rafe
  • 1,937
  • 22
  • 31
10

A dict (really, a defaultdict) gives you a pretty easy way to do this trick:

from collections import defaultdict
bool_mapping = defaultdict(bool) # Will give you False for non-found values
for val in ['True', 'yes', ...]:
    bool_mapping[val] = True

print(bool_mapping['True']) # True
print(bool_mapping['kitten']) # False

If you only want to map known values and throw an exception otherwise:

truthy_strings = ['True', 'yes']  # ... and so on
falsy_strings = ['False', 'no']   # ... and so on

bool_mapping = {}
for v in truthy_strings:
    bool_mapping[v] = True
for v in falsy_strings:
    bool_mapping[v] = False

If you want to be too clever by half, you can shorten this with itertools

from itertools import chain, repeat

bool_mapping = dict(chain(zip(truthy_strings, repeat(True)), zip(falsy_strings, repeat(False))))

This is probably dumb but itertools tricks are vaguely amusing.

Nate
  • 4,561
  • 2
  • 34
  • 44
9

I don't agree with any solution here, as they are too permissive. This is not normally what you want when parsing a string.

So here the solution I'm using:

def to_bool(bool_str):
    """Parse the string and return the boolean value encoded or raise an exception"""
    if isinstance(bool_str, basestring) and bool_str: 
        if bool_str.lower() in ['true', 't', '1']: return True
        elif bool_str.lower() in ['false', 'f', '0']: return False

    #if here we couldn't parse it
    raise ValueError("%s is no recognized as a boolean value" % bool_str)

And the results:

>>> [to_bool(v) for v in ['true','t','1','F','FALSE','0']]
[True, True, True, False, False, False]
>>> to_bool("")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 8, in to_bool
ValueError: '' is no recognized as a boolean value

Just to be clear because it looks as if my answer offended somebody somehow:

The point is that you don't want to test for only one value and assume the other. I don't think you always want to map Absolutely everything to the non parsed value. That produces error prone code.

So, if you know what you want code it in.

estani
  • 24,254
  • 2
  • 93
  • 76
  • 3
    I think you're missing the point: the point of the answers was to demonstrate the general principle, not to tell person who asked the question exactly how they should do it. The person who asked the question originally was overthinking what's actually a simple problem. – Keith Gaughan Nov 26 '12 at 10:37
  • 9
    @Keith I disagree. The point is answering the question as it is asked. – estani Nov 26 '12 at 10:45
  • 2
    The question asked was how to convert a string to a boolean. That was the question I answered. I have no idea what's considered a valid boolean string for the original poster, and nor do you. That's why it's more important to demonstrate the general principle than give the poster the full answer. The original poster didn't need everything spelled out to them: all they needed was for the general principle to be demonstrated. From that, anybody competent will get to your answer. – Keith Gaughan Nov 26 '12 at 10:53
  • 1
    @Keith not sure what this is all about but the point is building knowledge. I'm not "judging" your answer, I fell no other answer was "complete" as they missed the fact that parsing a boolean has 3 outcomes, true, false or unparsable. That's all. (I will just pretend I never read the last line of your comment) – estani Nov 28 '12 at 16:38
  • Do you need the `isinstance` check? I would think that duck typing suffices: anything with method `.lower()` which compares equal to one of the given strings is almost certainly some kind of string. – dshepherd Apr 07 '15 at 14:29
  • 3
    @dshepherd the isinstance is there to be sure I'm parsing what I expect. I'm parsing strings so a method car_race.lower() that by chance returns '1' shouldn't return true, it should throw a ValueError. But it might suffice in other cases. – estani Apr 07 '15 at 16:42
  • 1
    The `elif` can be (and should be IMHO) simplified to `if`. Not sure if there's a PEP style guide on this, but using `if` correctly implies that your code is doing an `assert` style return, for lack of a better phrase. `elif` here implies you need it to be `elif`, when you don't. – CivFan Apr 10 '15 at 20:14
  • 2
    @CivFan interesting point. Though I tried it, and it didn't read so nice (to me). `elif` is redundant because of the return word, but it gives you more information without having to scan for `return`. But that's only me, if there's a PEP style violation, I would change it though. Without any other constrain, we should always go for readability (and standards do that). Thanks for the heads up and interesting comment! – estani Apr 12 '15 at 13:03
8

By using below simple logic you can convert a string say a = 'true' or 'false', to boolean.

a = a.lower() == 'true'

if a == 'true' then this will set a=True and if a == 'false' then a=False.

Neuron
  • 5,141
  • 5
  • 38
  • 59
Sagar Deshmukh
  • 384
  • 3
  • 4
6

Yet another option

from ansible.module_utils.parsing.convert_bool import boolean
boolean('no')
# False
boolean('yEs')
# True
boolean('true')
# True
Matt Kucia
  • 1,026
  • 12
  • 17
6

I use

# function
def to_bool(x):
    return x in ("True", "true", True)

# test cases
[[x, to_bool(x)] for x in [True, "True", "true", False, "False", "false", None, 1, 0, -1, 123]]
"""
Result:
[[True, True],
 ['True', True],
 ['true', True],
 [False, False],
 ['False', False],
 ['false', False],
 [None, False],
 [1, True],
 [0, False],
 [-1, False],
 [123, False]]
"""
Neuron
  • 5,141
  • 5
  • 38
  • 59
MrHIDEn
  • 1,723
  • 1
  • 25
  • 23
5

You probably already have a solution but for others who are looking for a method to convert a value to a boolean value using "standard" false values including None, [], {}, and "" in addition to false, no , and 0.

def toBoolean( val ):
    """ 
    Get the boolean value of the provided input.

        If the value is a boolean return the value.
        Otherwise check to see if the value is in 
        ["false", "f", "no", "n", "none", "0", "[]", "{}", "" ]
        and returns True if value is not in the list
    """

    if val is True or val is False:
        return val

    falseItems = ["false", "f", "no", "n", "none", "0", "[]", "{}", "" ]

    return not str( val ).strip().lower() in falseItems
Chris McMillan
  • 1,954
  • 1
  • 13
  • 5
5

If you know that your input will be either "True" or something else, then why not use:

def bool_convert(s):
    return s == "True"
Neuron
  • 5,141
  • 5
  • 38
  • 59
Daniel van Flymen
  • 10,931
  • 4
  • 24
  • 39
5

If you have control over the entity that's returning true/false, one option is to have it return 1/0 instead of true/false, then:

boolean_response = bool(int(response))

The extra cast to int handles responses from a network, which are always string.

Update 2021: "which are always string" -- this is a naive observation. It depends on the serialization protocol used by the library. Default serialization of high-level libraries (the ones used by most web devs) is typically to convert to string before being serialized to bytes. And then on the other side, it's deserialized from bytes to string, so you've lost any type information.

Sam Malayek
  • 3,595
  • 3
  • 30
  • 46
4

The usual rule for casting to a bool is that a few special literals (False, 0, 0.0, (), [], {}) are false and then everything else is true, so I recommend the following:

def boolify(val):
    if (isinstance(val, basestring) and bool(val)):
        return not val in ('False', '0', '0.0')
    else:
        return bool(val)
Carl G
  • 17,394
  • 14
  • 91
  • 115
4

If you like me just need boolean from variable which is string. You can use distils as mentioned by @jzwiener. However I could not import and use the module as he suggested.

Instead I end up using it this way on python3.7

distutils string to bool in python

from distutils import util # to handle str to bool conversion
enable_deletion = 'False'
enable_deletion = bool(util.strtobool(enable_deletion))

distutils is part of the python std lib, so no need to install anything, which is great!

Neuron
  • 5,141
  • 5
  • 38
  • 59
Gunay Anach
  • 1,193
  • 1
  • 13
  • 19
4

You can also evaluate any string literal :

import ast
ast.literal_eval('True')  # True
type(ast.literal_eval('True'))  # <class 'bool'>


ls = '[1, 2, 3]'
ast.literal_eval(ls)  # [1, 2, 3]
type(ast.literal_eval(ls))  # <class 'list'>
Nomi
  • 185
  • 2
  • 13
3

This is the version I wrote. Combines several of the other solutions into one.

def to_bool(value):
    """
    Converts 'something' to boolean. Raises exception if it gets a string it doesn't handle.
    Case is ignored for strings. These string values are handled:
      True: 'True', "1", "TRue", "yes", "y", "t"
      False: "", "0", "faLse", "no", "n", "f"
    Non-string values are passed to bool.
    """
    if type(value) == type(''):
        if value.lower() in ("yes", "y", "true",  "t", "1"):
            return True
        if value.lower() in ("no",  "n", "false", "f", "0", ""):
            return False
        raise Exception('Invalid value for boolean conversion: ' + value)
    return bool(value)

If it gets a string it expects specific values, otherwise raises an Exception. If it doesn't get a string, just lets the bool constructor figure it out. Tested these cases:

test_cases = [
    ('true', True),
    ('t', True),
    ('yes', True),
    ('y', True),
    ('1', True),
    ('false', False),
    ('f', False),
    ('no', False),
    ('n', False),
    ('0', False),
    ('', False),
    (1, True),
    (0, False),
    (1.0, True),
    (0.0, False),
    ([], False),
    ({}, False),
    ((), False),
    ([1], True),
    ({1:2}, True),
    ((1,), True),
    (None, False),
    (object(), True),
    ]
Tom Ekberg
  • 2,133
  • 1
  • 13
  • 8
3

In python version 3.10 you could do something like this;

def stringToBool(string: str) -> bool:
    match(string.lower()):
        case 'true':
            return True
        case 'false':
            return False

The match-statement is equivalent to switch in C++.

2

I completely agree with the solution of @Jacob\ Gabrielson but the thing is ast.literal_eval only work with string value of True and False not with true or false. So you just have to use .title() for it to work

import ast
ast.literal_eval("false".title())
# or
ast.literal_eval("False".title())
Anand Tripathi
  • 14,556
  • 1
  • 47
  • 52
  • does not solve the problem that the string might be "0". ```>>> type(ast.literal_eval("0".title())) ``` – sagi Mar 31 '22 at 06:19
2

Use this solution:

def to_bool(value) -> bool:
    if value == 'true':
        return True
    elif value == 'True':
        return True
    elif value == 'false':
        return False
    elif value == 'False':
        return False
    elif value == 0:
        return False
    elif value == 1:
        return True
    else:
        raise ValueError("Value was not recognized as a valid Boolean.")
Neuron
  • 5,141
  • 5
  • 38
  • 59
srburton
  • 349
  • 3
  • 8
1

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)
Ron E
  • 2,214
  • 2
  • 16
  • 14
1

Use package str2bool pip install str2bool

Headmaster
  • 2,008
  • 4
  • 24
  • 51
1

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.

ARHAM RUMI
  • 441
  • 5
  • 11
1

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

RE_Specto
  • 51
  • 3
1

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.

ely
  • 74,674
  • 34
  • 147
  • 228
0

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.

SingleNegationElimination
  • 151,563
  • 33
  • 264
  • 304
0

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
Neuron
  • 5,141
  • 5
  • 38
  • 59
Clayton Rabenda
  • 5,229
  • 2
  • 19
  • 16
0
def str2bool(str):
  if isinstance(str, basestring) and str.lower() in ['0','false','no']:
    return False
  else:
    return bool(str)

idea: check if you want the string to be evaluated to False; otherwise bool() returns True for any non-empty string.

xvga
  • 591
  • 1
  • 9
  • 15
0

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
Rcynic
  • 392
  • 3
  • 10
0

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)

# ...
Ouss
  • 2,912
  • 2
  • 25
  • 45
0

Here's something I threw together to evaluate the truthiness of a string:

def as_bool(val):
 if val:
  try:
   if not int(val): val=False
  except: pass
  try:
   if val.lower()=="false": val=False
  except: pass
 return bool(val)

more-or-less same results as using eval but safer.

tylerl
  • 30,197
  • 13
  • 80
  • 113
-8

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'>
elPastor
  • 8,435
  • 11
  • 53
  • 81
  • 5
    What happens, if the string contains `#\nshutil.rmtree('/someImportantDirectory')`? (Don't try it!) – mastov Nov 28 '17 at 15:54
  • @mastov - ridiculous downvote. Obviously if you don't have control of the incoming string, you need to put precautions in place, as you would with any code. But if you do control the workflow, this is a simple solution that works. Don't confuse a solution that isn't perfect in every way with a bad answer. – elPastor Nov 28 '17 at 15:55
  • 1
    Apart from not mentioning the dangers (which already makes this a bad answer): You are proposing to sanitize the input beforehand? That's going to kill the simplicity of this method, which was its main plus. – mastov Nov 28 '17 at 16:04
  • 6
    Using `eval` for something this simple is just *asking* for a vulnerability. – mastov Nov 28 '17 at 16:04
  • Not all code is exposed to the general public, and thus not susceptible to the issues that seem to frighten you so much. A simple comment that this answer should include a warning would suffice. – elPastor Nov 28 '17 at 16:09
  • 1
    Not all code. But especially code that converts strings to other types usually *is* out of your control. Often you might not even realize it. You might say: "It's my database (or config file), it's part of my system, under my control." Then you give some other module access to a database because: "What's the harm? It's only some tables with strings." But with `eval` those strings might help someone to take over the whole system. – mastov Nov 28 '17 at 16:15
  • @pshep123 The security part isn't even the only concern. Using eval to convert a string to a boolean is just beyond bad practice. There are proper ways to do things, which definitely don't include using the jackhammer that is eval to hammer in a nail. The (non ridiculous) downvote isn't because your answer doesn't work - it's because it's a bad answer, even if it does work. – Overcode Apr 08 '18 at 22:13
  • @Overcode, to say anything "is just beyond bad practice" and not giving a reason (especially when ruling out security issue) is beyond bad practice. Help us learn why things are bad practice instead of just saying that they are. – elPastor Apr 08 '18 at 22:16
  • @pshep123 If you are really interested, a quick google of "why is eval bad" should give you plenty to read. Code injection violates the Fundamental Principle of Software. On top of that, eval is slower (you force the interpreter to revisit the precompiler), harder to debug, displays bad code design, etc. And just like in this situation, there's almost always just a better way to do it that fits good code design/practice. – Overcode Apr 08 '18 at 22:40
  • Good to know. Thanks. – elPastor Apr 08 '18 at 22:41