0

将命令输出重定向到 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/#需要刷新。此外,我真的不喜欢必须创建文件进行通信的想法。有没有直接的解决办法?

4

2 回答 2

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 脚本,则可以跳过这一步。对此的任何帮助都会很棒!

于 2014-08-12T14:46:34.003 回答
0

在 VTE 中,您使用 terminal.feed("string")

vte_terminal_feed

使用 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 模块。这将要求您生成自己的提示,因此它是获得所需内容的更具体的选项。

于 2014-08-11T02:43:14.360 回答