Estou lendo um True - False
valor de um arquivo e preciso convertê-lo em booleano. Atualmente, ele sempre o converte em True
mesmo se o valor for definido como False
.
Aqui está um exemplo MWE
do que estou tentando fazer:
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'
O file.dat
arquivo consiste basicamente em uma única string com o valor True
ou False
escrito dentro. O arranjo parece muito complicado porque este é um exemplo mínimo de um código muito maior e é assim que eu leio os parâmetros nele.
Por que está flag
sempre convertendo para True
?
Respostas:
bool('True')
ebool('False')
sempre retornaTrue
porque as strings 'True' e 'False' não estão vazias.Para citar um grande homem (e a documentação do Python ):
A
bool
função interna usa o procedimento de teste de verdade padrão. É por isso que você sempre consegueTrue
.Para converter uma string em booleano, você precisa fazer algo assim:
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
fonte
ValueError
fazendoraise ValueError("Cannot covert {} to a bool".format(s))
.ast
? Faz parte da biblioteca padrão, portanto, não é realmente extra.bool
simplesmente não converte as stringsTrue
eFalse
para os valores booleanosTrue
eFalse
? Parece ser um comportamento inconsistente com o queint
faz. Eu apenas estou genuinamente curioso por que meu raciocínio está errado e por que a outra opção foi a decisão.você pode usar
distutils.util.strtobool
>>> from distutils.util import strtobool >>> strtobool('True') 1 >>> strtobool('False') 0
True
Os valores sãoy
,yes
,t
,true
,on
e1
;False
Os valores sãon
,no
,f
,false
,off
e0
. AumentaValueError
se val for qualquer outra coisa.fonte
bool(strtobool(my_string))
para converter a saída como uma variável booleana True / Falsestrtobool()
não retorna, de fato, umbool
Use
ast.literal_eval
:>>> import ast >>> ast.literal_eval('True') True >>> ast.literal_eval('False') False
Strings não vazias são sempre True em Python.
Relacionado: Teste de Valor da Verdade
Se NumPy for uma opção, então:
>>> 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)
fonte
bool
simplesmente não converte as stringsTrue
eFalse
para os valores booleanosTrue
eFalse
? Parece ser um comportamento inconsistente com o queint
faz. Eu apenas estou genuinamente curioso por que meu raciocínio está errado e por que a outra opção foi a decisão.A solução mais limpa que já vi é:
from distutils.util import strtobool def string_to_bool(string): return bool(strtobool(str(string)))
Claro, ele requer uma importação, mas tem tratamento de erros adequado e requer muito pouco código para ser escrito (e testado).
fonte
Não estou sugerindo que esta seja a melhor resposta, apenas uma alternativa, mas você também pode fazer algo como:
flag = reader[0] == "True"
flag será
True
id reader [0] é "True", caso contrário, seráFalse
.fonte
Atualmente, está avaliando para
True
porque a variável tem um valor. Há um bom exemplo encontrado aqui do que acontece quando você avalia tipos arbitrários como booleanos.Resumindo, o que você quer fazer é isolar a string
'True'
ou'False'
e executáeval
-la.>>> eval('True') True >>> eval('False') False
fonte
eval()
. Na minha opinião, deve ser removido da linguagem.eval()
dados brutos de um arquivo, isso significa que qualquer pessoa com acesso de gravação a esse arquivo pode executar o código no mesmo nível de permissão do seu script.eval('false')
,eval('FALSE')
haverá um erro.Você pode usar dict para converter string em booleano. Altere esta linha
flag = bool(reader[0])
para:flag = {'True': True, 'False': False}.get(reader[0], False) # default is False
fonte
Se você quiser não diferenciar maiúsculas de minúsculas, pode apenas fazer:
b = True if bool_str.lower() == 'true' else False
Exemplo de uso:
>>> 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
fonte
pip install str2bool
>>> from str2bool import str2bool >>> str2bool('Yes') True >>> str2bool('FaLsE') False
fonte
Você pode fazer com
json
.In [124]: import json In [125]: json.loads('false') Out[125]: False In [126]: json.loads('true') Out[126]: True
fonte
Apenas para acrescentar que se o seu valor de verdade pode variar, por exemplo, se for uma entrada de diferentes linguagens de programação ou de diferentes tipos, um método mais robusto seria:
flag = value in ['True','true',1,'T','t','1'] # this can be as long as you want to support
E uma variante de maior desempenho seria (set lookup is O (1)):
TRUTHS = set(['True','true',1,'T','t','1']) flag = value in truths
fonte
Se seus dados forem da JSON, você pode fazer isso
fonte
Se você precisa de uma maneira rápida de converter strings em bools (que funcionam com a maioria das strings), tente.
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
fonte
Usando dicts para converter "True" em True:
def str_to_bool(s: str): status = {"True": True, "False": False} try: return status[s] except KeyError as e: #logging
fonte