通过字符串调用函数

时间:2019-06-12 20:28:17

标签: python python-2.x

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

我已经尝试了显而易见的方法,该方法只是尝试运行字符串,但这没有用。我还找到了如果goto(x)在我的主模块中也可以使用的globals()方法,并且我也找到了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文件中获取字符串的,我只是以这种方式制作了示例,以使其易于理解。

1 个答案:

答案 0 :(得分:0)

您可以使用的一个选项是__getattribute__类上的action,以获取函数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获取函数对象,并以未调用的方式返回它,因此您以后可以调用它。

对于多个参数,您可以利用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社区中这被认为是不好的做法。对于未经验证的代码,这是不安全的,如果您不监视源文件,很容易被利用