如何在Python GUI中集成可填充进程/线程?

时间:2015-12-15 08:34:46

标签: python multithreading kill-process

善良的一切,我对python真的很陌生,我正面临着一个我无法完全掌握的任务。

我已经创建了一个与Tkinter的界面,这应该可以完成一些显而易见的功能。 点击"开始"按钮两个线程/进程将启动(每个调用多个子函数),主要从串行端口读取数据(当然每个进程一个端口)并将它们写入文件。 I / O操作在while循环中循环,具有非常高的计数器,以允许它们几乎无限期地继续前进。

"停止"按钮应该停止采集,基本上它应该:

  1. 杀死读/写线程
  2. 关闭文件
  3. 关闭串口
  4. 不幸的是,我仍然不明白如何完成第1点,即:如何在不杀死整个GUI的情况下创建可填充线程。有没有办法做到这一点?

    谢谢大家!

2 个答案:

答案 0 :(得分:1)

首先,您必须选择是否要使用线程或进程。

我不会过分分歧,google it;)无论如何,这里有一些事情需要考虑:在线程之间建立通信比在进程之间建立通信要容易得多;在Python中,所有线程都将在同一个CPU核心上运行(参见Python GIL),但子进程可能使用多个核心。

<强>过程

如果您使用的是子流程,则有两种方式:subprocess.Popenmultiprocessing.Process。使用Popen可以运行任何内容,而Process为运行python代码提供了一个更简单的类似线程的接口,python代码是子进程中项目的一部分。

两者都可以使用terminate方法杀死。

请参阅multiprocessingsubprocess

的文档

当然,如果你想要一个更优雅的退出,你需要向子流程发送一个“退出”消息,而不是只是终止它,这样它就有机会进行清理。你可以这样做,例如通过写入它的标准输入。该进程应该从stdin读取,当它收到消息“exit”时,它应该在退出之前做任何你需要的事情。

<强>线程

对于线程,你必须实现自己的停止机制,而不是使用像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,它不再可用。

答案 1 :(得分:0)

首先,您可以使用subprocess.Popen()生成子进程,之后您可以使用Popen.terminate()来终止它们。

请注意,如果您愿意,也可以在单个Python线程中执行所有操作,无需子进程。完全可能&#34;复用&#34;在单个事件循环中从多个端口读取。