深入Python多进程编程基础

python多进程基础教程:python并发编程之多进程 文章目录一 multiprocessing模块介绍二 Process类的介绍三 Process类的使用四 守护进程五 进程同步(锁)六 队列(推荐使用)七 管道八 共享数据九 信号量(了解)十 事件(了解)十一 进程池回掉函数: 一 multiprocessing模块介绍 python中的多线程无法利用多核优势,如果想要充分地使用多核CPU的资源(os.cpu_count()查看),在python... 阅读详情

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

docker pull python:2.7

生成子进程

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

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是在父进程里执行,如果是子进程,就不要在调用了。

# 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可以使进程休眠任意时间,单位为秒,可以是小数

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)。

# 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函数会返回子进程的退出状态,它就像子进程留下的临终遗言,必须等父进程听到后才能彻底瞑目。

# 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之后,子进程终于停止了输出。

接下来我们换一个自定义信号处理函数,子进程收到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

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

接下来我们用多进程版本,我们用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 多进程编程基础与实例 模块是Python标准库中用于多进程编程的模块。它提供了一个类似于threading模块的API,但是能够创建并管理进程,而不是线程。使用模块可以方便地创建子进程,并通过进程间通信(IPC)机制在进程之间传递数据。模块还提供了丰富的工具和函数,用于控制进程的行为,如进程池、锁、事件等。 阅读详情

相关推荐

Python多进程与多线程编程【python基础篇】

Python多进程与多线程编程摘要: Python提供了多进程和多线程两种并发编程方式。多线程通过threading模块实现,线程共享进程内存但需注意线程安全问题。创建线程有两种方式:直接使用Thread类或继承Thread类。线程状态包括新建、就绪、运行、阻塞和终止。为解决线程安全问题,Python提供了锁(Lock)、RLock、Semaphore等同步机制。多进程适用于CPU密集型任务,每个进程有独立内存空间;多线程适用于I/O密集型任务,线程间通信更高效但需处理同步问题。选择哪种方式取决于具体应用场

博客 1793

python多进程

python多进程

weixin_43717602的博客 998

汽车软件工程师必看:ASPICE流程实战指南(附完整产物清单)

本文为汽车软件工程师提供ASPICE流程实战指南,详细解析如何搭建合规开发环境、各阶段文档产出清单及工具链整合策略。通过实战案例和模板资源,帮助团队高效实施ASPICE标准,提升软件开发质量与效率。

weixin_29230805的博客 472

杀死僵尸进程(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

Proteus仿真AT89C51驱动DHT11:温湿度数据采集与LCD1602显示的5个调试坑点总结

本文总结了在Proteus仿真环境下使用AT89C51驱动DHT11温湿度传感器并通过LCD1602显示的5个常见调试坑点,包括DHT11时序问题、LCD1602初始化错误、数据校验失败、仿真特有差异及系统稳定性问题,提供了详细的解决方案和优化代码示例,帮助开发者高效完成温湿度采集项目。

weixin_30335575的博客 357

AniME框架深度体验:用AI自动生成《修真小说》动画全流程记录

本文详细记录了使用开源多智能体框架AniME,结合其核心动画生成模型AniSora V3,将一段修真小说文本自动转化为风格统一动画视频的全流程实战。文章深入解析了从环境搭建、导演智能体任务分解,到多智能体协作生成分镜、角色、动画及最终合成的每一步操作与挑战,为AI驱动的长视频创作提供了宝贵的实践经验与流程优化思路。

ol789012345的博客 626

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

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

芳樽里的歌的博客 1744

Android实现TextToSpeech控件实现语音播报--朗读文字 (附完整源码)

Android实现TextToSpeech控件实现语音播报--朗读文字 (附完整源码)

希望我的博客,能帮上你解决学习中工作中所遇到的问题 1121

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

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

3万+

【AUTOSAR SystemServices】AUTOSAR CP中Watchdog Manager模块技术解析

本文深入解析了AUTOSAR中的Watchdog Manager模块实现。该模块通过多层次监督机制(Alive/Deadline/Logical Supervision)确保系统安全运行,具备动态模式切换和分级故障处理能力。 关键实现包括: 数据结构设计:包含监督实体状态结构体(实时状态维护)、监督配置结构体(支持模式切换)和全局状态信息(系统级监控) 核心流程优化:初始化采用事务性设计,检查点处理通过条件编译优化,主监控循环采用流水线式并行处理 监督机制实现:Alive监督采用滑动窗口算法,Deadlin

1039

Claude Code 任务编排 头脑风暴与 疯狂拷问:Superpowers vs Grill-me 硬核对比与工程落地

Superpowers和Grill-me是AI编程中的互补工具:Superpowers提供工程化开发流程(从需求梳理到代码审查),确保规范执行;Grill-me通过持续追问帮助厘清需求,避免方向偏差。两者结合形成"构思-拷问-执行"工作流,前者负责方案生成与落地,后者专注需求审查。根据场景选择:个人项目可用Grill-me快速澄清需求,企业项目推荐Superpowers全流程,复杂开发则建议组合使用。它们分别解决"如何落地"和"是否对齐"的问题,共

十年老程序猿,AI 疯狂研究专家,前沿硬核知识分享 329

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

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

JaweG 867

编写python脚本调用ordinals以及BRC20的接口

1、钱包地址生成walletreceive,对应ord命令:ord wallet receive。6、测试手动出块generate,这个只在regtest链节点用得上。所有接口都是post请求,采用postman进行测试。4、测试bitcoin转币sendtoaddress。7、测试其他的wallet方法wallet。2、钱包币种铭刻inscription,对应bitcoin-cli命令。对应bitcoin-cli命令。对应bitcoin-cli命令。fee.json文本模板。还可以加很多根据需要加减。

云深海阔专栏 1049

Python多进程编程全指南:从基础到实战

在 Python 开发中,充分利用多核 CPU 资源是提升程序性能的关键。当面对 CPU 密集型任务时,多线程由于 GIL(全局解释器锁)的限制难以发挥多核优势,而多进程编程成为解决这一问题的理想方案。本文将全面介绍 Python 标准库multiprocessing的使用方法,从基础概念到高级技巧,助你轻松掌握多进程编程。

weixin_48552411的博客 1160

60、新型共轴直升机建模与事件触发积分强化学习研究

本文研究了新型共轴直升机的动力学建模与控制方法,基于牛顿-欧拉方程建立了6自由度非线性模型,并设计了四通道闭环控制器实现稳定飞行。同时,提出一种事件触发积分强化学习方法,用于解决非零和博弈中的最优跟踪控制问题,在减少通信开销的同时保证系统性能。通过仿真验证了控制器的轨迹跟踪能力,并证明了算法下跟踪误差与神经网络权重估计误差的一致最终有界性。两种方法协同可提升飞行器的自主性与鲁棒性,未来可拓展至多智能体协作、智能交通等复杂系统应用。

rl6adventurer的博客 118

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

《100天精通Python——基础篇 2025 第24天:Python 多进程编程入门与实战详解》

本文聚焦 Python 多进程编程,系统讲解 multiprocessing 模块的核心用法,包括 Process 类的使用、进程间通信(队列、管道)、进程池以及进程同步机制。通过实战案例对比多线程与多进程在 CPU 密集型任务中的性能差异,深入理解为何多进程可以突破 GIL 限制,实现真正的并行计算。文章内容循序渐进,帮助读者构建对多进程编程的整体认知,为高性能程序开发打下坚实基础。

XAMO Lab|代码、调试与复盘笔记 1344

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

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

多进程编程知识是Python程序员进阶高级的必备知识点,我们平时习惯了使用multiprocessing库来操纵多进程,但是并不知道它的具体实现原理。下面我对多进程的常用...

shellquery的博客 135

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

深入理解Python多进程编程:从基础到实战案例解析

深入理解Python多进程编程:从基础到实战案例解析

学习成长日记 1162

【python内功修炼001】:python多进程编程基础

文章目录一、什么是进程?1、程序的定义:完成特定任务的一系列指令集合2、进程的定义:就是一个运行的程序或者软件。3、进程和程序的区别4、进程的作用二、什么是线程?1、线程的定义:是进程的一个实体三、线程和进程的区别四、浅析并发和并行五、多道程序技术五、浅析同步\异步\阻塞\非阻塞1、同步和异步2、阻塞和非阻塞六、Python进程详解1、进程的创建2、进程的终止3、进程的层次结构4、进程的状态4.1...

金鞍少年的博客 826

Python多进程编程 ---- 基础篇6. Pipe

----------基础篇 引子 创建管道方法: Pipe([duplex]):在进程之间创建一条管道,并返回元组(conn1,conn2),其中conn1,conn2表示管道两端的连接对象,强调一点:必须在产生Process对象之前产生管道。dumplex:默认管道是全双工的,如果将duplex射成False,conn1只能用于接收,conn2只能用于发送。 conn1.recv():接收conn2.send(obj)发送的对象。如果没有消息可接收,recv方法会一直阻塞。如果连接的另外一端已经关闭,那么

愿时光能缓故人不散 563

python基础知识学习——多进程编程

多进程编程1.什么是进程2.进程的层次结构3.进程并发的现象4.multiprocessing模块介绍5.multiprocessing模块的使用开启进程的两种方式互斥锁确定当前进程守护进程终止进程进程通信Queue队列传递Pipe管道通信Managers数据共享 1.什么是进程 进程是系统中正在运行的一个程序,程序一旦运行就是进程。 进程可以看成程序执行的一个实例。进程是系统资源分配的独立实体...

Dim_Jerry的博客 667

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

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

weixin_40004081的博客 163

深入探究Python多进程编程:Multiprocessing模块基础与实战

在Python编程中,多进程处理是一项关键的技术,特别是在需要处理大规模数据或执行耗时任务时。为了充分利用多核处理器的优势,Python提供了`multiprocessing`模块,使得并行编程变得更加容易。本文将深入探讨`multiprocessing`模块的基础知识,并通过实际代码示例演示其在解决实际问题中的应用。

一键难忘的博客 4297
上一篇: 为什么阿里的员工要带着工牌逛街?
下一篇: 深入Python多进程编程基础——图文版
codehole_
博客等级 码龄7年 34粉丝 132原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值