在线程中使用exec(compile())导入问题

时间:2016-02-21 17:05:06

标签: python multithreading import nameerror

Windows 10,Python 3.5.1 x64此处。

这很奇怪......让我说我有这个名为do.py的脚本。请注意import string声明:

import string

# Please note that if the print statement is OUTSIDE 'main()', it works.
# It's like if 'main()' can't see the imported symbols from 'string'
def main():
    print(string.ascii_lowercase)

main()

我想从一个"启动器脚本",在子线程中运行它,就像这样(launcher.py):

import sys
import threading

sys.argv.append('do.py')

def run(script, filename):
    exec(compile(script, filename, 'exec'))

with open(sys.argv[1], 'rb') as _:
    script = _.read()

# But this WORKS:
# exec(compile(script, sys.argv[1], 'exec'))

thread = threading.Thread(name='Runner', target=run, args=(script, sys.argv[1]))
thread.start()
thread.join()

它因以下错误而死:

Exception in thread Runner:
Traceback (most recent call last):
  File "C:\Program Files\Python35\lib\threading.py", line 914, in _bootstrap_inner
    self.run()
  File "C:\Program Files\Python35\lib\threading.py", line 862, in run
    self._target(*self._args, **self._kwargs)
  File "tmpgui.py", line 7, in run
    exec(compile(script, filename, 'exec'))
  File "do.py", line 6, in <module>
    main()
  File "do.py", line 4, in main
    print(string.ascii_lowercase)
NameError: name 'string' is not defined

也就是说,执行代码未正确导入string或类似内容,并且main() string模块中不可见。

这不是我的项目的完整代码,这个代码太大了,不能在这里发布,但是我创建的最小代码模仿了这个问题。

为了防止有人好奇,我正在重写我的旧程序,该程序导入了脚本的main()函数并运行该函数,标准输出流重定向到tkinter文本框。我想加载脚本并运行它,而不是从脚本中导入函数。出于各种原因,我不想使用subprocess,我更喜欢运行&#34;重定向&#34;代码在线程中并与主线程进行通信,主线程是处理GUI的主线程。这部分工作得很好,我唯一的问题就是这个,我无法理解为什么会发生这种情况!

我最好的选择:我应该将全球或本地词典中的内容传递给exec,但我在这里丢失了......

提前多多感谢!

1 个答案:

答案 0 :(得分:3)

exec(thing, globals(), locals())相当于run

因此,

  • do.py 的本地符号表是import string函数的本地符号表
  • do.py 的全局符号表是 launcher.py 的全局符号表

run导入模块并将其绑定到本地空间中的变量,该变量是def run(script, filename): try: exec(compile(script, filename, 'exec')) finally: assert 'string' in locals(), "won't fail because 'import' worked properly" 函数的本地空间。您可以验证这一点:

main

string有一个单独的本地范围,但它与 do.py 共享全局符号表,因此与 launcher.py 共享。

Python试图在main的本地(它是空的)和全局符号表中找到名为NameError的变量,但是失败了,并引发了exec

在调用def run(script, filename): exec(compile(script, filename, 'exec'), {}) 时传递一个空字典:

%{
  #include "y.tab.h"
  #include "Expression.h"
%}

%%

"=="            {return EQ;}
"<"             {return '<';}
">"             {return '>';}
"="             {return '=';}
"+"             {return '+';}
"-"             {return '-';}
"*"             {return '*';}
"/"             {return '/';}
","             {return ',';}
";"             {return ';';}
"("             {return '(';}
")"             {return ')';}
"{"             {return '{';}
"}"             {return '}';}
"["             {return '[';}
"]"             {return ']';}
"int"               {return INT;} 
"char"              {return CHAR;}
"float"             {return FLOAT;}
"long"              {return LONG;}
"double"            {return DOUBLE;}
"return"            {return RETURN;}
"if"                {return IF;}
"else"              {return ELSE;}


[0-9]+              {return Number;}
[A-Za-z][A-Za-z0-9]*        {return Identifier;}                }

[ \t]               ;
[\n]                ;
"."             {return BADTOKEN;}


%%