尽管我讨厌反刍问题,但在我将要提出的下一个问题上取得结果是必要的。
使用python3,tkinter和subprocess包,我的目标是编写一个控制面板,用一组特定的命令启动和停止不同的终端窗口,以运行ROS application stack的应用程序/会话,包括核心。
因此,代码看起来像我希望控制的每个可执行文件:
class TestProc(object):
def __init__(self):
pass
def start(self):
self.process = subprocess.Popen(["gnome-terminal", "-c", "'cd /path/to/executable/script.sh; ./script.sh'"])
print("Process started.")
def stop(self):
self.process.terminate()
print("Process terminated.")
目前,可以启动终端窗口和分配的命令/进程,但仍存在两个问题:
gnome-terminal
将启动终端窗口,然后解除对内部进程的控制;因此,一旦开始,我就没有进一步的控制权。一个可能的解决方案是使用xterm
,但这带来了一系列其他问题。我需要有来自用户的.bashrc
和/或export
的变量cd
或roslaunch
将无法用于终端会话,可能是由于执行顺序(例如,命令在加载bash配置文件之前运行)阻止任何可用的终端因此,问题响起:我如何能够启动和停止在用户环境中最多运行两个命令/进程的新终端窗口?
您可以采取几种方法,最灵活的方法也是最复杂的方法,因此您需要考虑是否需要这样做。
如果只需要显示脚本的输出,则只需将输出传递给文件或命名管道即可。然后,您可以通过读取/拖尾文件来捕获该输出。这是最简单的,只要脚本实际上不需要任何用户交互。
如果您真的只需要生成在后台运行的脚本,并且您需要模拟用户交互但实际上不需要接受实际的用户输入,则可以使用expect
方法(使用pexpect库)。
如果您需要实际允许真实用户与程序交互,那么您有两种方法。首先,您可以将VTE widget嵌入到您的应用程序中,这是最无缝的集成,因为它将使终端看起来与您的应用程序无缝,但它也是最重的。
另一种方法是像你在这里一样启动gnome-terminal,这必然会产生一个新的窗口。
如果您需要同时编写一些交互脚本,同时允许一些用户输入,您可以通过在tmux会话中生成脚本来完成此操作。使用tmux send-keys
命令自动化月球交互部分,然后生成终端模拟器,供用户与tmux attach
交互。如果您需要在自动部件和交互式部件之间来回切换,您可以将此方法与期望结合起来。