如何提取Python脚本中的变量而不执行它?

chy5wohz  于 2023-01-22  发布在  Python
关注(0)|答案(1)|浏览(117)

在某些情况下,从Python脚本(可能来自不受信任的源)读取数据并从中提取值非常有用。
尽管在大多数情况下,XML/JSON/YAML/TOML这样的格式更适合,但有时候这样做是有用的。
如何在不执行Python脚本的情况下从脚本中提取变量名和值?

  • (假设值构造不包含创建它们的代码执行)*
mspsb9vt

mspsb9vt1#

这可以通过Python的ast模块来实现:
此示例函数从文件中读取单个命名变量。
当然,这要求变量可以使用ast.literal_eval()进行求值。

def safe_eval_var_from_file(mod_path, variable, default=None, *, raise_exception=False):
    import ast
    ModuleType = type(ast)
    with open(mod_path, "r", encoding='UTF-8') as file_mod:
        data = file_mod.read()

    try:
        ast_data = ast.parse(data, filename=mod_path)
    except Exception as ex:
        if raise_exception:
            raise
        print("AST error ({!r}), {!r}, {!r}".format(ex, mod_path))
        ast_data = None

    if ast_data is not None:
        for body in ast_data.body:
            if body.__class__ == ast.Assign:
                if len(body.targets) == 1:
                    if getattr(body.targets[0], "id", "") == variable:
                        try:
                            return ast.literal_eval(body.value)
                        except Exception as ex:
                            if raise_exception:
                                raise
                            print("AST error ({!r}) {!r} for {!r}".format(
                                ex, variable, mod_path,
                            ))
    return default

# Example use, read from ourself :)
that_variable = safe_eval_var_from_file(__file__, "this_variable")
this_variable = {"Hello": 1.5, b'World': [1, 2, 3], "this is": {'a set'}}
assert(this_variable == that_variable)

相关问题