通过字符串调用函数

Calling function through string

我有一个 Python 主程序,它导入另一个具有多个功能的模块(称为动作)。主程序应该运行一些东西,得到一个字符串(即goto(114))然后运行 actions.goto(114),其中114是函数goto( x) 在行动中。

我已经尝试了明显的尝试 运行 字符串,但是没有用。我还找到了 globals() 方法,如果 goto(x) 在我的主模块中,它会起作用,我还找到了 getattr 方法,但在这种情况下,我还没有找到我传递函数名称和争论所以我有点迷路了。

#main.py
import actions
def main():
    getc = 'goto(114)'
    result = actions.getc #this would be actions.goto(114)
    print result

#actions.py
def goto(x):
    #code
    return something

实际程序从另一个程序编写的.txt文件中获取字符串,我只是这样制作示例以便于理解。

您可以使用的一个选项是 action class 上的 __getattribute__ 来获取函数 goto,然后使用包含的参数调用它。您需要像这样解析它:

import re
import action

getc = 'goto(114)'
func, arg = re.search('(\w+)\((\d+)\)', 'goto(114)').groups()

# f is the function action.goto with the argument 114 supplied as an int
# __getattribute__ allows you to look up a class method by a string name
f = action.__getattribute__(func)

# now you can just call it with the arg converted to int
result = f(int(arg))

正则表达式可能需要改进一下,但它正在查找调用函数的名称以及括在括号中的参数。 __getattribute__ 将从 action 和 return 中获取函数对象,它未被调用,因此您可以稍后调用它。

对于多个参数,您可以利用 ast 库:

import re
import ast

# I'm going to use a sample class as a stand-in
# for action
class action:
    def goto(*args):
        print(args)

getc = 'goto(114, "abc", [1,2,3])'
func, args = re.search('(\w+)\((.*)\)', getc).groups()

# will convert this into python data structures
# safely, and will fail if the argument to literal_eval
# is not a python structure
args = ast.literal_eval('(%s)' % args)

f = getattr(action, func)
f(*args)
# 114, "abc", [1,2,3]

更简单的选择(谨慎行事)是使用 eval:

cmd = 'action.%s' % getc
result = eval(cmd)

请注意,尽管标准库中有使用它的示例,但在 python 社区中这被认为是不好的做法。这对 un-validated 代码来说是不安全的,如果您不监视源文件

则很容易被利用