multiprocessing 让子进程忽略信号,手动关闭子进程
起因
同事想要写一个代码,主进程中监听SIGINT、SIGTERM信号退出,并关闭启动的子进程,代码类似这样
import signal
import sys
import time
from multiprocessing import Process
from multiprocessing import Manager
class Test:
def __init__(self):
self.is_running = True
if sys.platform != 'win32':
signal.signal(signal.SIGHUP, self._signal_handler)
signal.signal(signal.SIGINT, self._signal_handler)
signal.signal(signal.SIGTERM, self._signal_handler)
def _signal_handler(self, signum, frame):
"""
Terminate scenario ticking when receiving a signal interrupt
"""
self.is_running = False
print('关闭场景调度')
def listen_manage(self, running, kill_task_lst):
"""监控取消任务"""
while running.value:
kill_task_lst.append(1)
time.sleep(1)
print("child is running")
def run(self):
"""启动场景调度"""
kill_task_lst = Manager().list()
running = Manager().Value(bool, True)
print('启动监控进程')
p = Process(target=self.listen_manage, args=(running, kill_task_lst, ))
p.start()
while self.is_running:
time.sleep(0.5)
print("main is running")
但是发现在ctrl + c 时候,子进程也同时接收到了信号,退出了
启动监控进程
main is running
main is running
child is running
main is running
关闭场景调度
Process Process-3:
Traceback (most recent call last):
File "D:\software\anaconda\envs\test_egg1\lib\multiprocessing\process.py", line 315, in _bootstrap
self.run()
File "D:\software\anaconda\envs\test_egg1\lib\multiprocessing\process.py", line 108, in run
self._target(*self._args, **self._kwargs)
File "D:\python_projects\pythonProject\test_egg\test.py", line 35, in listen_manage
time.sleep(1)
KeyboardInterrupt
main is running
这时猜想到可能是子进程也监听了SIGINT,退出了程序,所以想在子任务中设置忽略信号,改造后的 listen_manage:
def listen_manage(self, running, kill_task_lst):
"""监控取消任务"""
if sys.platform != 'win32':
signal.signal(signal.SIGHUP, signal.SIG_IGN)
signal.signal(signal.SIGINT, signal.SIG_IGN)
signal.signal(signal.SIGTERM, signal.SIG_IGN)
while running.value::
kill_task_lst.append(1)
time.sleep(1)
print("child is running")
运行后会报 BrokenPipeError: [WinError 232] 管道正在被关闭。
启动监控进程
main is running
main is running
child is running
main is running
关闭场景调度
main is running
child is running
Process Process-4:
Traceback (most recent call last):
File "D:\software\anaconda\envs\test_egg1\lib\multiprocessing\process.py", line 315, in _bootstrap
self.run()
File "D:\software\anaconda\envs\test_egg1\lib\multiprocessing\process.py", line 108, in run
self._target(*self._args, **self._kwargs)
File "D:\python_projects\pythonProject\test_egg\test.py", line 37, in listen_manage
kill_task_lst.append(1)
File "<string>", line 2, in append
File "D:\software\anaconda\envs\test_egg1\lib\multiprocessing\managers.py", line 834, in _callmethod
conn.send((self._id, methodname, args, kwds))
File "D:\software\anaconda\envs\test_egg1\lib\multiprocessing\connection.py", line 206, in send
self._send_bytes(_ForkingPickler.dumps(obj))
File "D:\software\anaconda\envs\test_egg1\lib\multiprocessing\connection.py", line 280, in _send_bytes
ov, err = _winapi.WriteFile(self._handle, buf, overlapped=True)
BrokenPipeError: [WinError 232] 管道正在被关闭。
这里想到的原因是父进程直接退出了,导致共享变量kill_task_lst被关闭导致的,所以想在关闭管道前等待子进程退出
可执行的完整代码:
import signal
import sys
import time
from multiprocessing import Process
from multiprocessing import Manager
class Test:
def __init__(self):
self.is_running = True
if sys.platform != 'win32':
signal.signal(signal.SIGHUP, self._signal_handler)
signal.signal(signal.SIGINT, self._signal_handler)
signal.signal(signal.SIGTERM, self._signal_handler)
def _signal_handler(self, signum, frame):
"""
Terminate scenario ticking when receiving a signal interrupt
"""
self.is_running = False
print('关闭场景调度')
def listen_manage(self, running, kill_task_lst):
"""监控取消任务"""
if sys.platform != 'win32':
signal.signal(signal.SIGHUP, signal.SIG_IGN)
signal.signal(signal.SIGINT, signal.SIG_IGN)
signal.signal(signal.SIGTERM, signal.SIG_IGN)
while running.value:
kill_task_lst.append(1)
time.sleep(1)
print("child is running")
def run(self):
"""启动场景调度"""
kill_task_lst = Manager().list()
running = Manager().Value(bool, True)
print('启动监控进程')
p = Process(target=self.listen_manage, args=(running, kill_task_lst, ))
p.start()
while self.is_running:
time.sleep(0.5)
print("main is running")
running.set(False)
while p.is_alive():
time.sleep(0.01)
print("finish.....")
if __name__ == '__main__':
t = Test()
t.run()
执行结果:
启动监控进程
main is running
main is running
child is running
main is running
关闭场景调度
main is running
child is running
finish.....
multiprocessing 让子进程忽略信号,手动关闭子进程的更多相关文章
- wait & waitpid 以及子进程传给父进程的信号分析
wait() 和 waitpid() wait() 系统调用挂起调用进程的执行直到有一个孩子终止.调用 wait(&status) 等价于: waitpid(-1, &status, ...
- Linux 父进程发送信号杀死子进程
#include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <signal. ...
- 第9章 Linux进程和信号超详细分析
9.1 进程简单说明 进程是一个非常复杂的概念,涉及的内容也非常非常多.在这一小节所列出内容,已经是我极度简化后的内容了,应该尽可能都理解下来,我觉得这些理论比如何使用命令来查看状态更重要,而且不明白 ...
- node.js中process进程的概念和child_process子进程模块的使用
进程,你可以把它理解成一个正在运行的程序.node.js中每个应用程序都是进程类的实例对象. node.js中有一个 process 全局对象,通过它我们可以获取,运行该程序的用户,环境变量等信息. ...
- python的multiprocessing模块进程创建、资源回收-Process,Pool
python的multiprocessing有两种创建进程的方式,每种创建方式和进程资源的回收都不太相同,下面分别针对Process,Pool及系统自带的fork三种进程分析. 1.方式一:fork( ...
- 初步理解Python进程的信号通讯
Reference: http://www.jb51.net/article/63787.htm 信号的概念 信号(signal)-- 进程之间通讯的方式,是一种软件中断.一个进程一旦接收到信 ...
- python之multiprocessing创建进程
python的multiprocessing模块是用来创建多进程的,下面对multiprocessing总结一下使用记录. multiprocessing创建多进程在windows和linux系统下的 ...
- Linux进程间通信--进程,信号,管道,消息队列,信号量,共享内存
Linux进程间通信--进程,信号,管道,消息队列,信号量,共享内存 参考:<linux编程从入门到精通>,<Linux C程序设计大全>,<unix环境高级编程> ...
- Python多进程库multiprocessing创建进程以及进程池Pool类的使用
问题起因最近要将一个文本分割成好几个topic,每个topic设计一个regressor,各regressor是相互独立的,最后汇总所有topic的regressor得到总得预测结果.没错!类似bag ...
随机推荐
- 使用Node.js还可以发邮件
前言 今天,我们给大家开发一个小效果.篇幅比较短,主要给大家展示效果.实战 首先我们初始化一个Node项目 npm init -y 创建一个app.js文件 'use strict'; const n ...
- ansible对文件内容操作
ansible lineinfile 简介 lineinfile该模块是操作文件中的每一行内容,他是按照行为单位的,和下面的replace模块并不冲突. 修改匹配行,如果不存在就会添加 tasks: ...
- sql-DML-增删改
DML:增删改表中数据 1. 添加数据: insert into 表名(列名1,列名2,...列名n) values(值1,值2,...值n); insert into 表名 values(值1,值2 ...
- windows平台编译CEF支持H264(MP3、MP4)超详细
编译目标(如何确定目标定版本请查看:BranchesAndBuilding) CEF Branch:4664 CEF Commit:fe551e4 Chromium Version:96.0.4664 ...
- Python教程:随机验证码生成和join 字符串
函数:string.join() Python中有join()和os.path.join()两个函数,具体作用如下: join(): 连接字符串数组.将字符串.元组.列表中的元素以指定的字符(分隔符) ...
- 详解SQL中Groupings Sets 语句的功能和底层实现逻辑
摘要:本文首先简单介绍 Grouping Sets 的用法,然后以 Spark SQL 作为切入点,深入解析 Grouping Sets 的实现机制. 本文分享自华为云社区<深入理解 SQL 中 ...
- Android Studio的初次认识
Android的初试 一.认识Android Studio 在我们新建项目的时候,会遇到这样的一个窗口,首先我们认识一下这些都是什么,这样我们才能够更好的进行下一步的学习! 这里的 Phone and ...
- mvc 捕获404和500 等
之前一直以为HandleErrorAttribute 可以捕获到后面自己尝试了不行,又自己想自定义页面,发现不行,然后设置了<customErrors/>节点 又不符合SEO 返回stat ...
- golang面试-代码编写题1-14
目录 1.代码编写题--统计文本行数-bufio 2.代码编写题--多协程收集错误信息-channel 3.代码编写题--超时控制,内存泄露 4.代码编写题--单例模式 5.代码编写题--九九乘法表 ...
- 基于ABP实现DDD--实体创建和更新
本文主要介绍了通过构造函数和领域服务创建实体2种方式,后者多用于在创建实体时需要其它业务规则检测的场景.最后介绍了在应用服务层中如何进行实体的更新操作. 一.通过构造函数创建实体 假如Issue的 ...