异步等待子处理?

Posted

技术标签:

【中文标题】异步等待子处理?【英文标题】:Asynchronous waiting with subprocessing? 【发布时间】:2022-01-02 08:55:43 【问题描述】:

我在 Tkinter 脚本中有一个函数,它利用 subprocess.Popen.wait() 一直冻结我的 GUI。在浏览了一些文档(1 和2)之后,我发现我需要使用asyncio 通过异步等待来解决这个问题,但我很困惑:

注意:该函数是使用忙循环(非阻塞调用)实现的 和短暂的睡眠)。使用 asyncio 模块进行异步等待: 请参阅 asyncio.create_subprocess_exec。

这是否意味着我必须为我的 wait() 函数创建一个子进程?

另外,这是我目前所拥有的:

def foo(self)
    try:
        self.proc = subprocess.Popen(["python", "someModule.py"])
        try:
            self.proc.wait(11) # <-- freezes GUI
        except Exception as l:
            someFunc()
    except Exception as e:
        print(e)

注意:wait() 上的 TimeoutException 捕获用作另一个函数开始执行的指示符,而 wait() 的成功执行(即返回值 0)则相反。此外,我的目标是在成功执行子进程时激活我的 Tkinter 脚本中的计时器,如前所述,由 TimeoutException 指示。 Tkinter 接口将始终运行,而子进程将仅在用户输入时启动,并且类似地,在用户输入时结束(或者如果它意外崩溃)。

编辑:someModule.py 是一个脚本,用于激活外部数据采集蓝牙设备。它必须 (1) 建立与设备的连接,如果 (1) 成功,则 (2) 开始收集数据。功能 (1) 将等待 10 秒以建立与蓝牙设备的连接。如果 10 秒后没有建立连接,someModule.py(即子进程)会打印错误并终止。这就是 wait() 执行 11 秒的原因。

如何实现异步等待?

【问题讨论】:

等待块,是的。相反应该发生什么?当进程运行/终止时你想发生什么? 你是否尝试在线程中执行foo() @john-hen 感谢您的反馈。我不太确定我完全理解你的意思;您是说总是会执行 except 块,还是说我应该指定 TimeoutExpired 作为要捕获的异常?如果是前者,则不正确,因为当 wait() 的返回值为 0(零)时,不进入 except 块。 @MaxNoe 查看编辑。 tkinter 是不同于 asyncio 的异步“种类”。不能直接将两者一起使用。您必须编写自己的繁忙循环,使用tkinter 的睡眠方式。 【参考方案1】:

解决方法:通过thread 执行 foo() 解决了 GUI 冻结问题。

import threading

def thread(self):
    t1 = threading.Thread(target=foo)
    t1.start() # will terminate independently upon completion of foo()

【讨论】:

以上是关于异步等待子处理?的主要内容,如果未能解决你的问题,请参考以下文章

Java主线程如何等待子线程执行结束(转)

文件异步到达的相关数据处理管道

异步/等待和多处理

快速错误处理和异步等待

AlamoFire downloadProgress 完成处理程序到异步/等待

同步阻塞同步非阻塞异步阻塞异步非阻塞--简明介绍