Python 中的事件驱动系统调用

2024-03-08

我正在尝试使用系统调用或子流程来实现事件驱动的流程。基本上我想启动一个非阻塞系统命令,并在完成该系统调用后,我想要调用一个函数。 这样我就可以启动 GUI 进度条,启动系统命令并让进度条继续,当系统调用完成时,让进度条停止。

我绝对不想做的是生成一个进程,获取其进程 ID 并在 while 循环中继续检查该进程的完成情况。

下面只是我想象的一个例子(所有这些都在一个类中)

def launchTool(self):

    self.progressbar.config(mode = 'indeterminate')
    self.progressbar.start(20)
    self.launchButton.config(state = 'disabled')
    self.configCombobox.config(state = 'disabled')

    ##  here the "onCompletion" is a pointer to a function
    call("/usr/bin/make psf2_dcf", shell=True, onCompletion = self.toolCompleted)


def onCompletion(self):

    print('DONE running Tool')

    self.progressbar.stop()
    self.launchButton.config(state = 'normal')
    self.configCombobox.config(state = 'normal')

为了避免轮询子进程的状态,您可以使用SIGCHLDUnix 上的信号。要将其与 tkinter 的事件循环结合起来,您可以使用自管技巧 http://cr.yp.to/docs/selfpipe.html。也有解决办法可能的 tkinter + 信号问题 https://mail.python.org/pipermail/tkinter-discuss/2011-January/002737.html无需定期唤醒事件循环。

#!/usr/bin/env python3
import logging
import os
import signal
import subprocess
import tkinter

info = logging.getLogger(__name__).info

def on_signal(pipe, mask, count=[0]):
    try:
        signals = os.read(pipe, 512)
    except BlockingIOError:
        return # signals have been already dealt with

    # from asyncio/unix_events.py
    #+start
    # Because of signal coalescing, we must keep calling waitpid() as
    # long as we're able to reap a child.
    while True:
        try:
            pid, status = os.waitpid(-1, os.WNOHANG)
        except ChildProcessError:
            info('No more child processes exist.')
            return
        else:
            if pid == 0:
                info('A child process is still alive. signals=%r%s',
                     signals, ' SIGCHLD'*(any(signum == signal.SIGCHLD
                                              for signum in signals)))
                return
            #+end
            # you could call your callback here
            info('{pid} child exited with status {status}'.format(**vars()))
            count[0] += 1
            if count[0] == 2:
                root.destroy() # exit GUI


logging.basicConfig(format="%(asctime)-15s %(message)s", datefmt='%F %T',
                    level=logging.INFO)
root = tkinter.Tk()
root.withdraw() # hide GUI

r, w = os.pipe2(os.O_NONBLOCK | os.O_CLOEXEC) 
signal.set_wakeup_fd(w) 
root.createfilehandler(r, tkinter.READABLE, on_signal)
signal.signal(signal.SIGCHLD, lambda signum, frame: None) # enable SIGCHLD
signal.siginterrupt(signal.SIGCHLD, False) # restart interrupted syscalls automatically
info('run children')
p = subprocess.Popen('sleep 4', shell=True)
subprocess.Popen('sleep 1', shell=True)
root.after(2000, p.send_signal, signal.SIGSTOP) # show that SIGCHLD may be delivered
root.after(3000, p.send_signal, signal.SIGCONT) # while the child is still alive
root.after(5000, lambda: p.poll() is None and p.kill()) # kill it
root.mainloop()
info('done')

Output

2015-05-20 23:39:50 run children
2015-05-20 23:39:51 16991 child exited with status 0
2015-05-20 23:39:51 A child process is still alive. signals=b'\x11' SIGCHLD
2015-05-20 23:39:52 A child process is still alive. signals=b'\x11' SIGCHLD
2015-05-20 23:39:53 A child process is still alive. signals=b'\x11' SIGCHLD
2015-05-20 23:39:54 16989 child exited with status 0
2015-05-20 23:39:54 No more child processes exist.
2015-05-20 23:39:54 done
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Python 中的事件驱动系统调用 的相关文章

随机推荐

  • MySQL 并发性,它是如何工作的以及我是否需要在我的应用程序中处理它

    我目前正在运行 MySQL 数据库 我的所有表都使用表引擎 InnoDB 每个登录我的应用程序的人都可以查看记录 我担心在某些时候两个用户可能会同时更新或插入记录 MySQL 是否能够优雅地处理这种类型的并发问题 还是我必须将其编程到我的代
  • PCRE 正则表达式反向引用有效,但子例程无效

    我正在尝试匹配文本 1 嘿嘿嘿嘿 2 嘿嘿嘿嘿 与正则表达式 a w 1 w b w w w c w 1 w Regex a火柴1完全 并且2完全 但最后一个 y Regex b完全匹配1 and 2 Regex c不匹配1 or 2 下列
  • WordPress 博客分页不起作用

    我仍然卡在这个问题上 我的 WordPress 博客上的分页无法正常工作 http www example com news http www example com news 当您单击不同的页码时 它会正确更新 URL 和页面标题 但不会
  • Swift Couple - Publishers.CombineLatest 在多个线程上

    当将 Publishers CombineLatest 与运行除 Main 的 sink 以外的线程的 Publishers 一起使用时Publishers CombineLatest并不总是被调用 这个问题并不是每次都会出现 这就是为什么
  • 在 Facebook 见解上找不到我的应用程序?

    我正在使用社交插件运行一个网站 所以我创建了一个 Facebook 应用程序 然后我想使用 facebook inform 来连接我的网站和应用程序 ps 我还在标题中添加了app id或meta 但我在连接列表中找不到我创建的应用程序 有
  • 如何在 Android 中将 getview() 与 SimpleAdapter 一起使用?

    我正在生成一个ListView用一个SimpleAdapter My SimpleAdapter代码如下 ListAdapter k new SimpleAdapter this val1 R layout mytask new Strin
  • QTextEdit 中的水平线

    我试图在一个水平线QTextDocument 我使用 HTML 进行格式化 为了画出我想要的线条 我自然地使用了 hr 标签 但这条线是灰色的 我想把它的颜色改为黑色 这些样式似乎不适用于hr元素 那么有没有一个简单的解决方法可以在我的文档
  • 如何在Python中使用“with open”打开多个文件?

    我想一次更改几个文件 iff我可以写信给他们所有人 我想知道是否可以以某种方式将多个开放调用与with陈述 try with open a w as a and open b w as b do something except IOErr
  • Flask 应用程序“使用 stat 重新启动”

    我已经构建了一些 Flask 应用程序 但在我最新的项目中 我注意到开发模式有些奇怪 终端中常见消息的第二行始终显示 Running on http 127 0 0 1 5000 Restarting with reloader 已被替换为
  • git bisect skip 如何选择下一个提交来尝试?

    使用时git bisect 一个人可以跑git bisect skip将当前提交标记为不可构建 不可测试的提交 尝试让 Git 选择其他提交进行测试 Git 如何决定在某个提交之后尝试哪个提交git bisect skip 实验表明这不仅仅
  • Backbone.js 查看实例变量?

    我正在学习 Backbone js 并试图弄清楚是否可以在 Backbone 视图中包含实例变量 我的目标是在实例化视图时从外部文件加载视图的模板 目前 我将它们存储在 Backbone 应用程序的全局命名空间中的全局变量中 但将模板存储在
  • 动态获取变量

    我正在使用 Go 模板来管理 Helm 的部署 我有这样的values yaml 文件 env dev config dev myname Hi live myname Bye 现在我想根据环境 开发 实时 获取值 喜欢 Values co
  • dlopen 是否创建多个库实例?

    在网上搜索后 我似乎找不到答案 当我第一次使用 dlopen 时 它似乎比此后的任何时间都花费更长的时间 包括如果我从程序的多个实例运行它 dlopen 是否将 so 加载到内存中一次并让操作系统保存它 以便任何后续调用 甚至来自程序的另一
  • 在 Cassandra 中选择两个表

    I use Cassandra一个项目 这是我的第一个项目 我试图对两个表执行一个简单的请求 但这不起作用 我想做类似的事情 Select from table1 table2 where table1 test test and tabl
  • 无法打开选定的 VM 调试端口 (8700)。确保您没有运行 DDMS 或 eclipse 插件的另一个实例

    我正在尝试在 eclipse kepler 中执行 android 程序 但是 每次执行时我都会收到此消息 我按照大家对这个问题所说的做了 Making sure there is a line on windows Host file t
  • Xcode:“无法保存文档。您没有权限。”

    尝试在 Xcode 4 中保存文件时出现此错误 无法保存文档 您没有权限 要查看或更改权限 请在 Finder 中选择该项目 然后选择 文件 gt 获取信息 当然 将文件保存在 TextMate 中效果很好 权限 rw r r 与上次工作时
  • 使用 Ionic 框架将 html 文件的内容嵌入到另一个 html 页面?

    我目前正在创建一个网站使用离子框架 http ionicframework com左侧有一个侧边栏 用户可以单击某个项目转到网站的另一个页面 现在我必须将侧边栏的代码复制到每个页面 这是没有用的 也不是可行的方法 所以我的问题是是否可以将
  • 定期重置嵌入式 H2 数据库

    我正在演示服务器中设置应用程序的新版本 并且希望找到一种每天重置数据库的方法 我想我总是可以有一个 cron 作业执行删除和创建查询 但我正在寻找一种更干净的方法 我尝试使用带有删除创建方法的特殊持久性单元 但它不起作用 因为系统频繁地 按
  • 无法使用 C# 中的 CryptEncrypt/CryptDecrypt 进行解密

    我制作了一个小应用程序来加密和解密一些文本 只要我直接使用加密中的字节数组 一切都很好 但是 一旦我复制了数组来模拟将加密文本作为文件发送的过程 解密就不会运行 为什么我无法使用复制的数组运行解密 using System using Sy
  • Python 中的事件驱动系统调用

    我正在尝试使用系统调用或子流程来实现事件驱动的流程 基本上我想启动一个非阻塞系统命令 并在完成该系统调用后 我想要调用一个函数 这样我就可以启动 GUI 进度条 启动系统命令并让进度条继续 当系统调用完成时 让进度条停止 我绝对不想做的是生