【问题标题】:Defining a function with exec from inside a function in global environment从全局环境中的函数内部使用 exec 定义函数
【发布时间】:2015-04-23 01:56:59
【问题描述】:

我有一个函数,当被调用时,应该使用exec 定义另一个函数,并使这个新函数可用于主程序。 mwe 如下。

主程序:

#!/usr/bin/python
from ext import makeF

makeF()
sayA()

外部模块:

def makeF():
    script="def sayA():\n\tprint 'Aah'"
    exec(script)
    sayA()
    return

我想要的是能够从主程序调用内部函数sayA(),所以在这个例子中输出应该是

Aah
Aah

但它会返回

Aah
Traceback (most recent call last):
  File "mwe.py", line 5, in <module>
    sayA()
NameError: name 'sayA' is not defined

我有点期待,所以我根据docsexec(script) 行替换为exec(script,globals),但我得到了

Traceback (most recent call last):
  File "mwe.py", line 4, in <module>
    makeF()
  File "/home/tomas/tests/ext.py", line 3, in makeF
    exec(script,globals,locals)
TypeError: exec: arg 2 must be a dictionary or None

我觉得我在这里遗漏了一些非常明显的东西,但我无法弄清楚。任何帮助表示赞赏。

谢谢。

【问题讨论】:

    标签: python function python-2.7


    【解决方案1】:

    您已经在 makeF 内部创建了函数,因此它甚至在函数外部的外部模块范围内都不可见。

    如果你想从 main 调用它,return sayA

    def makeF():
        script="def sayA():\n\tprint('Aah')"
        exec(script)
        return sayA
    

    然后在main中:

    f = makeF()
    f()
    

    要在 exec 不再是语句而是函数的 python3 中获得相同的行为,您可以使用带有 dict 的 lambda:

    def makeF():
        d = {}
        "sayA = lambda: print('Aah')"
        exec("sayA = lambda: print('Aah')",d)
        return d["sayA"]
    
    from ext import makeF
    
    f = makeF()
    f()
    

    【讨论】:

    • 我尝试用 python3 运行这段代码,但没有成功。它对你有用吗?
    • 为我工作。我正在使用python 2.7。试试exec(script,globals())exec(script,globals)
    • @TomCho,这是一个 hack。不管它是否适合你,正确的答案是函数是 makeF 的本地函数,当你可以简单地返回函数时,为什么要破解一些东西?
    • @PadraicCunningham,我没有在我的程序中使用它。我实际上使用了你建议的同样的东西(根本没有globals)。我刚刚对@browskie 提出了建议,因为显然它在 p3k 上对他不起作用。我现在才意识到我忘了提到他。
    • @TomCho,抱歉,我没有看到其他评论。我恢复了 OP 正在使用 python2,因为即使在本地模块中,该函数在 python 3 中也根本不起作用。
    【解决方案2】:

    globals 和 locals() 是函数,而不是字典(尽管它们返回字典)。

    而且,你试图调用它的方式,sayA 是在 locals() 中定义的。把它放在一边。

    我的版本:

    def makeF():
      script="def sayA():\n\tprint 'Aah'"
      #exec script in globals()
      exec(script, globals())
      #exec(script, globals(), locals())
      sayA()
      print globals()
      print locals()
    
    makeF()
    sayA()
    

    试用注释掉的行进行对比。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-11-21
      • 1970-01-01
      • 1970-01-01
      • 2017-04-07
      • 2012-10-20
      • 2021-08-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多