从文本文件中读取Python函数并将其赋值给变量

3
我有一个包含Python函数的文本文件,类似于这样:
a.txt
def func():
    var = 5
    return var

然后我在一个Python脚本中读取了这个文件:
b.py
python_file = open("a.txt").read()

现在我想将`a.txt`文件的函数赋值给一个变量,而不用担心函数名,并执行它。我尝试了如下的代码:
python_file = open("a.txt").read()
b = exec(python_file)
b()

但是没有用,我也尝试了 execfile

1
为什么不直接将文件重命名为.py,然后以正常方式进行import呢?无论哪种方式,请注意exec不会返回任何内容,请阅读其文档 - jonrsharpe
@jonrsharpe 先生,这是一个 .txt 文件,所以不能导入“.”。而且要求是我不知道在 Python 文件中 txt 文件的函数名称。 - Ashisha Nautiyal
一个Python文件本质上也只是一个文本文件,为什么不能使用os.rename重命名它呢? - jonrsharpe
1
我想将它保存为txt文件。未来,Python函数将作为字符串从数据库中获取。 - Ashisha Nautiyal
3
你不觉得这类信息在问题中会很有用吗? - jonrsharpe
2个回答

4

执行字符串后,您可以直接调用func,因为它已被添加到您当前的命名空间中:

>>> exec("""def func():
    var = 5  # note that the semicolons are redundant and unpythonic
    return var""")
>>> func()
5

根据官方文档exec函数实际上不返回任何内容,因此将foo = exec(...)赋值是没有意义的。
如果想查看在执行的代码中本地定义了哪些名称,请将一个空字典作为locals参数传递给exec函数:
>>> ns = {}
>>> exec("""def func():
    var = 5
    return var""", globals(), ns)
>>> ns
{'func': <function func at 0x0315F540>}

您可以将该函数分配并像通常一样调用它:
>>> b, = ns.values()  # this will only work if only one name was defined
>>> b()
5

我不想用函数名来调用它。我不知道Python文件中的函数名。我想将任何函数分配给一个变量。 - Ashisha Nautiyal
您IP地址为143.198.54.68,由于运营成本限制,当前对于免费用户的使用频率限制为每个IP每72小时10次对话,如需解除限制,请点击左下角设置图标按钮(手机用户先点击左上角菜单按钮)。 - jonrsharpe
同意先生。但我想找到一种将其分配给变量的方法。 - Ashisha Nautiyal
1
我已经告诉你如何做到这一点,但你仍然没有真正回答我的问题。 - jonrsharpe
1
@SDilmac 这样解决问题吗?如果你有另外的答案,请将其作为一个回答添加进来。 - jonrsharpe
显示剩余2条评论

2
在提供我的解决方案之前,我强烈警告您,除非您确信中没有恶意代码,否则不要这样做。 我的解决方案使用execfile函数加载文本文件并返回第一个对象(可以是变量或函数):
def load_function(filename):
    """ Assume that filename contains only 1 function """
    global_var = dict()
    execfile(filename, global_var)
    del global_var['__builtins__']
    return next(global_var.itervalues())

# Use it
myfunction = load_function('a.txt')
print myfunction()

更新

为了更加谨慎,修改返回行如下,这样它就可以跳过变量(但无法跳过类声明)。

    return next(f for f in global_var.itervalues() if callable(f))

更新2

感谢johnsharpe指出在Python 3中没有execfile。这里有一个修改后的解决方案,使用exec代替。这次,函数应该在“本地”作用域中找到。

def load_function(filename):
    """ Assume that filename contains only 1 function """
    with open(filename) as f:
        file_contents = f.read()
        global_var = dict()
        local_var = dict()
        exec file_contents in global_var, local_var
        return next(f for f in local_var.itervalues() if callable(f))

# Use it
myfunction = load_function('a.txt')
print myfunction()

请注意,Python 3 没有 execfile 函数,请参考 https://docs.python.org/3/whatsnew/3.0.html#builtins 和 https://dev59.com/YHRC5IYBdhLWcg3wAcbU。 - jonrsharpe
我的错。我没有Python 3。在这种情况下,你的解决方案(打开文本文件,读取内容,调用exec)与我的(从全局命名空间获取第一个可调用对象)结合起来将会奏效。 - Hai Vu

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