python-将xterm嵌入QWidget并与之通信

我想将xterm嵌入pyqt4小部件并与其通信.特别是我希望能够打印到它并在其上执行命令(以使它在执行命令后像普通的shell一样返回到正常的用户提示符).考虑下面的最小示例.我该如何运作?

#!/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_())

解决方法:

要将xterm嵌入您的Windows之一,您应该使用:

-into windowId Given an X window identifier (a decimal integer), xterm will reparent its top-level shell widget to that window. This is used
to embed xterm within other applications.

xterm本身与启动的shell(bash等)进行对话.因此,您必须找到一种与启动的Shell对话的方法.您可以通过-Sccn标志将打开的文件描述符传递给xterm:

This option allows xterm to be used as an input and output channel for an existing program and is sometimes used in specialized applications

因此,我想无论您要将命令发送到什么地方,都必须创建bash,zsh实例.然后将该子进程的stdout / stderr fd连接到您的xterm实例,并将stdin连接到您的主程序,然后将来自xterm的输入和您要发送到bash的命令多路复用(这样它们将被执行并被在xterm中显示).

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

urxvt的联机帮助页揭示了urxvt具有一些类似的开关:

-embed windowid
Tells urxvt to embed its windows into an already-existing window,
which enables applications to easily embed a terminal.
[ … ]
Here is a short Gtk2-perl snippet that illustrates how this option can be used (a longer
example is in doc/embed):

my $rxvt = new Gtk2::Socket;
$rxvt->signal_connect_after (realize => sub {
my $xid = $_[0]->window->get_xid;
system “urxvt -embed $xid &”;
});

-pty-fd file descriptor
Tells urxvt NOT to execute any commands or create a new pty/tty pair but instead use the given file descriptor as the tty master. This is useful if you want to drive urxvt as a generic terminal emulator without having to run a program within it.

Here is a example in perl that illustrates how this option can be used (a longer example > is in doc/pty-fd):

use IO::Pty;
use Fcntl;

my $pty = new IO::Pty;
fcntl $pty, F_SETFD, 0; # clear close-on-exec
system “urxvt -pty-fd ” . (fileno $pty) . “&”;
close $pty;

# now communicate with rxvt
my $slave = $pty->slave;
while () { print $slave “got \n” }

要从python中打开PTY,pty模块看起来很有希望:http://docs.python.org/2/library/pty.html

有趣的阅​​读:http://sqizit.bartletts.id.au/2011/02/14/pseudo-terminals-in-python/

上一篇:阿里云云服务器 ECS和云数据库 PolarDB的简单使用


下一篇:程序员Docker进阶