使用Tkinter进行线程处理

时间:2013-06-16 19:40:38

标签: python multithreading user-interface tkinter python-multithreading

我需要能够将控制c发送到我开始的新线程。我该怎么做呢我可以启动线程,但是我需要像使用控件c一样在命令行中停止。

from Tkinter import *
import threading # should use the threading module instead!
import Queue
import os


def show1():
    os.system('ola_recorder -p MyRecord -i 0')

def show2 ():
    os.system('ola_recorder -p MyRecord ')

def stop ():
    os.system('^c')




t = threading.Thread(name='Show2', target=show2)





root = Tk()
b = Button(root, text="Show 1", command=lambda: thread.start_new(show1, ()))
b.pack()

b2 = Button(root, text="Show 2", command=lambda: t.start())
b2.pack()



root.mainloop()

1 个答案:

答案 0 :(得分:4)

首先,你正在做的事情不起作用:

每次调用os.system只会调用平台的system(或某些Windows平台上的_system)函数,每次都会创建一个全新的shell进程。所以,你无法用os.system做任何事情来影响另一个电话。


如果要将^ C发送到任意进程,可以使用os.kill执行此操作。为了便携,你必须做这样的事情:

def send_ctrl_c(pid):
    try:
        sig = signal.CTRL_C_EVENT
    except AttributeError:
        sig = signal.SIGINT
    else:
        os.signal(pid, sig)

但是,您需要其他进程的pid才能执行此操作,而os.system并未提供此功能。


所以,正确的做法是使用subprocess模块:

proc2 = None

def show2():
    global proc2
    proc2 = subprocess.Popen('ola_recorder -p MyRecord', shell=True)
    proc2.wait()

由于没有充分的理由在这里使用shell,你可能最好不要传递Popen一个args列表,而不是一个字符串,然后离开shell=True。当然,如果不将proc2粘贴到全球范围内会更加清晰,但我会忽略这个玩具示例。

无论如何,现在你可以得到pid并使用它:

def stop():
    send_ctrl_c(proc2.pid)

但是,如果您要这样做,您也可以直接使用Popen对象。有关您可以使用它的详细信息,请参阅the docs,但这是一个快速版本:

def stop():
    global proc2
    try:
        sig = signal.CTRL_C_EVENT
    except AttributeError:
        sig = signal.SIGINT
    proc.send_signal(sig)

当您调用stop时,该过程将被完全杀死,就像它已收到^ C(POSIX)一样,或尽可能接近,就好像它已收到^ C(Windows),{ {1}}调用将返回(带有-2,至少在POSIX上),您的线程也会完成。


最后一点:你几乎不想直接使用wait模块,也不想重用thread个对象。 所以,而不是:

threading.Thread

......或者这个:

b = Button(root, text="Show 1", command=lambda: thread.start_new(show1, ()))

......这样做:

b2 = Button(root, text="Show 2", command=lambda: t.start())

当然,非玩具程序应该避免使用全局,并且希望跟踪所有现有线程而不是最后一个(如果在后台线程已经运行时允许您单击按钮) ),并且可能希望在退出时def start2(): global t2 t2 = threading.Thread(name='Show2', target=show2) t2.start() 所有线程。