python中字符串的转换和评估

时间:2017-04-04 20:51:48

标签: 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有问题。

假设用户输入(要转换的字符串列表)是安全的。

3 个答案:

答案 0 :(得分:3)

警告:使用evaldangerous。要非常小心,或者更好的是,找不到替代品。

话虽这么说,你可以定义一个正则表达式来检查字符串是否像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在这一点上应该是安全的,如果表达式真的是数学,这是必要的。