深入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... 阅读详情

相关推荐

攻防世界 Crypto 新手练习区 1-12 全详解

本篇是攻防世界 Crypto 新手练习区的全解

闵行小鱼塘 3736

python多进程

python多进程

weixin_43717602的博客 998

CMake、Make、MinGw、Clang、Llvm、GCC、MSVC的区别

除开 GCC (GNU 编译器集合) 以外,MinGW 还包含有一些其他的 GNU 程序开发工具;的缩写,MinGw是windows版本的gcc集合。并不仅是一个 C/C++ 编译器,而是一套。是微软开发的VC运行时库,3、Make和CMake是。

m0_37698164的博客 1万+

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

从零构建SOEM主站:基于STM32的EtherCAT伺服控制实战指南

本文详细介绍了如何从零构建基于STM32的SOEM主站系统,实现EtherCAT伺服电机的高精度控制。通过硬件选型、SOEM协议栈移植、PDO/SDO配置优化等实战步骤,帮助开发者掌握工业自动化中的关键运动控制技术,特别适用于23位编码器伺服电机的应用场景。

weixin_29186249的博客 667

从FER2013到AffectNet:表情识别数据集十年演进史与你的项目选型攻略

本文回顾了从FER2013到AffectNet等主流人脸表情识别数据集的十年演进历程,详细分析了各数据集的特点、适用场景及技术突破。针对不同项目需求,提供了从移动端应用到高精度研究的选型策略,特别强调AffectNet在现代FER项目中的核心价值,并给出混合数据集构建的实战方案。

weixin_26808439的博客 522

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

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

芳樽里的歌的博客 1744

肖特基二极管选型参数,结构原理,工艺与注意问题总结

肖特基二极管(Schottky Diode)是一种特殊的二极管,也被称为肖特基势垒二极管。它是利用金属与半导体接触形成的金属-半导体结原理制成的。与传统的PN结二极管相比,肖特基二极管具有更低的正向压降、更高的开关速度、更高的反向恢复时间以及更好的温度稳定性等特点。本文对肖特基二极管的工作原理,结构特点,工艺流程,选型参数及设计注意事项进行总结。

fydar的博客 815

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

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

3万+

基于FPGA的万兆以太网学习(1)

万兆(10G) 以太网测速视频:SFP+屏蔽笼可以插入千兆或万兆光模块。SFP+信号定义与 SFP 一致。

baidu_34971492的博客 2250

Thinkpad可以安装Win11吗?Thinkpad升级Win11教程

win11正式版推出之后,不少用户也想要体验一把新系统,但是不知道thinkpad是否支持win11,其实基本上现在在售的都是可以升级win11的。2、如果大家使用的是老款的ThinkPad,那么可以通过软件来检测自己是否支持win11。【电脑健康状况检查下载】答:在售的ThinkPad都是可以支持win11的,但是部分旧版本不支持。2、这时候想要升级win11的话,就可以通过镜像系统的方式来跳过系统检测。3、如果使用上面的软件检测可以支持win11,那么只要进入“设置”

xhp618的博客 2989

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

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

JaweG 867

uniapp(全端兼容) - 超详细接入百度统计功能,给uniapp全平台各端项目引入添加百度统计的插件统计流量详细的步骤教程(提供最新的百度统计源代码,详细的示例代码复制粘贴即可快速搞定!)

uniapp h5 app 使用加入接入百度统计,uniapp百度统计,uniapp详细引入百度统计的教程,uniapp接入百度统计,uniapp如何实现加入百度的统计代码,uniapp怎么植入百度统计详细教程,uniapp如何对接百度统计,uniapp百度统计不生效怎么办,uniapp使用百度统计不生效常见问题,uniapp引入百度统计后没有生效,uniapp h5网页接入百度统计代码后没有统计无效,uniapp最新接入使用百度统计功能,uniapp增加百度统计代码,uniapp app如何接入百度统计,

✅ 精选推荐文章 1万+

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

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

weixin_40004081的博客 163

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

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

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

weixin_33976072的博客 233

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

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

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

weixin_39804603的博客 418

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

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多进程通信原理与实战——图文
codehole_
博客等级 码龄7年 34粉丝 132原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值