背景:私はもともと、ソリューションを使用してプログラムの途中でノンブロッキングの対話型インタープリターを開くことについて、この素晴らしい紳士の質問に答えました。threading
彼はそれがうまくいったことを指摘しましたが、彼にとってはうまくいきませんでした(理由は理解できthreading
ます). 恐れを抱いて、私multiprocessing
は高い CPU 使用率に直面して、よりパフォーマンスの高いソリューションを実現することに目を向けました。
このタイプのものを使用する際の基本的な問題multiprocessing
は、子プロセスがメインプロセスの STDIN を共有しないことです-これは回避できますが...
問題:解決策にたどり着きましたが (スレッドを参照)、私の解決策には 1 つの永続的な問題がありました: をcode.interact()
呼び出してセッションを終了するとexit()
(つまり、 を上げると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'
もはや爆発を引き起こさない。涼しい。