简体   繁体   English

如何覆盖 python 脚本文件中的一些分配?

[英]How to overwrite some assignments in a python script file?

I have a python file describing a set of objects/variables.我有一个描述一组对象/变量的 python 文件。 Example with file.py :file.py

a = 5
b = a+1

And I would like to import the file's content with the ability to overwrite the value of some variables: parse_with_overwrite(file.py, {"a": 6}) would make the current locals() contain a=6 and b=7 .而且我想导入文件内容并能够覆盖某些变量的值: parse_with_overwrite(file.py, {"a": 6})将使当前的locals()包含a=6b=7

Of course, like any python file, not all variables are described in one single line… so it's not possible to split each line on the = sign.当然,就像任何 python 文件一样,并非所有变量都在一行中描述……所以不可能在=符号上分割每一行。 Moreover, order of the variables matters since some variables may depend on other.此外,变量的顺序很重要,因为一些变量可能依赖于其他变量。

Is there any builtin or library that could help me achieve this?是否有任何内置或库可以帮助我实现这一目标?

Currently, I get the content of file.py with:目前,我通过以下方式获取file.py的内容:

context = {}
with open("file.py", "r") as f:
    # the magic should occur here :-)
    exec(f.read(), None, context)

A safe way to do it is to use the ast module to parse the file.一种安全的方法是使用ast 模块来解析文件。 You can then modify the nodes in the ast and finally compile it.然后可以修改ast中的节点,最后编译。

Here is a start:这是一个开始:

import ast

def replace_top_assignments(tree, map):
    for i, node in enumerate(tree.body):
        if not isinstance(node, ast.Assign):
            continue

        for nt in node.targets:
            if not isinstance(nt, ast.Name):
                # deal with tuple assignments a, b = 1, 2
                continue
            if nt.id in map:
                # ok we have to replace this
                if not isinstance(node.value, ast.Constant):
                    # warning it is not assigned a constant
                    continue
                # change value for all targets. this will break a=b=2 with a replace of a = 5
                node.value.value = map[nt.id]

src = """
a = 23
b = a
# todo handle these
# b = c = 2
# r, s = 1, a
# conf = usion = 1  what should happen here if you replace usion with 4 ? is conf 4?

print(a)
print(b)
"""

tree = ast.parse(src)
replace_top_assignments(tree, {'a': 4})
code_obj = compile(tree, 'aaa', mode='exec')
exec(code_obj)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM