在Python脚本中,有没有一种获取所有变量值的方法?

4
如果这个问题不在范围内,请建议我可以将其移动到哪里。
我有很多Python脚本(版本2.7),它们互相调用。为了查看哪个脚本调用了哪个脚本,我目前已经构建了一个漂亮的GUI树来映射它们之间的关系。
我的问题在于解析文件。一个脚本调用另一个脚本的最简单示例是调用:
os.system('another.py')

这很容易解析,只需取出括号内的内容。现在我开始评估变量。 我目前评估变量的方法如下:
x = 'another'
dot = '.'
py = 'py'
os.system(x+dot+py) # Find three variables

listOfVars = getVarsBetweenParenthesis() # Pseudo code.

# Call getVarValue to find value for every variable, then add these together 

'''
    Finds the value of a variable.
'''
def getVarValue(data, variable, stop):
    match = ''
    for line in data:
        noString = line.replace(' ', '') # Remove spaces
        if variable+'=' in noString:
            match = line.replace(variable+'=', '').strip()
        if line == stop:
            break
    return match

除了这段代码很丑陋之外,它还有一些缺点。当执行Call getVarValue to find value for every variable, then add these together时,并不是所有变量都能得到其期望的值。例如:
x = os.getcwd() # Cannot be found by getVarValue
script = 'x.py'
os.system(x+script) # Find three variables

问题在于我不想调用这些脚本(一些脚本创建/更新文件),而是通过值来解析它们。由于Python解释器能够解析脚本,我想这应该是可能的。
我已经研究了tokenize,但没有什么帮助,还有抽象语法树。然而,这两者似乎都不能解析变量而不运行文件。
是否有一种方法(最好是Pythonic)可以在不执行脚本的情况下检索变量值?

想一想你在问什么:如果变量的值在脚本执行后发生了改变,你想显示什么?初始值还是计算后的值? - Burhan Khalid
我不确定,但你尝试过 monkeypatching os.system 吗?像这样:os.system = lambda script_name: send_script_name_to_where_you_collect_them(script_name) - J0HN
@J0HN 没有想到,谢谢 :) 如果我想对比 os.system 更多的模块执行此操作,那么我需要对所有这些模块进行猴子补丁吗? - Pphoenix
是的。同时,您可能希望跟踪已修补的内容,并在某个时候将其恢复为原始值。 - J0HN
请查看以下链接,其中包含类似问题的Python3答案:http://stackoverflow.com/questions/42875156 - ideasman42
显示剩余3条评论
1个回答

1

这是从Python3 Q&A修改而来的示例,演示了如何使用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") as file_mod:
        data = file_mod.read()

    try:
        ast_data = ast.parse(data, filename=mod_path)
    except:
        if raise_exception:
            raise
        print("Syntax error 'ast.parse' can't read %r" % mod_path)
        import traceback
        traceback.print_exc()

    if ast_data:
        for body in ast_data.body:
            if body.__class__ == ast.Assign:
                if len(body.targets) == 1:
                    print(body.targets[0])
                    if getattr(body.targets[0], "id", "") == variable:
                        try:
                            return ast.literal_eval(body.value)
                        except:
                            if raise_exception:
                                raise
                            print("AST error parsing %r for %r" % (variable, mod_path))
                            import traceback
                            traceback.print_exc()
    return default

# example use
this_variable = {"Hello": 1.5, 'World': [1, 2, 3]}
that_variable = safe_eval_var_from_file(__file__, "this_variable")
print(this_variable)
print(that_variable)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接