3

xtermをウィジェットに埋め込んpyqt4で通信したい。特に、印刷してコマンドを実行できるようにしたい(通常のシェルと同じように、コマンドの実行後に通常のユーザープロンプトに戻るようにする)。次の最小限の例を考えてみましょう。どうすればそれを機能させることができますか?

#!/usr/bin/env python
#-*- coding:utf-8 -*-

import  sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *


class embedxterm(QWidget):

    def __init__(self):
        QWidget.__init__(self)
        self.setMinimumWidth(900)
        self.setMinimumHeight(400)
        self.process = QProcess(self)

        self.terminal = QWidget(self)
        self.terminal.setMinimumHeight(300)

        self.cmd1 = QPushButton('Command1',self)
        self.cmd2 = QPushButton('Command2',self)
        self.hello = QPushButton('Print Hello World',self)

        layout = QVBoxLayout(self)

        layoutH = QHBoxLayout(self)

        layoutH.addWidget(self.cmd1)
        layoutH.addWidget(self.cmd2)
        layoutH.addWidget(self.hello)


        layout.addLayout(layoutH)
        layout.addWidget(self.terminal)


        self.process.start(
            'xterm',['-into', str(self.terminal.winId())])

        self.cmd1.clicked.connect(self.Ccmd1)
        self.cmd2.clicked.connect(self.Ccmd2)
        self.hello.clicked.connect(self.Chello)

    def Ccmd1(self):
        self.process.write('ls -l')
        # Should execute ls -l on this terminal

    def Ccmd2(self):
        self.process.write('ping www.google.com')
        # should execute ping www.google.com on this terminal

    def Chello(self):
        self.process.write('Hello World')
        # should just print "Hello World" on this terminal

if __name__ == "__main__":
    app = QApplication(sys.argv)
    main = embedxterm()
    main.show()
    sys.exit(app.exec_())
4

1 に答える 1

4

をウィンドウの 1 つに埋め込むには、xterm次を使用する必要があります。

-into windowId X ウィンドウ識別子 (10 進数の整数) を指定すると、xterm は最上位のシェル ウィジェットをそのウィンドウに再親化します。これは、xterm を他のアプリケーションに埋め込むために使用されます。

xtermそれ自体が起動されたシェル (bash など) と通信します。そのため、起動したシェルと通信する方法を見つける必要があります。xterm次の-Sccnフラグを使用して、開いているファイル記述子を渡すことができます。

このオプションにより、xterm を既存のプログラムの入出力チャネルとして使用できるようになり、特殊なアプリケーションで使用されることもあります。

したがって、コマンドを送信したいものは何でも、bash、zshのインスタンスを作成する必要があると思います。次に、そのサブプロセスのstdout / stderr fdをxtermのインスタンスに接続し、stdinをメインプログラムに接続します。メインプログラムは、xtermからの入力とbashに送信するコマンドを多重化します(したがって、それらは実行され、 xterm で示されます)。

bash ----------------------> xterm
    \--< your.py <----------/

いくつかの同様のスイッチがあるurxvtreveilsのマンページ:urxvt

-embed windowid
urxvt にそのウィンドウを既存のウィンドウに埋め込むように指示します。これにより、アプリケーションはターミナルを簡単に埋め込むことができます。[ ... ] このオプションの使用方法を示す短い Gtk2-perl スニペットを次に示します (より長い例は doc/embed にあります)。

私の $rxvt = 新しい Gtk2::Socket;
$rxvt->signal_connect_after (realize => sub { my $xid = $_[0]->window->get_xid;
system "urxvt -embed $xid &";
});

-pty-fd ファイル記述子
urxvt に、コマンドを実行したり、新しい pty/tty ペアを作成したりせずに、指定されたファイル記述子を tty マスターとして使用するように指示します。これは、urxvt 内でプログラムを実行することなく、汎用端末エミュレーターとして urxvt を駆動したい場合に便利です。

このオプションの使用方法を示す perl の例を次に示します (より長い例は doc/pty-fd にあります)。

IO::Pty を使用します。
Fcntl を使用します。

私の $pty = 新しい IO::Pty;
fcntl $pty, F_SETFD, 0; # close-on-exec
システム "urxvt -pty-fd" をクリアします。(fileno $pty) . "&";
$pty を閉じます。

# 今 rxvt と通信し
ます my $slave = $pty->slave;
while () { print $slave "get \n" }

Python内からPTYを開くには、ptyモジュールが有望に見えます:http://docs.python.org/2/library/pty.html

興味深い読み物: http://sqizit.bartletts.id.au/2011/02/14/pseudo-terminals-in-python/

于 2013-02-08T12:07:45.913 に答える