gpt4 book ai didi

python - 使用重定向标准输入在子进程中引发 SystemExit

转载 作者:太空宇宙 更新时间:2023-11-04 01:23:25 26 4
gpt4 key购买 nike

背景:我最初给出了 this fine gentleman's question 的答案。关于使用 threading 解决方案在程序中打开非阻塞交互式解释器。他注意到它有效,但对他来说表现不佳(可以理解,因为 threading)。带着忐忑不安,我求助于 multiprocessing 以在面对高 CPU 利用率时实现性能更高的解决方案。

使用 multiprocessing 处理这类事情的基本问题是子进程不共享主进程的 STDIN - 我可以解决这个问题,但是......

问题:虽然我确实找到了解决方案(请参阅线程),但我的解决方案存在一个持续存在的问题:退出 code.interact() session 调用 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 中出现问题的 block :

   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 是长度为 1 的元组 (None,)。我猜是有道理的。

问题:这是怎么回事?! exit() 生成的 SystemExit 版本如何获取 e.args(None,) 元组?这显然不会正常发生 - 一个简单的 raise SystemExit 意味着 e.args == ()

我也愿意接受改进我的代码(或我对链接线程的回答)的方法,但主要是我想知道我是否正在做我明确不应该做的事情。在子进程中重定向 sys.stdin 似乎无害,但是......

解决方案:感谢 Peters 先生,原来这是 python 3.2 中的一个错误。在 3.3 中,违规行变为:sys.stderr.write(str(e.args[0]) + '\n')str(None) + '\n' 不再导致爆炸。很酷。

最佳答案

我无法深入了解您的真正问题,但可以解开exit() 之谜。这是记录在案的行为,来自 site 模块文档:

quit(code=None) 
exit(code=None)
Objects that when printed, print a message like “Use quit() or
Ctrl-D (i.e. EOF) to exit”, and when called, raise SystemExit with
the specified exit code

所以 exit()exit(None) 相同,这就是 None 的来源。但还有一件事! quitexitLib/_sitebuiltins.py 中定义的 Quitter 类的实例,并且有这个 __call__ 方法:

def __call__(self, code=None):
# Shells like IDLE catch the SystemExit, but listen when their
# stdin wrapper is closed.
try:
sys.stdin.close()
except:
pass
raise SystemExit(code)

令我惊讶的是他们关闭了 sys.stdin。相关的?不知道。注释暗示这是一个技巧,这样像 IDLE 这样的程序就可以知道用户真的想要退出。

顺便说一句,我正在查看当前 (3.4.0a4+) 开发分支负责人的源代码,因此可能与您使用的 Python 存在细微差别。

关于python - 使用重定向标准输入在子进程中引发 SystemExit,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19761124/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com