2016-01-15 24 views
3

我想将函数定义传递给python命令行脚本。做这个的最好方式是什么?我使用python 2.假设我有一个这样的脚本:如何将函数定义传递给python脚本作为字符串

#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一部分?

我想一个解决办法:

  1. 得到命令行字符串函数定义
  2. 它写在一些临时目录
  3. 负载使用的解决方案从文件中定义的.py扩展名的文件这个问题:How to import a module given the full path?
  4. 执行
  5. 清理

但我确定必须有更好的方法。

+1

我想你调用代码应该解释你为什么要传递一个函数作为一个字符串来运行的原因。这可以帮助我们更好地帮助你,并且可能找到一种解决方法来使用当前答案所提示的内容(eval和exec)。评估命令行参数并将其作为代码运行极其危险,除非绝对必要,否则不应该完成。 – disflux

+0

出于好奇 - 你为什么需要这个?我问,因为它导致非常糟糕的解决方案(eval),也许你只是没有看到其他的可能性。 –

+0

我正在编写一个shell应用程序,用于对来自其他应用程序的日志/输出进行map/reduce/filter操作 –

回答

2

您可以使用eval来运行在字符串中定义的代码。像这样:

import sys 

x = load_some_data() 
function = eval("".join(sys.argv[1:])) 
print(function(x)) 

有了您的具体的例子,虽然你可能需要使用像lambda x: len(x)

正如@扬Spurny正确地指出:“永远,永远,永远不会,除非你是绝对的把握使用eval别无他法,即使这样,你也应该停下来思考一下。“

在我看来,更好的策略是将数据加载器和执行器变成一个模块,其方法是将函数作为参数并运行所需的代码。最终的结果是这样的:

import data_loader_and_executor 

def function(x): 
    return len(x) 

data_loader_and_executor.run(function) 
+1

I强烈建议做最后一句('理想情况下,不应该永远不要使用eval'。'')更明显(粗体)或改写它,例如:“永远,永远不会使用'eval',除非你绝对**确定没有别的办法,即使如此,你应该停下来再想一想。“ –

+0

eval背后的危险是什么? –

+2

@JanOsch - 有人可以通过任何**任何**,它会被执行。例如,一些小丑可以通过:“def f(x):import shutil; shutil.rmtree('/');”并删除你的文件系统。 Eval是您程序中最大的最危险的后门程序。 –

0

使用功能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定义的唯一对象,你可以只返回第一个元素locals()

def load_function_definition_from_command_line(): 
    exec(sys.argv[1]) 
    return locals()[0] 
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

编辑:强制性的,“这是不明智的执行用户的输入像这个。”

相关问题