Python Popen的无序输出

Python Popen的无序输出,python,shell,pipe,stdio,Python,Shell,Pipe,Stdio,我正在编写另一个终端窗口(使用PySide),并使用以下命令运行shell(bash): 将各种stdio设置为子流程管道时 我还使用禁用输出stdio(out,err)上的缓冲 然后,我使用计时器轮询输出io以获取可用数据并将其提取。 它工作得相当好,但有时我会有一些奇怪的行为。如果在提示下发出命令(如pwd),我会得到两个不同的可能输出: /etc:$ pwd /etc /etc:$ 另一个是 /etc:$ pwd/etc /etc:$ 就好像命令中的换行符和输出的其余部分被交换一

我正在编写另一个终端窗口(使用PySide),并使用以下命令运行shell(bash):

将各种stdio设置为子流程管道时
我还使用禁用输出stdio(out,err)上的缓冲

然后,我使用计时器轮询输出io以获取可用数据并将其提取。

它工作得相当好,但有时我会有一些奇怪的行为。如果在提示下发出命令(如pwd),我会得到两个不同的可能输出:

/etc:$ pwd
/etc
/etc:$ 
另一个是

/etc:$ pwd/etc

/etc:$
就好像命令中的换行符和输出的其余部分被交换一样。基本上任何命令都会出现这种情况,例如,对于ls,第一个文件出现在ls之后,最后一个文件后面是一个空行。
让我不安的是它不一致

编辑:添加了完整的代码示例


在尝试创建一个要粘贴的小代码示例(添加在上面)之后,我注意到问题的出现是因为stdout和stderr之间的同步。
一点点的搜索让我想到了以下问题:

我在那里尝试了第一个答案,并使用了轮询方法,但这并没有解决问题,因为我的事件混合方式与以前相同。


解决这个问题的是mossman的答案,它基本上将stderr重定向到stdout,这在我的情况下已经足够好了。

如果您希望我们能够提供帮助,您必须提供超过0.5行的代码。当然,您是对的,代码细节中有魔鬼。我试图创建一个小的代码示例来说明这个问题,在这样做的时候,我发现问题可能在于stdout和stderr之间的同步。我正在调查。
/etc:$ pwd
/etc
/etc:$ 
/etc:$ pwd/etc

/etc:$
#!/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()