Python 子进程问题
我想在Python中启动一个进程,并实现双向通信。当然,Pexpect可以做到这一点,确实是我可能会考虑的一种方法。不过,这并不是最理想的选择。
我理想的情况是有一种跨平台的通用方法,只用标准的Python库。Subprocess这个模块已经很接近了,但我必须等进程结束后才能安全地与它互动,这让我觉得不太方便。
查看文档后,我发现可以直接操作stdin、stdout和stderr这些文件描述符,但有个大大的警告说“不要这样做”。不幸的是,这个警告的原因并不是很清楚,但从我在网上查到的信息来看,这和操作系统的缓冲有关。如果这些内部缓冲出现问题,可能会导致代码意外地死锁(顺便说一下,如果有示例能展示错误的做法和正确的做法,我会很感激)。
所以,冒着代码可能死锁的风险,我想尝试使用poll或select来与正在运行的进程进行交互式读取,而不杀掉它。虽然这样可能失去跨平台的能力,但我喜欢它不需要额外的库。更重要的是,我想知道这样做是否是个好主意。我还没有尝试这种方法,但我担心可能会有一些问题会严重影响我的程序。这样做能行吗?我应该测试哪些内容?
在我的具体情况下,我并不太关心能否向进程写入数据,只是想不断地从中读取数据。而且,我不期望我的进程会输出大量文本,所以我希望能避免死锁的问题,不过我想知道这些限制到底是什么,并能够写一些测试来看看在哪些情况下会出问题。
4 个回答
我在一个单独的线程中做这个,使用消息队列来让不同的线程之间进行沟通。在我的情况下,子进程会把完成的百分比打印到标准输出(也就是屏幕上)。我想让主线程显示一个漂亮的进度条。
if sys.platform == 'win32':
self.shell = False
self.startupinfo = subprocess.STARTUPINFO()
self.startupinfo.dwFlags = 0x01
self.startupinfo.wShowWindow = 0
else:
self.shell = True
self.startupinfo = None
. . .
f = subprocess.Popen( cmd, stdin=subprocess.PIPE, stderr=subprocess.PIPE, stdout=subprocess.PIPE, env = env, shell = self.shell, startupinfo = self.startupinfo )
f.stdin.close()
line = ''
while True:
log.debug('reading')
c = f.stdout.read(1)
log.debug(c)
if len(c) == 0:
log.info('stdout empty; must be done')
break;
if ord(c) == 13:
continue
if c == '%':
# post % complete message to waiting thread.
line = ''
else:
line += c
log.info('checking for errors')
errs = f.stderr.readlines()
if errs:
prettyErrs = 'Reported Errors: '
for i in errs:
prettyErrs += i.rstrip('\n')
log.warn( prettyErrs )
#post errors to waiting thread
else:
print 'done'
return
在Python 2.6的标准库中,使用
这个模块里面有一个
请原谅我对这个话题的无知,但你难道不可以用 -u 这个参数来启动 Python 吗?这个参数的意思是“无缓冲”。
这可能也会引起你的兴趣……http://www.gossamer-threads.com/lists/python/python/658167