如何在 GUI 中并行 运行 两个非终止脚本?
How to run two non-terminating scripts in parallel in a GUI?
我知道我可以通过打开两个终端 windows 轻松地手动完成此操作。我试图通过创建一个带有两个按钮的 GUI 来尽可能地自动化该过程。一个连接 运行 听众,一个 运行 说话者。
这是我的代码:
#python 3
#from tkinter import *
#from tkinter import ttk
#python 2
from Tkinter import *
import ttk
import time
import subprocess
import paramiko
def calculate(*args):
try:
value = float(feet.get())
meters.set((0.3048 * value * 10000.0 + 0.5)/10000.0)
except ValueError:
pass
def connect():
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect('192.168.1.2', username='pi', password='raspberry')
stdin, stdout, stderr = ssh.exec_command('cd')
stdin, stdout, stderr = ssh.exec_command('roscore &')
time.sleep(20)
stdin, stdout, stderr = ssh.exec_command('\n')
stdin, stdout, stderr = ssh.exec_command('cd scripts')
stdin, stdout, stderr = ssh.exec_command('python /home/pi/scripts/listener2.py')
return
def run():
stdin, stdout, stderr = ssh.exec_command('python ES96_Vivaldi/talker2.py')
root = Tk()
mainframe = ttk.Frame(root, padding="3 3 12 12")
mainframe.grid(column=0, row=0, sticky=(N, W, E, S))
mainframe.columnconfigure(0, weight=1)
mainframe.rowconfigure(0, weight=1)
ttk.Button(mainframe, text="Connect", command=connect).grid(column=1, row=3, sticky=S)
ttk.Button(mainframe, text="Run", command=run).grid(column=3, row=3, sticky=S)
ttk.Label(mainframe, text="Click 'Connect' to establish link.").grid(column=1, row=1, sticky=W)
ttk.Label(mainframe, text="Click 'Run' to control using the arrow keys").grid(column=1, row=2, sticky=W)
for child in mainframe.winfo_children(): child.grid_configure(padx=5, pady=5)
root.mainloop()
它会打开一个带有连接按钮和 运行 按钮的小型 GUI。 Connect 工作正常,但由于 listener2.py 脚本没有终止,GUI 冻结并且我无法按下 运行 按钮(以相反的顺序尝试时同样的问题)。
有没有办法启动一个脚本并将其 运行 留在后台,这样 GUI 就不会被冻结,这样我就可以启动下一个脚本?
谢谢!
您可以 运行 后台线程中的处理程序。在您当前的设置中,处理程序不会向 gui 提供任何反馈,因此实际上只需将按钮命令切换为启动线程的函数即可。
我添加了一些代码来禁用按钮,这样处理程序只能启动一次。诀窍是您需要一些地方来存储按钮小部件,以便您以后可以再次访问它们。
#python 3
#from tkinter import *
#from tkinter import ttk
#python 2
from Tkinter import *
import ttk
import time
import subprocess
import paramiko
import threading
# keep track of widgets for event handlers
widget_track = {}
# event handler creates connect thread
def connect_evt():
t = threading.Thread(target=connect)
t.daemon = True
t.start()
widget_track['connect'].config(text="Connected", state="disabled", command=None)
def connect():
time.sleep(5) # todo: temporary for test
return
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect('192.168.1.2', username='pi', password='raspberry')
stdin, stdout, stderr = ssh.exec_command('cd')
stdin, stdout, stderr = ssh.exec_command('roscore &')
time.sleep(20)
stdin, stdout, stderr = ssh.exec_command('\n')
stdin, stdout, stderr = ssh.exec_command('cd scripts')
stdin, stdout, stderr = ssh.exec_command('python /home/pi/scripts/listener2.py')
return
# event handler creates run thread
def run_evt():
t = threading.Thread(target=run)
t.daemon = True
t.start()
widget_track['run'].config(text="Running", state="disabled", command=None)
def run():
time.sleep(5) # todo: temporary for test
return
stdin, stdout, stderr = ssh.exec_command('python ES96_Vivaldi/talker2.py')
root = Tk()
mainframe = ttk.Frame(root, padding="3 3 12 12")
mainframe.grid(column=0, row=0, sticky=(N, W, E, S))
mainframe.columnconfigure(0, weight=1)
mainframe.rowconfigure(0, weight=1)
# connect button starts connect background thread
btn = ttk.Button(mainframe, text="Connect", command=connect_evt)
btn.grid(column=1, row=3, sticky=S)
widget_track['connect'] = btn
# run button start run background thread
btn = ttk.Button(mainframe, text="Run", command=run_evt)
btn.grid(column=3, row=3, sticky=S)
widget_track['run'] = btn
ttk.Label(mainframe, text="Click 'Connect' to establish link.").grid(column=1, row=1, sticky=W)
ttk.Label(mainframe, text="Click 'Run' to control using the arrow keys").grid(column=1, row=2, sticky=W)
for child in mainframe.winfo_children(): child.grid_configure(padx=5, pady=5)
root.mainloop()
我知道我可以通过打开两个终端 windows 轻松地手动完成此操作。我试图通过创建一个带有两个按钮的 GUI 来尽可能地自动化该过程。一个连接 运行 听众,一个 运行 说话者。
这是我的代码:
#python 3
#from tkinter import *
#from tkinter import ttk
#python 2
from Tkinter import *
import ttk
import time
import subprocess
import paramiko
def calculate(*args):
try:
value = float(feet.get())
meters.set((0.3048 * value * 10000.0 + 0.5)/10000.0)
except ValueError:
pass
def connect():
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect('192.168.1.2', username='pi', password='raspberry')
stdin, stdout, stderr = ssh.exec_command('cd')
stdin, stdout, stderr = ssh.exec_command('roscore &')
time.sleep(20)
stdin, stdout, stderr = ssh.exec_command('\n')
stdin, stdout, stderr = ssh.exec_command('cd scripts')
stdin, stdout, stderr = ssh.exec_command('python /home/pi/scripts/listener2.py')
return
def run():
stdin, stdout, stderr = ssh.exec_command('python ES96_Vivaldi/talker2.py')
root = Tk()
mainframe = ttk.Frame(root, padding="3 3 12 12")
mainframe.grid(column=0, row=0, sticky=(N, W, E, S))
mainframe.columnconfigure(0, weight=1)
mainframe.rowconfigure(0, weight=1)
ttk.Button(mainframe, text="Connect", command=connect).grid(column=1, row=3, sticky=S)
ttk.Button(mainframe, text="Run", command=run).grid(column=3, row=3, sticky=S)
ttk.Label(mainframe, text="Click 'Connect' to establish link.").grid(column=1, row=1, sticky=W)
ttk.Label(mainframe, text="Click 'Run' to control using the arrow keys").grid(column=1, row=2, sticky=W)
for child in mainframe.winfo_children(): child.grid_configure(padx=5, pady=5)
root.mainloop()
它会打开一个带有连接按钮和 运行 按钮的小型 GUI。 Connect 工作正常,但由于 listener2.py 脚本没有终止,GUI 冻结并且我无法按下 运行 按钮(以相反的顺序尝试时同样的问题)。
有没有办法启动一个脚本并将其 运行 留在后台,这样 GUI 就不会被冻结,这样我就可以启动下一个脚本?
谢谢!
您可以 运行 后台线程中的处理程序。在您当前的设置中,处理程序不会向 gui 提供任何反馈,因此实际上只需将按钮命令切换为启动线程的函数即可。
我添加了一些代码来禁用按钮,这样处理程序只能启动一次。诀窍是您需要一些地方来存储按钮小部件,以便您以后可以再次访问它们。
#python 3
#from tkinter import *
#from tkinter import ttk
#python 2
from Tkinter import *
import ttk
import time
import subprocess
import paramiko
import threading
# keep track of widgets for event handlers
widget_track = {}
# event handler creates connect thread
def connect_evt():
t = threading.Thread(target=connect)
t.daemon = True
t.start()
widget_track['connect'].config(text="Connected", state="disabled", command=None)
def connect():
time.sleep(5) # todo: temporary for test
return
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect('192.168.1.2', username='pi', password='raspberry')
stdin, stdout, stderr = ssh.exec_command('cd')
stdin, stdout, stderr = ssh.exec_command('roscore &')
time.sleep(20)
stdin, stdout, stderr = ssh.exec_command('\n')
stdin, stdout, stderr = ssh.exec_command('cd scripts')
stdin, stdout, stderr = ssh.exec_command('python /home/pi/scripts/listener2.py')
return
# event handler creates run thread
def run_evt():
t = threading.Thread(target=run)
t.daemon = True
t.start()
widget_track['run'].config(text="Running", state="disabled", command=None)
def run():
time.sleep(5) # todo: temporary for test
return
stdin, stdout, stderr = ssh.exec_command('python ES96_Vivaldi/talker2.py')
root = Tk()
mainframe = ttk.Frame(root, padding="3 3 12 12")
mainframe.grid(column=0, row=0, sticky=(N, W, E, S))
mainframe.columnconfigure(0, weight=1)
mainframe.rowconfigure(0, weight=1)
# connect button starts connect background thread
btn = ttk.Button(mainframe, text="Connect", command=connect_evt)
btn.grid(column=1, row=3, sticky=S)
widget_track['connect'] = btn
# run button start run background thread
btn = ttk.Button(mainframe, text="Run", command=run_evt)
btn.grid(column=3, row=3, sticky=S)
widget_track['run'] = btn
ttk.Label(mainframe, text="Click 'Connect' to establish link.").grid(column=1, row=1, sticky=W)
ttk.Label(mainframe, text="Click 'Run' to control using the arrow keys").grid(column=1, row=2, sticky=W)
for child in mainframe.winfo_children(): child.grid_configure(padx=5, pady=5)
root.mainloop()