3

我想将一个嵌入xtermpyqt4部件并与之通信。特别是我希望能够打印到它并在其上执行命令(这样它在执行命令后返回到正常的用户提示符,就像普通的 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_())
4

1 回答 1

4

要将 a 嵌入xterm到您的一个窗口中,您应该使用:

-into windowId 给定一个 X 窗口标识符(一个十进制整数),xterm 会将其顶级 shell 小部件重新设置为该窗口。这用于在其他应用程序中嵌入 xterm。

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

此选项允许 xterm 用作现有程序的输入和输出通道,有时用于专门的应用程序

所以,我认为你必须创建你的 bash、zsh 实例,无论你想将命令发送到什么地方。然后将该子进程的 stdout/stderr fd 连接到您的 xterm 实例,并将标准输入连接到您的主程序,然后多路复用来自 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 作为通用终端仿真器来驱动,而无需在其中运行程序,这将非常有用。

这是 perl 中的一个示例,说明了如何使用此选项(更长的示例 > 在 doc/pty-fd 中):

使用 IO::Pty;
使用 Fcntl;

我的 $pty = 新 IO::Pty;
fcntl $pty,F_SETFD,0;# 清除关闭执行
系统“urxvt -pty-fd”。(文件号 $pty)。"&";
关闭 $pty;

# 现在与 rxvt 通信
my $slave = $pty->slave;
while () { print $slave "得到\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 回答