python中字符串的转换和求值
如何从包含以下内容的文本文件中获取Python列表python中字符串的转换和求值,python,string,types,Python,String,Types,如何从包含以下内容的文本文件中获取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方面有困难 假定要转换的字符串
'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方面有困难
假定要转换的字符串的用户输入列表是安全的。警告:使用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,您可以使用,这可能比普通评估的危险性要小一些:
另一种选择是使用@poke,因为literal_eval不理解“2*3”
最后,即使是像“2**2**2**2**2**2**2**2**2”这样的安全表达式也可能导致服务器停机。怎么样:
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]
让我们认真对待避免危险评估>:
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很容易理解。当您进行解析时,会得到一个模块。模块内有一条语句。其中最有可能的是丢弃代码,这意味着它在任何地方都没有被使用
如果不是丢弃代码,我们假设它是一个字符串。首先,这有可能防止eval产生任何危险的副作用。有人在这里证明我错了——用废弃代码包装一个危险的表达式
这是表达式的核心部分——从这里我假设任何普通字符串都将在AST中显示为名称。任何不是名字的东西都可能是数字或数学运算
我认为在这一点上,eval应该是安全的,如果表达式是真正的数学表达式,这是必要的。您是只想转换字符串和数字,还是希望对任何Python对象进行eval?您如何确定哪些字符串保持为字符串,哪些内容得到计算?也就是说,为什么“400+2”会成为一个被评估的数字,你是如何决定的无论如何,您需要为此编写一些较小的解析器来检测您想要对输入做什么。一旦你做到了这一点,根据你的决定评估输入应该不会有问题。目前的问题有点太宽泛了。从你所说的问题来看,我同意poke的观点,它有点宽泛,你应该定义你想对每个案例的输入做什么。目前,它似乎正在向循环/迭代器中的正则表达式方向发展。这个列表中的输入信息是否详尽无遗?您不断地更改输入信息,直到您不再清楚您要做什么。请明确你想做什么;不仅仅是你的例子的结果应该做什么,还有输入的实际情况。很抱歉多次专门讨论这个问题。现在应该没问题了。在编写正则表达式之前,实际上不需要对数学进行评估。你可以声明一个看起来像数学的表达式可能是一个数字。这种近似比使用eval要安全得多,在我看来,这很值得权衡。@kojiro:那很好,但是你如何将“400+2”转换为402呢?啊,很好,OP改变了我的问题。也许我一开始就误解了。我以为OP是在要求对类型进行解释。添加一条注释“在这里要非常小心!!!”并没有任何帮助。一旦对用户输入使用eval,您就已经丢失了,不能再小心了。@poke:True。尽管如此,我还是留下了评论,这样如果OP使用该解决方案并将其复制粘贴到其他地方,就会清楚地提醒您一个非常危险的方法调用。我很想知道只有数字和基本运算符最危险的表达式是什么。eval不会容忍\x00,因此结果将是:['hallo','hallo\n','\x00*1',100402]与user1753919相同的注释['hallo','impOrt shutil;shutil.rmtree/home/user','400+2']有一个拼写错误,使它更安全。你明白了。@wolle先生我复制粘贴了。。。结果实际上是\x00,而不是\x00*1。您可以检查它…您不应该在没有某种检查的情况下调用eval。OP需要的信息不仅仅是数字或字符串。尽管如此,你的方法还是很有趣的。有些犹豫地更新了。鉴于我对这个问题的新理解,我认为eval是无法避免的。即使我拆开AST并执行它,结果基本上是eval。你可以像我一样编写自己的表达式计算器。那么你在问题的评估方面是完全安全的,我仍然认为检测部分是困难的/不清楚的。似乎可以用括号很容易地击败这一点。我必须更加努力…
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]