如何从包含以下内容的文本文件中获取Python列表?
'hallo'
'hallo\n'
'\x00' * 1
100
'400 + 2'
400 + 2
例如:
ll = ["hallo", "hallo\n", "\x00", 100, 402, 402]
类型:
[string, string, string, int, int, int]
意味着,python理解为int
的每个字符串都应该来自int
类型。
我尝试使用eval
,但\n
和\x00
有问题。
假设用户输入(要转换的字符串列表)是安全的。
答案 0 :(得分:3)
警告:使用eval
为dangerous。要非常小心,或者更好的是,找不到替代品。
话虽这么说,你可以定义一个正则表达式来检查字符串是否像eval
那样。例如,任何只有数字,空格和数学运算符的东西都可以被认为是安全的:
import re
l = ['hallo', 'hallo\n', '\x00' * 1, '100', 100, '400 + 2', '400 + - ', 400 + 2]
def string_or_expression(something):
if isinstance(something, str):
expression = re.compile('\A[\d\.\-\+\*\/ ]+\Z')
if expression.match(something):
try:
return eval(something)
except:
return something
return something
print([string_or_expression(s) for s in l])
# ['hallo', 'hallo\n', '\x00', 100, 100, 402, '400 + - ', 402]
使用Python3,您可能会使用ast.literal_eval
,这可能比普通的eval
稍微危险一点:
import re
import ast
l = ['hallo', 'hallo\n', '\x00' * 1, '100', 100, '400 + 2', '400 + - ', 400 + 2]
def string_or_expression(something):
if isinstance(something,str):
expression = re.compile('\A[\d\.\-\+\*\/ ]+\Z')
if expression.match(something):
try:
return ast.literal_eval(something)
except:
return something
return something
print([string_or_expression(s) for s in l])
# ['hallo', 'hallo\n', '\x00', 100, 100, 402, '400 + - ', 402]
另一个替代方案是使用@ poke "expression evaluation algorithm",因为literal_eval
无法理解'2 * 3'
。
最后,即使像'2**2**2**2**2**2**2**2**2**2'
这样的“安全”表达式也可能会导致服务器崩溃。
答案 1 :(得分:0)
怎么样:
def try_eval(x):
try:
res=eval(x)
except:
res=x
return res
[try_eval(x) for x in l]
输出:
['hallo', 'hallo\n', '\x00', 100, 402]
答案 2 :(得分:0)
让我们认真考虑避免危险的评估>:)
import compiler
def is_math(expr):
"""Return True if the expression smells mathematical."""
try:
module = compiler.parse(expr)
stmt, = module.getChildNodes()
discard, = stmt.getChildNodes()
code, = discard.getChildNodes()
return not isinstance(code, compiler.ast.Name)
except ValueError:
return False
except TypeError:
return False
t = [eval(s) if is_math(s) else s for s in l]
是的,我在这里做了几个假设,但你可以根据自己的需要严格修改它们。 AST非常容易理解。当您执行parse
时,您将获得一个模块。模块内部是一个声明。在里面(最有可能)丢弃代码(这意味着它不会在任何地方使用)。
如果它不是丢弃代码,我们假设它是一个字符串。首先,这可能会防止eval产生任何危险的副作用。 (有人在这里证明我错了 - 在丢弃代码中包含一个危险的表达。)
里面是你表达的内容 - 从那里我假设任何一个普通字符串看起来都是AST中的一个名字。任何不是名字的东西都可能是数字或数学运算。
我认为 eval在这一点上应该是安全的,如果表达式真的是数学,这是必要的。