我想将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/