如何将函数定义作为字符串传递给 python 脚本
How do I pass function definition to python script as string
我想将函数定义传递给python命令行脚本。做这个的最好方式是什么?我正在使用 python 2. 假设我有这样的脚本:
#myscript.py
x = load_some_data()
my_function = load_function_definition_from_command_line()
print my_function(x)
我想这样称呼它:python myscript.py 'def fun(x): return len(x)'
如何执行 load_function_definition_from_command_line
部分?
我想象一个解决方法:
- 从命令行获取字符串函数定义
- 将其写入某个临时目录中扩展名为 .py 的文件
- 使用此问题的解决方案从文件加载定义:How to import a module given the full path?
- 执行
- 清理
但我相信一定有更好的方法。
您可以使用eval
到运行代码定义一个字符串。像这样:
import sys
x = load_some_data()
function = eval("".join(sys.argv[1:]))
print(function(x))
对于您的具体示例,尽管您可能必须使用类似 lambda x: len(x)
的内容
正如@Jan-Spurny 正确指出的那样:"Never, never, never use eval unless you're absolutely sure there is no other way. And even then you should stop and think again."
在我看来,更好的策略是将数据加载器和执行器转换为一个模块,该模块的方法将函数作为参数并 运行s 所需的代码。最终结果是这样的:
import data_loader_and_executor
def function(x):
return len(x)
data_loader_and_executor.run(function)
使用函数exec:
import sys
def load_function_definition_from_command_line():
exec(sys.argv[1])
return locals()['fun']
当然你必须知道你的函数将如何命名,但这可以通过传递给你的参数第二个参数来完成:
$ python myscript.py 'def fun(x): return len(x)' fun
然后您的函数将如下所示:
import sys
def load_function_definition_from_command_line():
exec(sys.argv[1])
return locals()[sys.argv[2]]
!!请记住,评估用户输入是非常危险的!!
编辑:由于 fun
将是 locals
中定义的唯一对象,您可以只 return [=16] 中的第一个元素=]:
def load_function_definition_from_command_line():
exec(sys.argv[1])
return locals()[0]
您可以使用 eval 或 exec 在您当前的命名空间中创建一个函数。
exec "somefunc(x): return x * 2"
somefunc(2) # 2
您的上下文中的示例
python load_function.py "def f(x): return x * 2"
//load_function.py
import sys
exec sys.argv[1]
print f(2)
命令行输出:
4
编辑: 必填,"It is not wise to execute user input like this."
有关如何执行此操作的正确答案的最明显来源是在 timeit
python builtin 库中。
它是这样调用的:
$ python -m timeit '"-".join(str(n) for n in range(100))'
你可以在这里找到源代码,它使用 compile
和 exec
从命令行调用代码
我想将函数定义传递给python命令行脚本。做这个的最好方式是什么?我正在使用 python 2. 假设我有这样的脚本:
#myscript.py
x = load_some_data()
my_function = load_function_definition_from_command_line()
print my_function(x)
我想这样称呼它:python myscript.py 'def fun(x): return len(x)'
如何执行 load_function_definition_from_command_line
部分?
我想象一个解决方法:
- 从命令行获取字符串函数定义
- 将其写入某个临时目录中扩展名为 .py 的文件
- 使用此问题的解决方案从文件加载定义:How to import a module given the full path?
- 执行
- 清理
但我相信一定有更好的方法。
您可以使用eval
到运行代码定义一个字符串。像这样:
import sys
x = load_some_data()
function = eval("".join(sys.argv[1:]))
print(function(x))
对于您的具体示例,尽管您可能必须使用类似 lambda x: len(x)
正如@Jan-Spurny 正确指出的那样:"Never, never, never use eval unless you're absolutely sure there is no other way. And even then you should stop and think again."
在我看来,更好的策略是将数据加载器和执行器转换为一个模块,该模块的方法将函数作为参数并 运行s 所需的代码。最终结果是这样的:
import data_loader_and_executor
def function(x):
return len(x)
data_loader_and_executor.run(function)
使用函数exec:
import sys
def load_function_definition_from_command_line():
exec(sys.argv[1])
return locals()['fun']
当然你必须知道你的函数将如何命名,但这可以通过传递给你的参数第二个参数来完成:
$ python myscript.py 'def fun(x): return len(x)' fun
然后您的函数将如下所示:
import sys
def load_function_definition_from_command_line():
exec(sys.argv[1])
return locals()[sys.argv[2]]
!!请记住,评估用户输入是非常危险的!!
编辑:由于 fun
将是 locals
中定义的唯一对象,您可以只 return [=16] 中的第一个元素=]:
def load_function_definition_from_command_line():
exec(sys.argv[1])
return locals()[0]
您可以使用 eval 或 exec 在您当前的命名空间中创建一个函数。
exec "somefunc(x): return x * 2"
somefunc(2) # 2
您的上下文中的示例
python load_function.py "def f(x): return x * 2"
//load_function.py
import sys
exec sys.argv[1]
print f(2)
命令行输出:
4
编辑: 必填,"It is not wise to execute user input like this."
有关如何执行此操作的正确答案的最明显来源是在 timeit
python builtin 库中。
它是这样调用的:
$ python -m timeit '"-".join(str(n) for n in range(100))'
你可以在这里找到源代码,它使用 compile
和 exec
从命令行调用代码