善良的一切,我对python真的很陌生,我正面临着一个我无法完全掌握的任务。
我已经创建了一个与Tkinter的界面,这应该可以完成一些显而易见的功能。 点击"开始"按钮两个线程/进程将启动(每个调用多个子函数),主要从串行端口读取数据(当然每个进程一个端口)并将它们写入文件。 I / O操作在while循环中循环,具有非常高的计数器,以允许它们几乎无限期地继续前进。
"停止"按钮应该停止采集,基本上它应该:
不幸的是,我仍然不明白如何完成第1点,即:如何在不杀死整个GUI的情况下创建可填充线程。有没有办法做到这一点?
谢谢大家!
答案 0 :(得分:1)
首先,您必须选择是否要使用线程或进程。
我不会过分分歧,google it;)无论如何,这里有一些事情需要考虑:在线程之间建立通信比在进程之间建立通信要容易得多;在Python中,所有线程都将在同一个CPU核心上运行(参见Python GIL),但子进程可能使用多个核心。
<强>过程强>
如果您使用的是子流程,则有两种方式:subprocess.Popen
和multiprocessing.Process
。使用Popen
可以运行任何内容,而Process
为运行python代码提供了一个更简单的类似线程的接口,python代码是子进程中项目的一部分。
两者都可以使用terminate
方法杀死。
当然,如果你想要一个更优雅的退出,你需要向子流程发送一个“退出”消息,而不是只是终止它,这样它就有机会进行清理。你可以这样做,例如通过写入它的标准输入。该进程应该从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;在单个事件循环中从多个端口读取。