首先,您必须选择是使用线程还是进程。
我不会过多讨论差异,google it ;) 无论如何,这里有一些事情需要考虑:在线程之间建立通信比在进程之间建立通信要容易得多;在 Python 中,所有线程都将在同一个 CPU 内核上运行(参见 Python GIL),但子进程可能使用多个内核。
流程
如果您使用子流程,有两种方法:subprocess.Popen 和multiprocessing.Process。使用Popen,您可以运行任何东西,而Process 提供了一个更简单的类似线程的接口来运行python 代码,它是您项目中子进程的一部分。
两者都可以使用terminate 方法杀死。
请参阅 multiprocessing 和 subprocess 的文档
当然,如果你想要一个更优雅的退出,你会想要向子进程发送一个“退出”消息,而不是仅仅终止它,以便它有机会进行清理。你可以这样做,例如通过写入其标准输入。该进程应该从标准输入读取,当它收到“退出”消息时,它应该在退出之前做任何你需要的事情。
线程
对于线程,你必须实现自己的停止机制,而不是使用像process.terminate() 这样暴力的东西。
通常,一个线程在一个循环中运行,并在该循环中检查一个显示 stop 的标志。然后你跳出循环。
我通常是这样的:
class MyThread(Thread):
def __init__(self):
super(Thread, self).__init__()
self._stop_event = threading.Event()
def run(self):
while not self._stop_event.is_set():
# do something
self._stop_event.wait(SLEEP_TIME)
# clean-up before exit
def stop(self, timeout):
self._stop_event.set()
self.join(timeout)
当然,你需要一些异常处理等,但这是基本思想。
编辑:评论中问题的答案
thread.start_new_thread(your_function) 启动一个新线程,这是正确的。另一方面,threading 模块为您提供了更高级的 API。
使用threading 模块,您可以使用:
t = threading.Thread(target=your_function)
t.start()
或者您可以创建自己的类,该类继承自Thread,并将您的功能放入run 方法中,如上例所示。然后,当用户单击开始按钮时,您可以:
t = MyThread()
t.start()
您应该将 t 变量存储在某处。确切的位置取决于您如何设计应用程序的其余部分。我可能会有一些对象将所有活动线程保存在一个列表中。
当用户点击停止时,您应该:
t.stop(some_reasonable_time_in_which_the_thread_should_stop)
之后,您可以从列表中删除t,它不再可用。