我正在编写另一个终端窗口(使用PySide),我正在运行shell(bash):
subprocess.Popen(['/bin/bash','-i'],....
将各种stdio设置为subprocess.PIPE
我也在使用
fcntl(s.fileno(),F_SETFL,os.O_NONBLOCK)
然后我使用计时器轮询输出io以获取可用数据并将其拉出来
它运作得相当好,但我有时候会遇到一些奇怪的行为。如果在提示符处我发出命令(例如pwd),我会得到两个不同的可能输出:
/etc:$ pwd
/etc
/etc:$
另一个是
/etc:$ pwd/etc
/etc:$
好像来自命令的换行符和输出的其余部分被换掉了。基本上任何命令都会发生这种情况,因此对于ls,例如,第一个文件出现在ls之后,而一个空行出现在最后一个文件之后。
我的错误在于它不一致。
编辑:添加了完整的代码示例
#!/usr/bin/python
from PySide import QtCore
from PySide import QtGui
import fcntl
import os
import subprocess
import sys
class MyTerminal(QtGui.QDialog):
def __init__(self,parent=None):
super(MyTerminal,self).__init__(parent)
startPath=os.path.expanduser('~')
self.process=subprocess.Popen(['/bin/bash','-i'],cwd=startPath,stdout=subprocess.PIPE,stdin=subprocess.PIPE,stderr=subprocess.PIPE)
fcntl.fcntl(self.process.stdout.fileno(),fcntl.F_SETFL,os.O_NONBLOCK)
fcntl.fcntl(self.process.stderr.fileno(),fcntl.F_SETFL,os.O_NONBLOCK)
self.timer=QtCore.QTimer(self)
self.connect(self.timer,QtCore.SIGNAL("timeout()"),self.onTimer)
self.started=False
def keyPressEvent(self,event):
text=event.text()
if len(text)>0:
if not self.started:
self.timer.start(10)
self.started=True
self.sendKeys(text)
event.accept()
def sendKeys(self,text):
self.process.stdin.write(text)
def output(self,text):
sys.stdout.write(text)
sys.stdout.flush()
def readOutput(self,io):
try:
text=io.read()
if len(text)>0:
self.output(text)
except IOError:
pass
def onTimer(self):
self.readOutput(self.process.stdout)
self.readOutput(self.process.stderr)
def main():
app=QtGui.QApplication(sys.argv)
t=MyTerminal()
t.show()
app.exec_()
if __name__=='__main__':
main()
答案 0 :(得分:0)
在尝试创建一个要粘贴的小代码示例(上面添加)后,我注意到问题出现是因为stdout和stderr之间的同步。
一点点的搜索引发了我以下问题:
Merging a Python script's subprocess' stdout and stderr while keeping them distinguishable
我在那里尝试了第一个答案,并使用了轮询方法,但这并没有解决问题,因为我正在以与以前相同的方式混合事件。
是什么解决了这个问题,是苔藓人的答案,它基本上将stderr重定向到了标准输出,在我的情况下这已经足够了。