別のターミナル ウィンドウ (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()