深入Python多进程编程基础——图文版

Python编程环境详解:交互式与文件式开发实践 Python作为通用编程语言的核心优势在于其灵活的双模式编程环境。交互式开发(REPL)通过即时反馈机制提升算法验证效率,而文件式编程则确保项目代码的可维护性。理解这两种模式的底层原理对开发者至关重要:交互模式基于Read-Eval-Print Loop机制实现即时执行,文件模式则通过Python解释器编译执行.py文件。现代开发工具如VSCode和PyCharm通过集成终端和虚拟环境支持两种模式的无缝切换,其中虚拟环境能有效解决依赖冲突问题。在数据科学领域,IPython和Jupyter Notebook 阅读详情

多进程编程知识是Python程序员进阶高级的必备知识点,我们平时习惯了使用multiprocessing库来操纵多进程,但是并不知道它的具体实现原理。下面我对多进程的常用知识点都简单列了一遍,使用原生的多进程方法调用,帮助读者理解多进程的实现机制。代码跑在linux环境下。没有linux条件的,可以使用docker或者虚拟机运行进行体验。

docker pull python:2.7

生成子进程

Python生成子进程使用os.fork(),它将产生一个子进程。fork调用同时在父进程和主进程同时返回,在父进程中返回子进程的pid,在子进程中返回0,如果返回值小于零,说明子进程产生失败,一般是因为操作系统资源不足。

640?wx_fmt=png
import os
def create_child():
    pid = os.fork()
    if pid > 0:
        print 'in father process'
        return True
    elif pid == 0:
        print 'in child process'
        return False
    else:
        raise

生成多个子进程

我们调用create_child方法多次就可以生成多个子进程,前提是必须保证create_child是在父进程里执行,如果是子进程,就不要在调用了。

640?wx_fmt=png
# coding: utf-8
# child.py
import os

def create_child(i):
    pid = os.fork()
    if pid > 0:
        print 'in father process'
        return pid
    elif pid == 0:
        print 'in child process', i
        return 0
    else:
        raise

for i in range(10):  # 循环10次,创建10个子进程
    pid = create_child(i)
    # pid==0是子进程,应该立即退出循环,否则子进程也会继续生成子进程
    # 子子孙孙,那就生成太多进程了
    if pid == 0:
        break

运行python child.py,输出

in father process
in father process
in child process 0
in child process 1
in father process
in child process 2
in father process
in father process
in child process 3
in father process
in child process 4
in child process 5
in father process
in father process
in child process 6
in child process 7
in father process
in child process 8
in father process
in child process 9

进程休眠

使用time.sleep可以使进程休眠任意时间,单位为秒,可以是小数

640?wx_fmt=png
import time
for i in range(5):
    print 'hello'
    time.sleep(1)  # 睡1s

杀死子进程

使用os.kill(pid, sig_num)可以向进程号为pid的子进程发送信号,sig_num常用的有SIGKILL(暴力杀死,相当于kill -9),SIGTERM(通知对方退出,相当于kill不带参数),SIGINT(相当于键盘的ctrl+c)。

640?wx_fmt=png
# coding: utf-8
# kill.py

import os
import time
import signal


def create_child():
    pid = os.fork()
    if pid > 0:
        return pid
    elif pid == 0:
        return 0
    else:
        raise


pid = create_child()
if pid == 0:
    while True:  # 子进程死循环打印字符串
        print 'in child process'
        time.sleep(1)
else:
    print 'in father process'
    time.sleep(5)  # 父进程休眠5s再杀死子进程
    os.kill(pid, signal.SIGKILL)
    time.sleep(5)  # 父进程继续休眠5s观察子进程是否还有输出

运行python kill.py,我们看到控制台输出如下

in father process
in child process
# 等1s
in child process
# 等1s
in child process
# 等1s
in child process
# 等1s
in child process
# 等了5s

说明os.kill执行之后,子进程已经停止输出了

僵尸子进程

在上面的例子中,os.kill执行完之后,我们通过ps -ef|grep python快速观察进程的状态,可以发现子进程有一个奇怪的显示<defunct>

root        12     1  0 11:22 pts/0    00:00:00 python kill.py
root        13    12  0 11:22 pts/0    00:00:00 [python] <defunct>

待父进程终止后,子进程也一块消失了。那<defunct>是什么含义呢?

收割子进程

如果彻底干掉僵尸进程?父进程需要调用waitpid(pid, options)函数,「收割」子进程,这样子进程才可以灰飞烟灭。waitpid函数会返回子进程的退出状态,它就像子进程留下的临终遗言,必须等父进程听到后才能彻底瞑目。

640?wx_fmt=png
# coding: utf-8
import os
import time
import signal
def create_child():
    pid = os.fork()
    if pid > 0:
        return pid
    elif pid == 0:
        return 0
    else:
        raise
pid = create_child()
if pid == 0:
    while True:  # 子进程死循环打印字符串
        print 'in child process'
        time.sleep(1)
else:
    print 'in father process'
    time.sleep(5)  # 父进程休眠5s再杀死子进程
    os.kill(pid, signal.SIGTERM)
    ret = os.waitpid(pid, 0)  # 收割子进程
    print ret  # 看看到底返回了什么
    time.sleep(5)  # 父进程继续休眠5s观察子进程是否还存在

运行python kill.py输出如下

in father process
in child process
in child process
in child process
in child process
in child process
in child process
(125, 9)

我们看到waitpid返回了一个tuple,第一个是子进程的pid,第二个9是什么含义呢,它在不同的操作系统上含义不尽相同,不过在Unix上,它通常的value是一个16位的整数值,前8位表示进程的退出状态,后8位表示导致进程退出的信号的整数值。所以本例中退出状态位0,信号编号位9,还记得kill -9这个命令么,就是这个9表示暴力杀死进程。

如果我们将os.kill换一个信号才看结果,比如换成os.kill(pid, signal.SIGTERM),可以看到返回结果变成了(138, 15),15就是SIGTERM信号的整数值。

waitpid(pid, 0)还可以起到等待子进程结束的功能,如果子进程不结束,那么该调用会一直卡住。

捕获信号

SIGTERM信号默认处理动作就是退出进程,其实我们还可以设置SIGTERM信号的处理函数,使得它不退出。

# coding: utf-8
import os
import time
import signal
def create_child():
    pid = os.fork()
    if pid > 0:
        return pid
    elif pid == 0:
        return 0
    else:
        raise
pid = create_child()
if pid == 0:
    signal.signal(signal.SIGTERM, signal.SIG_IGN)
    while True:  # 子进程死循环打印字符串
        print 'in child process'
        time.sleep(1)
else:
    print 'in father process'
    time.sleep(5)  # 父进程休眠5s再杀死子进程
    os.kill(pid, signal.SIGTERM)  # 发一个SIGTERM信号
    time.sleep(5)  # 父进程继续休眠5s观察子进程是否还存在
    os.kill(pid, signal.SIGKILL)  # 发一个SIGKILL信号
    time.sleep(5)  # 父进程继续休眠5s观察子进程是否还存在

我们在子进程里设置了信号处理函数,SIG_IGN表示忽略信号。我们发现第一次调用os.kill之后,子进程会继续输出。说明子进程没有被杀死。第二次os.kill之后,子进程终于停止了输出。

640?wx_fmt=png

接下来我们换一个自定义信号处理函数,子进程收到SIGTERM之后,打印一句话再退出。

# coding: utf-8
import os
import sys
import time
import signal
def create_child():
    pid = os.fork()
    if pid > 0:
        return pid
    elif pid == 0:
        return 0
    else:
        raise
def i_will_die(sig_num, frame):  # 自定义信号处理函数
    print "child will die"
    sys.exit(0)
pid = create_child()
if pid == 0:
    signal.signal(signal.SIGTERM, i_will_die)
    while True:  # 子进程死循环打印字符串
        print 'in child process'
        time.sleep(1)
else:
    print 'in father process'
    time.sleep(5)  # 父进程休眠5s再杀死子进程
    os.kill(pid, signal.SIGTERM)
    time.sleep(5)  # 父进程继续休眠5s观察子进程是否还存在

输出如下

in father process
in child process
in child process
in child process
in child process
in child process
child will die

信号处理函数有两个参数,第一个sig_num表示被捕获信号的整数值,第二个frame不太好理解,一般也很少用。它表示被信号打断时,Python的运行的栈帧对象信息。读者可以不必深度理解。

多进程并行计算实例

下面我们使用多进程进行一个计算圆周率PI。对于圆周率PI有一个数学极限公式,我们将使用该公司来计算圆周率PI。

640?wx_fmt=png

先使用单进程版本

import math
def pi(n):
    s = 0.0
    for i in range(n):
        s += 1.0/(2*i+1)/(2*i+1)
    return math.sqrt(8 * s)
print pi(10000000)

输出

3.14159262176

这个程序跑了有一小会才出结果,不过这个值已经非常接近圆周率了。

640?wx_fmt=png

接下来我们用多进程版本,我们用redis进行进程间通信。

# coding: utf-8
import os
import sys
import math
import redis
def slice(mink, maxk):
    s = 0.0
    for k in range(mink, maxk):
        s += 1.0/(2*k+1)/(2*k+1)
    return s
def pi(n):
    pids = []
    unit = n / 10
    client = redis.StrictRedis()
    client.delete("result")  # 保证结果集是干净的
    del client  # 关闭连接
    for i in range(10):  # 分10个子进程
        mink = unit * i
        maxk = mink + unit
        pid = os.fork()
        if pid > 0:
            pids.append(pid)
        else:
            s = slice(mink, maxk)  # 子进程开始计算
            client = redis.StrictRedis()
            client.rpush("result", str(s))  # 传递子进程结果
            sys.exit(0)  # 子进程结束
    for pid in pids:
        os.waitpid(pid, 0)  # 等待子进程结束
    sum = 0
    client = redis.StrictRedis()
    for s in client.lrange("result", 0, -1):
        sum += float(s)  # 收集子进程计算结果
    return math.sqrt(sum * 8)
print pi(10000000)

我们将级数之和的计算拆分成10个子进程计算,每个子进程负责1/10的计算量,并将计算的中间结果扔到redis的队列中,然后父进程等待所有子进程结束,再将队列中的数据全部汇总起来计算最终结果。

输出如下

3.14159262176

这个结果和单进程结果一致,但是花费的时间要缩短了不少。

这里我们之所以使用redis作为进程间通信方式,是因为进程间通信是一个比较复杂的技术,我们需要单独一篇文章来仔细讲,各位读者请耐心听我下回分解,我们将会使用进程间通信技术来替换掉这里的redis。

640?wx_fmt=jpeg

阅读python相关高级文章,请关注公众号「码洞」

史上最全的 python 基础知识汇总篇,没有比这再全面的了,建议收藏 网友们有福了,小编终于把基础篇的内容全部涉略了一遍,这是一篇关于基础知识的汇总的文章,请朋友们收下,不用客气,不过文章篇幅肯能会有点长,耐心阅读吧爬虫(七十)多进程multiproces... 阅读详情

相关推荐

记录LeNet的硬件加速器设计(一)

LeNet的硬件加速器设计实现。

2301_81029398的博客 3545

python多进程

python多进程

weixin_43717602的博客 998

水文预报新手别怕!用Matlab 18小时搞定马斯京根法参数K和x(附完整代码)

本文详细介绍了如何使用Matlab在18小时内快速掌握水文预报中的马斯京根法参数K和x的求解方法。通过完整的代码示例和分步解析,帮助新手从理论到实践快速跨越,解决传统手工试算耗时耗力的问题,提升水文预报的效率和精度。

weixin_42573113的博客 259

杀死僵尸进程(defunct)

在Linux中,有时候PS查看进程发现一些进程用kill -9无法杀死,形成了defunct, 即僵尸进程。 这多数情况都是由于父子进程间通信由于某些不知名原因被中途破坏,所以关键核心在于要杀死父进程才行,光kill子进程并不起任何作用。 怎么做? 看看这些进程的ID及其父进程ID: $ ps -ef | grep defunct 显示如下 username 5432 6789 0 17:08 pts/18 00:00:00 grep --color=auto defunct user

flyinmo的博客 4461

从入门到精通:MATEKH743 飞控全解析——MAVLink 接口软/硬件对接实战

MATEKH743飞控是基于STM32H743微控制器的无人机核心控制系统,具备强大计算能力和丰富外设接口。该飞控采用双核架构,集成高性能IMU、气压计等传感器,支持多种开源固件(Betaflight/INAV/ArduPilot),适用于FPV穿越机、固定翼及工业无人机。相比PX4等飞控,MATEKH743在性价比和DIY友好度上优势明显,同时支持MAVLink协议实现设备通信。未来发展方向包括集成更高精度传感器、优化电源管理以及拓展工业应用场景,持续推动无人机技术创新。

bother3000的博客 2287

STM32F407 BootLoader实战:从零搭建到OTA升级(附完整源码)

本文详细介绍了为STM32F407微控制器从零搭建BootLoader并实现稳定OTA升级的完整实战指南。内容涵盖Flash分区规划、链接脚本配置、核心跳转逻辑、中断向量表重定向、可靠的升级流程设计,并深入探讨了双备份与回滚机制以提升工业级可靠性。文章提供了可直接使用的代码框架,并分享了关键调试技巧,帮助开发者快速掌握STM32远程固件更新技术。

weixin_29192211的博客 445

关于Python3多进程机制的一些探索

本文探索了flask中利用多进程实现异步请求的方式

芳樽里的歌的博客 1744

单细胞转录组数据分析全流程:从原始数据到细胞注释

本文详细介绍了单细胞转录组数据分析的全流程,从原始数据读取、环境搭建、数据质控与标准化,到降维聚类、细胞类型注释,以及高级质控与多样本整合。重点阐述了如何利用Seurat等工具进行数据处理,并通过标志基因比对与自动注释方法完成细胞身份鉴定,为研究者提供了一套清晰、可操作的分析指南。

coffee的博客 553

python程序主动退出进程的方式:五种方式总有一种适合你

如果你的程序中包含有线程,用这种方式绝对没错!sys.exit()是一种常用的退出当前进程的方法,它可以终止一个程序的运行,并可以返回一个状态码。当sys.exit()被调用时,程序将立即停止执行,所有的finally子句(如果有的话)将被忽略,并且返回一个标识状态的整数。os._exit()是一种基于系统调用的退出方式,它可以忽略所有的清理活动,包括所有的缓存和终止信号处理器等。当使用os.exit()方法退出时,Python解释器将立即终止程序的运行,不会执行任何清理操作并且不会返回状态码。

3万+

[AI] 本地部署 Dify 遇到 Internal Error?一文彻底解决密码不一致引发的问题

摘要:Dify本地部署常见InternalError错误主要由配置残留或密码不一致导致,特别是修改.env文件后未同步清除数据库记录。彻底解决方案包括:1)清理Docker数据;2)删除旧配置和数据库;3)还原源代码;4)重建.env文件;5)重新初始化部署。关键提醒:记录部署路径、备份.env文件并妥善保存密码。该错误本质是配置冲突,最有效方法是完全重置而非调试,保持清晰的部署管理可避免多数InternalError问题。(149字)

技术小甜甜:传播可落地技术,帮助个人和企业降低解决真实场景问题的成本 439

RT-DETR改进策略【模型轻量化】| 替换骨干网络为 GhostNet V3 2024华为的重参数轻量化模型

本文记录的是基于 GhostNetV3 的 RT-DETR轻量化改进方法研究。GhostNetV3的轻量模块采用方法,训练时为深度可分离卷积和1×1卷积添加,推理时通过移除分支、折叠操作,能够在不增加推理成本的同时提高性能,从而实现RT-DETR的轻量化改进。

Limiiiing的博客 973

孤儿进程/僵尸进程<defunct> Z+

1、孤儿进程 爹生孩子;爹死了,孩子还或者,孩子叫孤儿进程;孤儿进程被init进程领养,init进程变为孤儿进程的父亲 int main(){ pid_t pid=fork(); ...

JaweG 867

AI产品经理面试宝典第94天:RAG知识库构建与预处理策略面试指南

本文深入解析RAG知识库构建的核心挑战与预处理策略,涵盖文档格式转换、问答对生成及自动化测试全流程,为AI产品经理提供面试必备的实战方法论与避坑指南,助你精准应对技术深度类问题。

打造全国最全的AI Agent开发知识领域的博客 314

python编程图文_深入Python多进程编程基础——图文版

多进程编程知识是Python程序员进阶高级的必备知识点,我们平时习惯了使用multiprocessing库来操纵多进程,但是并不知道它的具体实现原理。下面我对多进程的常用知识点都简单列了一遍,使用原生的多进程方法调用,帮助读者理解多进程的实现机制。代码跑在linux环境下。没有linux条件的,可以使用docker或者虚拟机运行进行体验。docker pull python:2.7生成子进程Pyt...

weixin_40004081的博客 163

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

Python多进程编程基础——图文版

多进程编程知识是Python程序员进阶高级的必备知识点,我们平时习惯了使用multiprocessing库来操纵多进程,但是并不知道它的具体实现原理。下面我对多进程的常用知识点都简单列了一遍,使用原生的多进程方法调用,帮助读者理解多进程的实现机制。代码跑在linux环境下。没有linux条件的,可以使用docker或者虚拟机运行进行体验。 docker pull python:2.7 复制代码生成...

weixin_33976072的博客 233

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

python多进程并行计算linux上进程睡眠_深入 Python 多进程编辑基础——图文版

多进程编程知识是 Python 程序员进阶高级的必备知识点,我们平时习惯了使用 multiprocessing 库来操纵多进程,但是并不知道它的具体实现原理。下面我对多进程的常用知识点都简单列了一遍,使用原生的多进程方法调用,帮助读者理解多进程的实现机制。代码跑在 linux 环境下。没有 linux 条件的,可以使用 docker 或者虚拟机运行进行体验。docker pull python:2...

weixin_39804603的博客 418

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

python 多进程 内存增长_python多进程中的内存复制(实例讲解)

导读热词比较好奇python对于多进程中copy on write机制的实际使用情况。目前从实验结果来看,python 使用multiprocessing来创建多进程时,无论数据是否不会被更改,子进程都会复制父进程的状态(内存空间数据等)。所以如果主进程耗的资源较多时,不小心就会造成不必要的大量的内存复制,从而可能导致内存爆满的情况。示例举个例子,假设主进程读取了一个大文件对象的所有行,然后通过m...

weixin_30425639的博客 1109

Python多进程进行OCR图文识别

本文介绍了一个使用Python多进程技术进行批量图片OCR识别的脚本。该脚本采用进程池方式处理本地图片列表,每个子进程独立运行CnOCR模型识别图片文字,并将结果写入不同的TXT文件以避免竞争。文中提到由于CnOCR对内存要求较高,建议合理设置进程数量(并非越多越好),并给出了可调参数说明。脚本会自动记录处理时间,最终每个进程生成独立的识别结果文件,用户可根据需要自行合并。该方案能有效提高OCR批量处理的效率,适合本地图片文字识别场景。

qq_43326214的博客 257

python创建多进程_python基于multiprocessing的多进程创建方法

本文实例讲述了python基于multiprocessing的多进程创建方法。分享给大家供大家参考。具体如下:import multiprocessingimport timedef clock(interval):while True:print ("the time is %s"% time.time())time.sleep(interval)if __name__=="__main__":...

weixin_39825872的博客 103

python3多进程实现

if name == “main”:print(“Parent process %s.”%(os.getpid()))for i in range(5):p = Process(target=run_process,args=(str(i),))print(“Process will start.”)p.start()p.join()print(“Process end”)Parent process 21073.Process will start.Process will start.Process w

2401_84138927的博客 931

python基础教程:多线程与多进程

现在能在网上找到很多很多的学习资源,有免费的也有收费的,当我拿到1套比较全的学习资源之前,我并没着急去看第1节,我而是去审视这套资源是否值得学习,有时候也会去问一些学长的意见,如果可以之后,我会对这套学习资源做1个学习计划,我的学习计划主要包括规划图和学习进度表。

2401_84572752的博客 960

用Python多进程 实现socket tcp协议 server端的并发_python tcp server 多进程(1)

我们在看视频学习的时候,不能光动眼动脑不动手,比较科学的学习方法是在理解之后运用它们,这时候练手项目就很适合了,只是里面的项目比较多,水平也是参差不齐,大家可以挑自己能做的项目去练练。使用多进程 实现socket tcp协议 server端的并发。

2401_84138927的博客 861

视频教程-Python编程的术与道:Python语言进阶-Python

Python编程的术与道:Python语言进阶 大学教授,美国归国博士、博士...

weixin_34709474的博客 352

python多进程关闭socket_python socket多线程和多进程(1)

现在能在网上找到很多很多的学习资源,有免费的也有收费的,当我拿到1套比较全的学习资源之前,我并没着急去看第1节,我而是去审视这套资源是否值得学习,有时候也会去问一些学长的意见,如果可以之后,我会对这套学习资源做1个学习计划,我的学习计划主要包括规划图和学习进度表。

m0_60721860的博客 671

Python学习三阶段经典书籍推荐:从零基础到项目实战再到深入理解

Python作为一门广泛应用于数据分析、Web开发、自动化脚本等领域的编程语言,其学习路径通常遵循从基础语法到项目实践,再到深入理解语言核心的渐进过程。掌握Python不仅需要理解变量、函数、类等基本概念,更需要通过实际项目将知识点串联,并最终深入其数据模型、并发机制等原理,以编写出高效、优雅的Pythonic代码。对于初学者,环境配置(如python安装、vscode配置python)往往是第一道门槛,而选择与学习阶段精准匹配的经典教材至关重要。本文针对Python学习中的常见痛点,推荐了三本分别对应零基

java2000.net 349
上一篇: 深入Python多进程编程基础
下一篇: 深入Python多进程通信原理与实战——图文
码洞
博客等级 码龄11年 41粉丝 137原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值