【问题标题】:Python: exec "function()"Python:执行“函数()”
【发布时间】:2012-03-04 06:39:44
【问题描述】:

我正在用 python 编写一个简单的测试程序作为我更大程序的一部分,但我想将一个子函数名称传递给主函数,以便主函数可以运行子函数。

例如:

import datetime;

def cronjob(repeat, interval, task):
    if (str(repeat) == 'inf'):
        repeat = 99999999999999999999;
    position = 0;
    interval = datetime.timedelta(seconds=interval);
    x = datetime.datetime.now()
    while not (position >= repeat):
        while (datetime.datetime.now() - x < interval):
            pass;
        x = datetime.datetime.now();
        position += 1;
        exec task;

def test():
    print "hello";

cronjob(10, 0.1, 'test');

编辑:已经解决了这个问题,但由于这里没有列出任何内容,让我告诉你如何去做,以防其他人需要它。

我摆弄了 eval() 和 exec,只尝试了 eval(task)。没有抛出错误,所以我尝试了 print eval(task),果然,它列出了函数的内存地址 [即 test()]。最后,我使用了 eval(task);然后调用该函数。以下是修复此问题的代码:

import datetime;

def cronjob(repeat, interval, task):
    if (str(repeat) == 'inf'):
        repeat = 99999999999999999999;
    position = 0;
    interval = datetime.timedelta(seconds=interval);
    x = datetime.datetime.now()
    while not (position >= repeat):
        while (datetime.datetime.now() - x < interval):
            pass;
        x = datetime.datetime.now();
        position += 1;
        eval(task);

def test():
    print "hello";

cronjob(10, 0.1, 'test()');

【问题讨论】:

    标签: python string function exec eval


    【解决方案1】:

    为什么不将函数对象本身传递给调度器?

    test 是一个对象,也可以用作参数!

    def test():
      print "test"
    
    def exe(func):
      func()
    
    exe(test)
    

    【讨论】:

    • 因为我的主程序只能发送字符串,所以我必须使用字符串。
    • 你确定吗? - 这似乎是一个任意的约束。我不想成为那个人 :) - 但你可以尽量避免这种棘手的东西。此外,如果你给出一个字符串“test”,cron 执行器仍然需要找到相应的函数。因此,如果您的主程序与 cron 执行程序如此分离,以至于您只能传递字符串,我怀疑指定的函数是否可以在执行程序的命名空间中访问。
    • 不幸的是,我正在编写的程序是封闭源代码。我正在制作一个 tcp 代理服务器,并且需要随时解释消息。但是,此任务仅由具有其他解释的内部函数使用,因此您可能对解决方法的可能性是正确的。我会调查的。干杯。
    • @DwayneBrumby - 如果您的程序通过stdin 获取输入,您可以使用Python 函数input 将字符串解析为python 脚本exe(input("enter function to execute:\n"))
    【解决方案2】:

    我相信由于函数是对象,你可以通过名称将一个传递给“控制”函数,所以你不需要 exec 调用(通常用于动态代码执行)。

    例如

    def foo(a_number, a_function):
        print a_number
        a_number += 1
        a_function(a_number)
    
    def bar(another_number):
        print another_number
    
    foo(5, bar)
    

    应该产生输出:
    5
    6

    【讨论】:

      【解决方案3】:

      如果您确定要从字符串派生函数,则可能需要使用 dict 作为从字符串到函数的映射,如下所示:

      dispatcher = {'dothis': module1.do_this,
                    'dothat': module2.to_that}
      
      def foo(fun):
          fun(arg1, arg2)
      
      def bar(action):
          fun = dispatcher.get(action)
          if fun:
             foo(fun)
      

      这将更加安全(因为操作可能来自外部)并提供更好的内部代码结构与外部 API 的解耦。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-07-07
        • 1970-01-01
        • 2020-08-24
        • 1970-01-01
        • 2021-09-29
        • 2016-07-25
        • 2019-07-31
        相关资源
        最近更新 更多