看langchain代码之前必备知识之 - python多进程信号接收与处理

文章目录

  • 前言
  • 一、示例代码
    • 1. 注册信号
    • 2.信号处理函数
      • 1)普通写法
      • 2)闭包写法
    • 3. 对终止信号的重写
      • 1)终止前关闭资源
      • 2)不关闭只抛出异常
  • 二、补充知识点
    • 1. signal.SIGTERM 和 signal.SIGINT的区别
    • 2. Process(target=task, daemon=True)里的daemon
  • 总结


前言

之前的文章里我们了解了python的多进程,这里想补充一下信号处理。我们可以通过langchain-chatchat的代码来了解信号处理。

代码是startup.py 的 async def start_main_server(): 方法,大家可以先去看一下。我们下面的例子是对它的一个改编

一、示例代码

import os
import time
from multiprocessing import Process
from time import sleepimport signaldef handler(signalname):def f(signal_received, frame):raise KeyboardInterrupt(f"{signalname} received")return fdef signal_handler(sig, frame):print(f"Received signal {sig} in process {os.getpid()}")# 在这里执行自定义的清理操作# 例如关闭文件、释放资源等# 这个示例中,我们简单地退出程序# sleep(10)exit(0)def task():# 打开文件file_handle = open("example.txt", "w")def task_signal_handler(sig, frame):print("Ctrl+C pressed. Exiting gracefully...")# 在这里关闭打开的文件if file_handle:print("Closing file...")file_handle.close()exit(0)signal.signal(signal.SIGINT, task_signal_handler)# 打印当前进程idprint("pid:", os.getpid())print("task")sleep(10)# 打印当前时分秒time_str = time.strftime("%H:%M:%S", time.localtime())print(time_str)if __name__ == "__main__":# 注册信号处理函数# signal.signal(signal.SIGINT, signal_handler)print("Press Ctrl+C to exit gracefully.")# 打印当前进程idprint("pid:", os.getpid())signal.signal(signal.SIGINT, handler("SIGINT"))signal.signal(signal.SIGTERM, handler("SIGTERM"))p1 = Process(target=task, daemon=True)try:p1.start()print("执行下一个任务")p1.join()print("执行完毕")except KeyboardInterrupt as e:print(e)finally:print("Cleaning up...")# p1.kill()p1.terminate()p1.join()print(f"Process status: {p1.is_alive()}")

1. 注册信号

大家可以看到这里有2种写法

signal.signal(signal.SIGINT, task_signal_handler)

signal.signal(signal.SIGINT, handler("SIGINT"))
实际上,注册信号的时候,是不能给后面的方法增加自定义参数的。那么为什么第二种可以增加一个自定义参数并传值SIGINT呢?

2.信号处理函数

1)普通写法

def signal_handler(sig, frame):print(f"Received signal {sig} in process {os.getpid()}")# 在这里执行自定义的清理操作# 例如关闭文件、释放资源等# 这个示例中,我们简单地退出程序# sleep(10)exit(0)

2)闭包写法

def handler(signalname):def f(signal_received, frame):raise KeyboardInterrupt(f"{signalname} received")return f

闭包方法实际上是把一个f(signal_received, frame)作为函数传递出去,也就是在
signal.signal(signal.SIGINT, handler("SIGINT")) 中最终第二个参数等同于信号注册函数需要的函数格式。这样就巧妙的利用闭包增加了一个自定义参数

3. 对终止信号的重写

1)终止前关闭资源

def task_signal_handler(sig, frame):print("Ctrl+C pressed. Exiting gracefully...")# 在这里关闭打开的文件if file_handle:print("Closing file...")file_handle.close()exit(0)

2)不关闭只抛出异常

def handler(signalname):def f(signal_received, frame):raise KeyboardInterrupt(f"{signalname} received")return f

这样可以让别的地方接收异常,然后再处理例如

try:p1.start()print("执行下一个任务")p1.join()print("执行完毕")except KeyboardInterrupt as e:print(e)finally:print("Cleaning up...")# p1.kill()p1.terminate()p1.join()print(f"Process status: {p1.is_alive()}")

二、补充知识点

1. signal.SIGTERM 和 signal.SIGINT的区别

signal.SIGTERMsignal.SIGINT 都与终止程序相关,但它们并不完全相同。

  • signal.SIGINT 是由键盘输入产生的信号,通常通过按下 Ctrl+C 来触发,用于请求程序中断。
  • signal.SIGTERM 是由操作系统发送的终止信号,通常用于请求程序终止。在 Unix/Linux 系统中,kill 命令默认发送 SIGTERM 信号。

虽然它们都可以用于请求程序终止,但它们的使用场景略有不同:

  • 通常情况下,SIGINT 更多地用于用户主动请求程序终止,比如在终端中按下 Ctrl+C
  • SIGTERM 则更多地由系统或其他程序发送,用于通知程序终止,但程序可以选择是否立即响应这个信号,或是在一段时间后进行优雅地关闭。

2. Process(target=task, daemon=True)里的daemon

Process的daemon参数的默认值是False,当它是false的时候,如果创建的子进程没有执行完,主进程会一直等待。当然要注意的是虽然会阻塞主进程结束,但并不会阻塞在如下代码 p1.start() 这里,在程序运行的时候,不管p1进程有没有执行完,都会立即往下走,也就是会输出“执行到这里”。它的

p1 = Process(target=task, daemon=False)
p1.start()
print('执行到这里')

而当daemon=True 时,不会阻塞主进程结束,主进程可以立即结束。如果不想主进程结束,需要增加p1.join()来等待子进程结束。要注意p1.join是会阻塞下面语句执行的。所以要想启动多个子进程,一定要把多个子进程.start(), 写在上面,而把 join 写在最下面。例如:

p1 = Process(target=task, daemon=False)
p1.start()
p1 = Process(target=task, daemon=False)
p2.start()
p1.join()
p2.join()

总结

通过今天的学习我们能了解到闭包的一种巧妙用法、信号接收与处理,以及各自的好处。这样我们写代码的时候可以考虑的更多,而不只是被动依赖于操作系统对进程的处理,减少类似内存泄露、资源浪费等的问题的发生。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/13428.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

剑指Offer打卡day34——AcWing 66. 两个链表的第一个公共结点

AcWing 66. 两个链表的第一个公共结点 暴力做法,两层for循环 /*** Definition for singly-linked list.* public class ListNode {* int val;* ListNode next;* ListNode(int x) {* val x;* next null;* }* }*/ class Solutio…

Linux ps命令详细参数

一、简介 在Linux系统中,ps(Process Status的缩写)命令常常用来用来列出系统中当前运行的进程。ps命令列出的是当前那些进程的快照,就是执行ps命令的那个时刻的那些进程,如果想要动态的显示进程信息,就可以使用top命令。要对进程…

Synchronize 底层实现原理

1 、加锁实现原理 public class SynchronizedTest {public void get(){synchronized (this){ // 这个是同步代码块System.out.println("你好呀");}}public synchronized void f(){ //这个是同步方法System.out.println("Hello world");}public s…

DC-DC直流升压线性可调电源模块电压控制输出0-50V/0-80V/0-100V/0-200V/0-250V/0-300V/0-500V/0-1000V

特点 效率高达 75%以上1*2英寸标准封装单电压输出可直接焊在PCB 上工作温度: -40℃~75℃阻燃封装,满足UL94-V0 要求温度特性好电压控制输出,输出电压随控制电压线性变化 应用 GRB 系列模块电源是一种DC-DC升压变换器。该模块电源的输入电压分为:4.5~9V、…

转载 | 大佬3万字深度分析:2024全球游戏业正在遭遇什么困境?

2022年,游戏业当时的裁员人数达到了破纪录的8500人,2023年这个数字几乎增长了20%,然后在2024开年的两个月,就已经有7800人丢掉了工作。伴随着这些裁员的,是大量表现不及预期的或者完全失败的游戏,还有更多处…

洛谷 P4317 花神的数论题

花神的数论题 题目背景 众所周知,花神多年来凭借无边的神力狂虐各大 OJ、OI、CF、TC …… 当然也包括 CH 啦。 题目描述 话说花神这天又来讲课了。课后照例有超级难的神题啦…… 我等蒟蒻又遭殃了。 花神的题目是这样的:设 sum ( i ) \text{sum}(i)…

Linux(八) 进程间通信

目录 一、什么进程间通信 1.1 进程间通信的目的 1.2 进程间通信的概念 1.3 进程间通信的分类 二、 管道/匿名管道(pipe) 2.1 什么是管道 2.2 管道的创建 2.3 站在文件描述符角度-深度理解管道 2.4 站在内核角度-管道本质 2.5 匿名管道的读写 2.6 匿名管道的读写规则 …

EIP-4844对Polygon的意义

1. 引言 Dencun 升级引入了L2新资源,并降低了与calldata相关的交易手续费。 本文要点为: EIP-4844 引入了 blobspace —— 一种用于高效管理大型二进制对象 (large binary objects,BLOB) 的数据库存储概念。Blobs 将降低rollups的交易成本…

运动耳机怎么选?五款新手必买的运动耳机盘点

运动耳机是专为运动爱好者设计的耳机,轻巧便携,佩戴稳固。无论你在跑步、健身还是骑行,它都能为你带来优质的音乐体验。那如何选择一款合适的运动耳机呢?这里,我结合自己和身边朋友平时选购经验,整理了一些…

编程实战:自己编写HTTP服务器(系列5:执行后台shell命令)

初级代码游戏的专栏介绍与文章目录-CSDN博客 我的github:codetoys,所有代码都将会位于ctfc库中。已经放入库中我会指出在库中的位置。 这些代码大部分以Linux为目标但部分代码是纯C的,可以在任何平台上使用。 系列入口:编程实战…

单片机负电压

在电子电路中我们常常需要使用负电压,比如说我们在使用运放的时候常常需要建立一个负电压。下面就简单的以正5V电压到负电压5V为例说一下它的电路。 通常需要使用负电压时一般会选择使用专用的负压产生芯片,但这些芯片都比较贵,比如电荷泵原理…

P1229 遍历问题

题目描述 我们都很熟悉二叉树的前序、中序、后序遍历,在数据结构中常提出这样的问题:已知一棵二叉树的前序和中序遍历,求它的后序遍历,相应的,已知一棵二叉树的后序遍历和中序遍历序列你也能求出它的前序遍历。然而给…

剪辑师创作必备声音素材,BGM背景音效素材合集1万款

一、素材描述 本套音效包含了全面丰富的声音效果,如动物、运输、人群、天气、航空、军事、Foley声音等,以及世界各地的场景声效等,可能是同类音效中最为全面的,共由三套声音素材组合而成,1、熊猫背景音乐3800首&#…

什么是单线服务器?

单线服务器主要是指只有一条物理线路连接到服务器的服务器,其中所有的数据与用户的请求都必须通过这条线路进行传输,由于线路只有一条,所以对于服务器的性能和可扩展性方面会有着一定的限制。 单线服务器和多线服务器进行比较的话&#xff0c…

宁静致远(“静”)

宁静致远是一个成语,读音为nng jng zh yuǎn,意思是只有心境平稳沉着、专心致志,才能厚积薄发、 有所作为。出自《淮南子:主术训》。 出处 宁静致远张铭篆刻 此句最早出自西汉初年道家刘安的《淮南子:主术训》,蜀汉丞相诸葛亮的…

5年增100倍6秒卖1瓶酒,酣客的“FFC模式”是什么

酣客酱酒销售模式,白酒FFC模式,白酒新零售模式设计 坐标:厦门,我是易创客肖琳 深耕社交新零售行业10年,主要提供新零售系统工具及顶层商业模式设计、全案策划运营陪跑等。 不知从何时起,营销圈开始有这么一…

Verilog 实现 i2c 协议

在时钟(SCL)为高电平的时候,数据总线(SDA)必须保持稳定,所以数据总线(SDA)在时钟(SCL)为低电平的时候才能改变。 在时钟(SCL)为高电平…

诸葛智能携手五大银行,以数据驱动的营销中台带来可预见增长

对于银行来说,客户是赖以生存的基础,也是保持活力的关键。尤其是大数据、人工智能等新兴技术的推动下,通过数据赋能产品升级和服务创新,深挖客户潜能,更是助推银行快步迈入高质量发展的新阶段。 在银行加速拥抱新质生…

文档分类DPCNN简介(pytorch实现)

文档分类DPCNN简介 DPCNN简介 模型结构区域嵌入等长卷积1/2池化DPCNN模型代码实现 DPCNN简介 论文中提出了一种基于 word-level 级别的网络-DPCNN,由于 TextCNN 不能通过卷积获得文本的长距离依赖关系,而论文中 DPCNN 通过不断加深网络,可以…

ATA-2021B高压放大器在光纤超声传感器中的应用

实验名称:超声传感性能研究 测试目的: 光纤马赫-曾德尔干涉仪是一种灵敏度高、结构灵活的传感结构。当在MZI上施加超声波信号时,会影响所涉及的干涉光之间的光程差,并导致干涉光谱的漂移。由于模式耦合是基于MZI的光纤传感器的关键…