将命令输出重定向到VTE终端的最佳方法是什么?
我带着这个想法:
在VTE上执行:
tty > /usr/tmp/terminal_number
然后从python程序中读取文件:
with open('/usr/tmp/terminal_number', 'r') as f:
self.VTE_redirect_path=f.readline()
然后执行bash命令,例如:
os.system('''echo "foo" > {0}'''.format(self.VTE_redirect_path))
此方法的问题是需要刷新包含terminal_number
的文件/dev/pts/#
。此外,我真的不喜欢必须创建文件进行通信的想法。有没有直接的解决方案?
答案 0 :(得分:2)
@Quentin你给我的解决方案打印控制台输出非常糟糕(它没有缩进)所以我不得不使用我的解决方案。这是一个明显的例子:
from gi.repository import Gtk, GObject, Vte, GLib
import os, time, threading
def command_on_VTE(self,command):
length=len(command)
self.terminal.feed_child(command, length)
class TheWindow(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self, title="inherited cell renderer")
self.set_default_size(600, 300)
self.terminal=Vte.Terminal()
self.terminal.fork_command_full(
Vte.PtyFlags.DEFAULT, #default is fine
os.environ['HOME'], #where to start the command?
["/bin/bash"], #where is the emulator?
[], #it's ok to leave this list empty
GLib.SpawnFlags.DO_NOT_REAP_CHILD,
None, #at least None is required
None,
)
#set up the interface
box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
#a scroll window is required for the terminal
scroller = Gtk.ScrolledWindow()
scroller.set_hexpand(True)
scroller.set_vexpand(True)
scroller.add(self.terminal)
box.pack_start(scroller, False, True, 2)
self.add(box)
#To get the command to automatically run
#a newline(\n) character is used at the end of the
#command string.
command_on_VTE(self,'''tty > /tmp/terminal_number\n''') # Get the terminal ID
# read the terminal ID
while not os.path.exists("/tmp/terminal_number"):
time.sleep(0.1)
with open('/tmp/terminal_number', 'r') as f:
self.VTE_redirect_path=f.readline()
os.remove('/tmp/terminal_number')
# this cleans the vte
os.system('''printf "\\033c" > {0}'''.format(self.VTE_redirect_path))
# this calls the exemple
threading.Thread(target=self.make_a_test).start()
def make_a_test(self):
os.system('''ls -laR /home/ > {rdc}
echo "-------- The listing ended -------
Note that the input of the commands are not printed
" > {rdc}'''.format(rdc=self.VTE_redirect_path))
win = TheWindow()
win.connect("delete-event", Gtk.main_quit)
win.show_all()
Gtk.main()
我还没有找到一种方法来获取终端ID而没有通过创建临时文件。如果有一些方法可以将变量从VTE传递给python脚本,则可以跳过此步骤。对此的任何帮助都会很棒!
答案 1 :(得分:0)
在VTE中,您使用terminal.feed(“string”)
使用python Popen是执行命令的建议方法。 如果您想使用命令,那么您应该这样做。
#Uncomment the next line to get the print() function of python 3
#from __future__ import print_function
import os
import subprocess
from subprocess import Popen
command = "echo \"something\""
env = os.environ.copy()
try:
po = Popen(command, shell=True, stdout=subprocess.PIPE, stdin=subprocess.PIPE,
universal_newlines=True, env=env)
po.wait()
output, error_output = po.communicate()
if po.returncode:
print(error_output)
else:
print(output)
except OSError as e:
print('Execution failed:', e, file=sys.stderr)
如果你想将gtk与gtk vte一起使用,那就改为使用。
#place the following in a method of a vte instance
env = os.environ.copy()
try:
po = Popen(command, shell=True, stdout=subprocess.PIPE, stdin=subprocess.PIPE,
universal_newlines=True, env=env)
po.wait()
output, error_output = po.communicate()
if po.returncode:
print(error_output)
else:
self.feed(output) #here you're printing to your terminal.
except OSError as e:
print('Execution failed:', e, file=sys.stderr)
对于常规终端中最精细的控制,您可以尝试cmd module。这将要求您生成自己的提示,以便获得您想要的更具体的选项。