亲切,我是 python 的新手,我正面临一项我无法完全掌握的任务。
我已经使用 Tkinter 创建了一个界面,它应该可以完成几个看似简单的壮举。 通过单击“开始”按钮,将启动两个线程/进程(每个调用多个子函数),它们主要从串行端口(当然每个进程一个端口)读取数据并将它们写入文件。 I/O 操作在具有非常高计数器的 while 循环中循环,以允许它们几乎无限期地继续进行。
“停止”按钮应该停止采集,本质上它应该:
- 杀死读/写线程
- 关闭文件
- 关闭串口
不幸的是,我仍然不明白如何完成第 1 点,即:如何在不杀死整个 GUI 的情况下创建可杀死的线程。有什么办法吗?
谢谢大家!
最佳答案
首先,您必须选择是要使用线程还是进程。
我不会过多地讨论差异,google 一下;)无论如何,这里有一些事情需要考虑:在线程之间建立通信比在进程之间建立通信要容易得多;在 Python 中,所有线程都将在同一个 CPU 核心上运行(参见 Python GIL ),但子进程可以使用多个核心。
进程
如果使用子进程,有两种方式:subprocess.Popen
和multiprocessing.Process
。使用 Popen
你可以运行任何东西,而 Process
提供了一个更简单的类似线程的接口(interface)来运行 python 代码,它是你项目的子进程的一部分。
两者都可以使用 terminate
方法终止。
请参阅 multiprocessing
的文档和 subprocess
当然,如果您想要更优雅地退出,您会希望向子进程发送“退出”消息,而不是仅仅终止它,以便它有机会进行清理。你可以这样做,例如通过写入其标准输入。该进程应该从 stdin 读取,当它收到消息“exit”时,它应该在退出前执行您需要的任何操作。
线程
对于线程,你必须实现自己的停止机制,而不是使用像process.terminate()
这样暴力的东西。
通常,一个线程在一个循环中运行,在该循环中您检查是否有一个标记为停止。然后你从循环中跳出。
我通常有这样的东西:
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
,它不再可用。
关于python - 如何在 Python GUI 中集成可终止的进程/线程?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34284335/