背景:我最初回答了这位绅士关于使用解决方案打开非阻塞交互式解释器中间程序的threading
问题。他指出它有效,但对他来说表现不佳(可以理解,因为threading
)。面对高 CPU 利用率,我怀着忐忑的心情转而寻求multiprocessing
一种性能更高的解决方案。
使用multiprocessing
这种类型的基本问题是子进程不共享主进程的 STDIN - 我可以解决这个问题,但是......
问题:虽然我确实找到了解决方案(请参阅线程),但我的解决方案存在一个持续存在的问题:code.interact()
通过调用exit()
(即 raise SystemExit
)退出会话会给出以下回溯:
Traceback (most recent call last):
File "/usr/lib/python3.2/multiprocessing/process.py", line 267, in _bootstrap
self.run()
File "/usr/lib/python3.2/multiprocessing/process.py", line 116, in run
self._target(*self._args, **self._kwargs)
File "./test2.py", line 6, in interp
code.interact(local=locs)
File "/usr/lib/python3.2/code.py", line 287, in interact
console.interact(banner)
File "/usr/lib/python3.2/code.py", line 223, in interact
more = self.push(line)
File "/usr/lib/python3.2/code.py", line 245, in push
more = self.runsource(source, self.filename)
File "/usr/lib/python3.2/code.py", line 74, in runsource
self.runcode(code)
File "/usr/lib/python3.2/code.py", line 90, in runcode
exec(code, self.locals)
File "<console>", line 1, in <module>
File "/usr/lib/python3.2/site.py", line 382, in __call__
raise SystemExit(code)
SystemExit: None
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/usr/lib/python3.2/multiprocessing/process.py", line 278, in _bootstrap
sys.stderr.write(e.args[0] + '\n')
TypeError: unsupported operand type(s) for +: 'NoneType' and 'str'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "./test2.py", line 12, in <module>
p.start()
File "/usr/lib/python3.2/multiprocessing/process.py", line 132, in start
self._popen = Popen(self)
File "/usr/lib/python3.2/multiprocessing/forking.py", line 126, in __init__
code = process_obj._bootstrap()
File "/usr/lib/python3.2/multiprocessing/process.py", line 286, in _bootstrap
util.info('process exiting with exitcode %d' % exitcode)
UnboundLocalError: local variable 'exitcode' referenced before assignment
重现:这是重现的代码:
#!/usr/bin/python3
def interp(locs,handle):
import code, os, sys
sys.stdin = os.fdopen(handle)
code.interact(local=locs)
if __name__ == '__main__':
from multiprocessing import Process
import sys
p=Process(target=interp,args=(locals(),sys.stdin.fileno()))
p.start()
import time
time.sleep(20)
在交互式解释器中,您必须键入exit()
. 执行 ctrl-D 优雅地退出。这是踢球者:做raise SystemExit
也优雅地退出。 什么?!
进一步调查:这是有问题的块process.py
:
except SystemExit as e:
if not e.args:
exitcode = 1
elif type(e.args[0]) is int:
exitcode = e.args[0]
else:
sys.stderr.write(e.args[0] + '\n') #exception here
exitcode = 1
并在该行之前直接插入调试语句表明它e.args
是 length-1 tuple (None,)
。有道理,我猜。
问题:这是怎么回事?!通过获取元组SystemExit
生成的版本如何?这显然不会正常发生 - 裸露的意思是exit()
(None,)
e.args
raise SystemExit
e.args == ()
我也愿意接受改进我的代码(或我对链接线程的回答)的方法,但主要是我想知道我是否正在做一些我明确不应该做的事情。sys.stdin
在子进程中重定向似乎无害,但是......
解决方案:感谢 Peters 先生,原来这是 python 3.2 中的一个错误。在 3.3 中,违规行变成了:sys.stderr.write(str(e.args[0]) + '\n')
. str(None) + '\n'
不再引起爆炸。凉爽的。