1

別のターミナル ウィンドウ (PySide を使用) を作成しており、以下を使用してシェル (bash) を実行しています。

subprocess.Popen(['/bin/bash','-i'],....

さまざまなstdioをsubprocess.PIPE
に設定しながら、出力stdio(out、err)のバッファリングも無効にしています

fcntl(s.fileno(),F_SETFL,os.O_NONBLOCK)

次に、タイマーを使用して、使用可能なデータの出力 io をポーリングし、プルします。

かなりうまく機能しますが、時々奇妙な動作が発生します。プロンプトでコマンド (pwd など) を発行すると、次の 2 つの異なる出力が得られます。

/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()
4

1 に答える 1