基于信号的Python多进程控制

Python版本: 3.9.8
信号模块: signal
多进程模块: multiprocess

1. 主进程接收信号,子进程发送信号。

子进程在结束时会自动给主进程发送SIGCHLD信号[1],因此在主进程内配置相应的处理函数即可捕获子进程的信号。
如下:

import multiprocessing
import signal

def handler():
    print("sub process doing")
    exit(0)

def signal_handler(signum, frame):
    print("main process got a signal")
    print(signum)

def main():
    signal.signal(signal.SIGCHLD, signal_handler) # 设置信号处理函数
    p = multiprocessing.Process(target=handler, name='sub process')
    p.start()
    signal.pause() # 主进程阻塞式等待信号

if __name__ == '__main__':
    main()

输出为:

sub process doing
main process got a signal
17

上述示例中,如果存在多个子进程时。主进程是无法区分信号SIGCHLD由哪个子进程发送的。此时需要在主进程内使用阻塞式的信号等待方法signal.sigwaitinfo[2],其返回一个信号的结构体,其中包含的si_pid就是相应的子进程ID。
如下:

import multiprocessing
import signal
import time
import os

def handler():
    print(f"sub process: {os.getpid()} doing")
    time.sleep(1)
    exit(0)

def signal_handler(signum, frame):
    print(f"main process got a signal: {signum}")

def main():
    signal.signal(signal.SIGCHLD, signal_handler) # 设置信号处理函数
    for _ in range(2):
        p = multiprocessing.Process(target=handler, name='sub process')
        p.start()
    #signal.pause() # 主进程阻塞式等待信号
    while True:
        s = signal.sigwaitinfo([signal.SIGCHLD])  # 不会再调用signal_handler()
        signal_handler(s.si_signo, None)  # 改为手动调用
        print(f"sub process pid: {s.si_pid}")


if __name__ == '__main__':
    main()

输出为:

sub process: 302537 doing
sub process: 302538 doing
main process got a signal: 17
sub process pid: 302537
main process got a signal: 17
sub process pid: 302538

2. 主进程发送信号,子进程接收信号。

在子进程内绑定相应的信号处理程序,之后由信号处理程序控制一个开关变量,进而达到控制子进程的主循环逻辑。
如下:

import multiprocessing
import time
import os
import signal
import logging

logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)
handler = logging.StreamHandler()
handler.setFormatter(logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s'))
logger.addHandler(handler)

def print(info):
    logger.debug(info)

class SubProcess(object):
    flag = True

    def signal_handler(self, signum, frame):
        print("signal handler doing")
        print(signum)
        self.flag = False

    def handler(self):
        signal.signal(signal.SIGINT, self.signal_handler)  # 绑定信号处理函数
        print("handler doing")
        while True:
            if self.flag is False:
                print("sub process flag is False")
                break
            time.sleep(3)
        exit(0)

def main():
    sp = SubProcess()
    p = multiprocessing.Process(target=sp.handler, name='sub_ps')
    p.start()
    while True:
        time.sleep(5)
        os.kill(p.pid, signal.SIGINT)  # send SIGINT every 5 seconds
        print("main looping")

if __name__ == '__main__':
    main()

输出结果:

2022-09-19 15:51:55,395 - __main__ - DEBUG - handler doing
2022-09-19 15:52:00,399 - __main__ - DEBUG - signal handler doing
2022-09-19 15:52:00,399 - __main__ - DEBUG - 2
2022-09-19 15:52:00,399 - __main__ - DEBUG - main looping
2022-09-19 15:52:01,399 - __main__ - DEBUG - sub process flag is False
2022-09-19 15:52:05,405 - __main__ - DEBUG - main looping
2022-09-19 15:52:10,410 - __main__ - DEBUG - main looping
2022-09-19 15:52:15,415 - __main__ - DEBUG - main looping

3. 总结

在主进程无阻塞式任务的前提下,可结合上述两种情况,通过信号来完成多进程之间的控制。

参考:

[1]. 孙剑.Linux系统编程[M].人民邮电出版社. 26.3章节.SIGCHLD信号
[2]. https://docs.python.org/3/library/signal.html#signal.sigwaitinfo

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 222,252评论 6 516
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,886评论 3 399
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 168,814评论 0 361
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,869评论 1 299
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,888评论 6 398
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,475评论 1 312
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 41,010评论 3 422
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,924评论 0 277
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,469评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,552评论 3 342
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,680评论 1 353
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,362评论 5 351
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 42,037评论 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,519评论 0 25
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,621评论 1 274
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 49,099评论 3 378
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,691评论 2 361

推荐阅读更多精彩内容