如何在 Python 2.7 中写入带有 运行 程序的其他终端?
How to write to an other terminal with a running program in it in Python 2.7?
我目前正在 python 制作一个程序来打开我的世界服务器。我已经完成了 window,您可以在其中选择列表中的服务器并启动它或进行备份。当你启动它时,一个新的终端打开(os.system('gnome-terminal...')
)并且 java 程序启动。有没有办法从第一个终端向这个 java 程序发送一些文本(比如命令)?
我用子流程尝试了很多东西,但没有令人满意的结果。
编辑:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import gtk
import re
import os
import time
active_button = 0
servers = [["Server 1","/home/myname/Desktop/server1","server.jar"],
["Serveur 2","/home/myname/Desktop/server2","server.jar"]]
def button_selection(button, num):
global active_button
state=button.state
if state >= 1:
active_button = int(num)
def validation(widget):
path = servers[active_button][1]
server = servers[active_button][2]
command = """gnome-terminal --working-directory="%s" -e 'java -jar %s'""" % (path, server)
print(command)
os.system(command)
def save(widget):
path = servers[active_button][1]
server = servers[active_button][2]
print "cp -a '%s' /home/myname/Documents/backups_minecraft_servers/%s" % (path+"/world", time.strftime("%d_%m_%Y-%T"))
os.system("cp -a '%s' /home/myname/Documents/backups_minecraft_servers/%s" % (path+"/world", time.strftime("%d_%m_%Y-%T")))
print("Backup finished")
def main():
window = gtk.Window()
vbox = gtk.VBox()
hbox = gtk.HBox()
validate = gtk.Button("Validate")
validate.connect("clicked", validation)
backup = gtk.Button("Backup")
backup.connect("clicked", save)
hbox.pack_start(validate)
hbox.pack_start(vbox)
hbox.pack_start(backup)
buttons = [gtk.RadioButton(None, servers[0][0])]
vbox.pack_start(buttons[0])
for server in servers[1:]:
buttons.append(gtk.RadioButton(buttons[0], server[0]))
vbox.pack_start(buttons[-1])
for i in range(len(buttons)):
buttons[i].connect("toggled", button_selection, i)
window.add(hbox)
window.show_all()
gtk.main()
if __name__=="__main__":
main()
首先,永远不要使用 os.system
。始终使用 subprocess
模块来启动新进程,因为它可以更好地处理许多边缘情况。 subprocess.check_call
可以做 os.system
可以做的一切,甚至更多,它会检查错误,这是 os.system
做不到的。
其次,不要使用 gnome-terminal
创建交互式终端到 运行 您的子进程!而是创建一个伪终端(pty);这样你的程序就可以保持对 child 行为的控制。在引擎盖下,这就是像 gnome-terminal
这样的程序本身的工作方式:它为 shell 和 shell 到 运行 中启动的程序创建一个 pty,然后它从 pty 读取并以图形方式呈现结果。
您的程序可以为您想要 运行 的每个 child 程序创建一个 pty,然后您的程序可以与 child 程序完全一样 gnome-terminal
能够。您可以使用 Python 标准库中的 pty
模块来执行此操作,但您可能需要考虑使用 pexpect
包,因为它大大简化了过程。
如果你不需要一个完整的终端,你可以通过打开一个管道到 child 进程来更简单地做到这一点。标准库中的 subprocess
模块提供了 Popen
class 可用于执行此操作。
在您的具体情况下,我建议 pexpect
。它易于使用,将 "do the right thing" 用于此类工作。
我目前正在 python 制作一个程序来打开我的世界服务器。我已经完成了 window,您可以在其中选择列表中的服务器并启动它或进行备份。当你启动它时,一个新的终端打开(os.system('gnome-terminal...')
)并且 java 程序启动。有没有办法从第一个终端向这个 java 程序发送一些文本(比如命令)?
我用子流程尝试了很多东西,但没有令人满意的结果。
编辑:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import gtk
import re
import os
import time
active_button = 0
servers = [["Server 1","/home/myname/Desktop/server1","server.jar"],
["Serveur 2","/home/myname/Desktop/server2","server.jar"]]
def button_selection(button, num):
global active_button
state=button.state
if state >= 1:
active_button = int(num)
def validation(widget):
path = servers[active_button][1]
server = servers[active_button][2]
command = """gnome-terminal --working-directory="%s" -e 'java -jar %s'""" % (path, server)
print(command)
os.system(command)
def save(widget):
path = servers[active_button][1]
server = servers[active_button][2]
print "cp -a '%s' /home/myname/Documents/backups_minecraft_servers/%s" % (path+"/world", time.strftime("%d_%m_%Y-%T"))
os.system("cp -a '%s' /home/myname/Documents/backups_minecraft_servers/%s" % (path+"/world", time.strftime("%d_%m_%Y-%T")))
print("Backup finished")
def main():
window = gtk.Window()
vbox = gtk.VBox()
hbox = gtk.HBox()
validate = gtk.Button("Validate")
validate.connect("clicked", validation)
backup = gtk.Button("Backup")
backup.connect("clicked", save)
hbox.pack_start(validate)
hbox.pack_start(vbox)
hbox.pack_start(backup)
buttons = [gtk.RadioButton(None, servers[0][0])]
vbox.pack_start(buttons[0])
for server in servers[1:]:
buttons.append(gtk.RadioButton(buttons[0], server[0]))
vbox.pack_start(buttons[-1])
for i in range(len(buttons)):
buttons[i].connect("toggled", button_selection, i)
window.add(hbox)
window.show_all()
gtk.main()
if __name__=="__main__":
main()
首先,永远不要使用 os.system
。始终使用 subprocess
模块来启动新进程,因为它可以更好地处理许多边缘情况。 subprocess.check_call
可以做 os.system
可以做的一切,甚至更多,它会检查错误,这是 os.system
做不到的。
其次,不要使用 gnome-terminal
创建交互式终端到 运行 您的子进程!而是创建一个伪终端(pty);这样你的程序就可以保持对 child 行为的控制。在引擎盖下,这就是像 gnome-terminal
这样的程序本身的工作方式:它为 shell 和 shell 到 运行 中启动的程序创建一个 pty,然后它从 pty 读取并以图形方式呈现结果。
您的程序可以为您想要 运行 的每个 child 程序创建一个 pty,然后您的程序可以与 child 程序完全一样 gnome-terminal
能够。您可以使用 Python 标准库中的 pty
模块来执行此操作,但您可能需要考虑使用 pexpect
包,因为它大大简化了过程。
如果你不需要一个完整的终端,你可以通过打开一个管道到 child 进程来更简单地做到这一点。标准库中的 subprocess
模块提供了 Popen
class 可用于执行此操作。
在您的具体情况下,我建议 pexpect
。它易于使用,将 "do the right thing" 用于此类工作。