如何将函数定义作为字符串传递给python脚本

时间:2016-01-15 13:44:32

标签: python function parsing command-line-arguments

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

 if (body.hasClass('page-sidebar-fixed')) {
            $('.page-sidebar').on('mouseenter', function () {
                if (body.hasClass('page-sidebar-closed')) {
                    $(this).find('.page-sidebar-menu').removeClass('page-sidebar-menu-closed');
                }
            }).on('mouseleave', function () {
                if (body.hasClass('page-sidebar-closed')) {
                    $(this).find('.page-sidebar-menu').addClass('page-sidebar-menu-closed');
                }
            });
        }

我想这样称呼:#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)'部分?

我想象一个解决方法:

  1. 从命令行
  2. 获取字符串函数定义
  3. 将其写入某个临时目录中扩展名为.py的文件
  4. 使用此问题的解决方案从文件加载定义:How to import a module given the full path?
  5. 执行
  6. 清理
  7. 但我相信一定有更好的方法。

4 个答案:

答案 0 :(得分:2)

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

import sys

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

使用您的具体示例,您可能需要使用lambda x: len(x)

之类的内容

正如@ Jan-Spurny正确地指出的那样:"永远不会,永远不会使用eval,除非你绝对确定没有别的办法。即便如此,你应该停下来思考一下。"

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

import data_loader_and_executor

def function(x):
    return len(x)

data_loader_and_executor.run(function)

答案 1 :(得分: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]]

!!请记住,评估用户输入非常危险!!

修改:由于funlocals中定义的唯一对象,因此您只需返回locals()中的第一个元素:

def load_function_definition_from_command_line():
   exec(sys.argv[1])
   return locals()[0]

答案 2 :(得分: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

编辑:强制性,"执行此类用户输入并不明智。"

答案 3 :(得分:0)

关于如何执行此操作的正确答案的最明显来源是timeit python builtin库。

它是这样调用的:

$ python -m timeit '"-".join(str(n) for n in range(100))'

你可以在这里找到源代码,它使用compileexec从命令行调用代码

https://hg.python.org/cpython/file/2.7/Lib/timeit.py#l143