我需要能够从字符串中运行大量的python代码。简单地使用exec
似乎不起作用,因为虽然代码在正常设置中完美运行,但这样做似乎会引发错误。我也不认为我可以像在互联网上托管一样导入它。这是代码:
import urllib.request
URL = "https://dl.dropboxusercontent.com/u/127476718/instructions.txt"
def main():
instructions = urllib.request.urlopen(URL)
exec(instructions.read().decode())
if __name__ == "__main__":
main()
这是我一直在犯的错误:
Traceback (most recent call last):
File "C:\Python33\rc.py", line 12, in <module>
main()
File "C:\Python33\rc.py", line 9, in main
exec(instructions.read().decode())
File "<string>", line 144, in <module>
File "<string>", line 120, in main
NameError: global name 'Player' is not defined
我正在尝试运行的代码可以在第一个代码段中的链接中找到。
如果您有任何问题我会回答。谢谢。
答案 0 :(得分:3)
如果不指定全局变量,exec
function(Python / bltinmodule.c)使用PyEval_GetGlobals()
和PyEval_GetLocals()
。对于函数的执行框架,后者创建一个新的f_locals
dict,它将成为编译代码中IMPORT_NAME
,STORE_NAME
,LOAD_NAME
操作的目标。
在Python的模块级别,正常的事态是globals() == locals()
。在这种情况下,STORE_NAME
正在使用模块的全局变量,这是模块中定义的函数将用作其全局命名空间。然而,对全局和局部使用单独的dicts显然打破了这个假设。
解决方案是手动提供globals
,exec
也将用作locals
:
def main():
instructions = urllib.request.urlopen(URL)
exec(instructions.read().decode(), globals())
您还可以使用已定义__name__
的新词典:
def main():
instructions = urllib.request.urlopen(URL)
g = {'__name__': '__main__'}
exec(instructions.read().decode(), g)
我在源代码中看到当前目录需要一个名为“pickup.wav”的声音文件,否则你只会收到另一个错误。
当然,关于使用exec
这样的安全问题的评论仍然适用。我只是在解决名称空间技术问题。
答案 1 :(得分:1)
首先我想你可以尝试使用StringIO对象__import__
。可能看起来像StackOverflow: Local Import Statements in Python。
......但那不对。
然后我考虑使用imp
模块,但这看起来没有用。
然后我看了一下:Alex Martelli对Use of Eval in Python的回答 - 并试图在一段愚蠢的代码上使用它。
我可以从中获取ast
对象以及compile()
的结果(尽管似乎只需拨打compile(some_string_containing_python_source, 'SomeName', 'exec')
而无需通过ast.parse()
如果您愿意,可以使用中间步骤。如果您希望在编译之前遍历生成的语法树,检查并可能修改节点,那么我将使用ast
。
最后,在执行命名空间中定义了函数,类或变量后,您似乎需要exec()
compile()
的结果。
答案 2 :(得分:0)
您可以使用pipe
将所有字符串放入python的子进程中,并从中获取输出结果。
Google os.popen
或subprocess.Popen