Converte il valore Vero / Falso letto dal file in booleano


88

Sto leggendo un True - Falsevalore da un file e devo convertirlo in booleano. Attualmente lo converte sempre in Trueanche se il valore è impostato su False.

Ecco MWEcosa sto cercando di fare:

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'

Il file.datfile è costituito fondamentalmente da una singola stringa con il valore Trueo Falsescritto all'interno. La disposizione sembra molto contorta perché questo è un esempio minimo di un codice molto più grande ed è così che leggo i parametri in esso.

Perché si flagconverte sempre in True?


1
pip install str2bool
Symon

Risposte:


101

bool('True')e bool('False')restituisce sempre Trueperché le stringhe "True" e "False" non sono vuote.

Per citare un grande uomo (e la documentazione di Python ):

5.1. Test del valore di verità

Qualsiasi oggetto può essere testato per il valore di verità, per l'uso in una condizione if o while o come operando delle operazioni booleane di seguito. I seguenti valori sono considerati falsi:

  • ...
  • zero di alcun tipo numerico, ad esempio 0, 0L, 0.0, 0j.
  • qualsiasi sequenza vuota, per esempio '', (), [].
  • ...

Tutti gli altri valori sono considerati veri, quindi gli oggetti di molti tipi sono sempre veri.

La boolfunzione incorporata utilizza la procedura standard di verifica della verità. Ecco perché stai sempre True.

Per convertire una stringa in booleana devi fare qualcosa del genere:

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

24
Potresti renderlo un "eroico" ValueErrorfacendo raise ValueError("Cannot covert {} to a bool".format(s)).
SethMMorton

Selezionando questo poiché non utilizza pacchetti aggiuntivi. Grazie ragazzi!
Gabriel

1
Cosa c'è di sbagliato in "pacchetti extra"? Ti riferisci ast? Fa parte della libreria standard, quindi non è davvero extra.
SethMMorton

4
potrebbe essere una domanda sciocca, ma perché boolsemplicemente non converte le stringhe Truee Falsenei valori booleani Truee False? Sembra essere un comportamento incoerente da quello che intfa. Sono solo sinceramente curioso del motivo per cui il mio ragionamento è sbagliato e perché l'altra opzione è stata la decisione.
Charlie Parker

1
Ogni volta che si confrontano le stringhe, mi piace appiattire il caso, (dove applicabile). per esempio userei: if s.upper () == 'TRUE': return True elif s.upper () == 'FALSE' return False
Bill Kidd

75

Puoi usare distutils.util.strtobool

>>> from distutils.util import strtobool

>>> strtobool('True')
1
>>> strtobool('False')
0

TrueI valori sono y, yes, t, true, one 1; Falsevalori sono n, no, f, false, offe 0. Solleva ValueErrorse val è qualcos'altro.


23
Ancora meglio, eseguire il bool(strtobool(my_string))cast dell'output come variabile booleana True / False
AlexG

11
@AlexG è pazzesco che una funzione chiamata strtobool()non restituisca, in effetti, unbool
dericke

61

Usa ast.literal_eval:

>>> import ast
>>> ast.literal_eval('True')
True
>>> ast.literal_eval('False')
False

Perché flag si converte sempre in True?

Le stringhe non vuote sono sempre True in Python.

Correlati: Test del valore di verità


Se NumPy è un'opzione, allora:

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

potrebbe essere una domanda sciocca, ma perché boolsemplicemente non converte le stringhe Truee Falsenei valori booleani Truee False? Sembra essere un comportamento incoerente da quello che intfa. Sono solo sinceramente curioso del motivo per cui il mio ragionamento è sbagliato e perché l'altra opzione è stata la decisione.
Charlie Parker

2
ast.literal_eval ('false') genera un'eccezione, che credo la renda meno desiderabile
Chris

@Chris Puoi sempre avvolgerlo attorno a try, tranne che in una funzione personalizzata invece di usarlo direttamente in quel momento.
Ashwini Chaudhary

@HewwoCraziness Analizza solo le espressioni, non alcun codice casuale.
Ashwini Chaudhary

16

La soluzione più pulita che ho visto è:

from distutils.util import strtobool
def string_to_bool(string):
    return bool(strtobool(str(string)))

Certo, richiede un'importazione, ma ha una corretta gestione degli errori e richiede pochissimo codice da scrivere (e testare).


Questo non funziona a meno che il valore di input non possa essere effettivamente un booleano, altrimenti sembra che generi un errore di valore. L'unica cosa a cui riesco a pensare è aggiungere una prova / tranne alla tua funzione e al ValueErrorritorno false.
Ari

13

Non mi è stata suggerita questa come la migliore risposta, solo un'alternativa, ma puoi anche fare qualcosa come:

flag = reader[0] == "True"

flag sarà Trueid reader [0] è "True", altrimenti lo sarà False.


10

Attualmente sta valutando Trueperché la variabile ha un valore. C'è un buon esempio di ciò che accade quando si valutano tipi arbitrari come booleani.

In breve, quello che vuoi fare è isolare la stringa 'True'o 'False'ed eseguirci evalsopra.

>>> eval('True')
True
>>> eval('False')
False

4
@samyi È pericoloso utilizzare il metodo eval. stackoverflow.com/questions/1832940/…
M07

1
Cordiali saluti. Questa è un'idea terribile e non dovresti mai usarla eval(). A mio parere, dovrebbe essere rimosso dalla lingua.
Nostalg.io

Questo è MOLTO MOLTO MALE perché è un difetto di sicurezza. Se usi eval()dati grezzi da un file, significa che chiunque abbia accesso in scrittura a quel file può eseguire codice allo stesso livello di autorizzazioni del tuo script.
Keith Ripley

Inoltre, se i valori non hanno l'esatta ortografia di Python, ad esempio eval('false'), eval('FALSE')verrà visualizzato un errore.
kev

5

Puoi usare dict per convertire la stringa in booleano. Cambia questa riga flag = bool(reader[0])in:

flag = {'True': True, 'False': False}.get(reader[0], False) # default is False

5

Se vuoi essere insensibile al maiuscolo / minuscolo, puoi semplicemente fare:

b = True if bool_str.lower() == 'true' else False

Utilizzo di esempio:

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

3

pip installa str2bool

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

2

Puoi fare con json.

In [124]: import json

In [125]: json.loads('false')
Out[125]: False

In [126]: json.loads('true')
Out[126]: True

2

Solo per aggiungere che se il tuo valore di verità può variare, ad esempio se è un input da diversi linguaggi di programmazione o da diversi tipi, un metodo più robusto sarebbe:

flag = value in ['True','true',1,'T','t','1'] # this can be as long as you want to support

E una variante più performante sarebbe (set lookup è O (1)):

TRUTHS = set(['True','true',1,'T','t','1'])
flag = value in truths


0

Se hai bisogno di un modo rapido per convertire le stringhe in bool (che funziona con la maggior parte delle stringhe) prova.

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


0

Utilizzo di dict per convertire "True" in True:

def str_to_bool(s: str):
    status = {"True": True,
                "False": False}
    try:
        return status[s]
    except KeyError as e:
        #logging
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.