首页 > 系统相关 >multiprocessing:Python像线程一样管理进程

multiprocessing:Python像线程一样管理进程

时间:2023-09-22 09:04:25浏览次数:55  
标签:__ p1 name Python 进程 线程 print multiprocessing

前言

multiprocessing库是基于threading API,它可以把工作划分为多个进程。有些情况下,multiprocessing可以作为临时替换取代threading来利用多个CPU内核,相应地避免Python全局解释器锁所带来的计算瓶颈。

下面,我们来看看multiprocessing库创建进程与threading库有多像。

创建一个进程

要创建一个进程,最简单的方式是用一个目标函数实例化一个Process对象,然后与threading一样调用start()函数让它工作。示例如下:

import multiprocessing

def worker():
    for i in range(3):
        print(i)

if __name__=="__main__":
    p = multiprocessing.Process(target=worker)
    p.start()

运行之后,效果如下:

需要注意的是,multiprocessing库在Windows创建进程必须在if name=="main":中,这是 Windows 上多进程的实现问题。在 Windows 上,子进程会自动 import 启动它的这个文件,而在 import 的时候是会执行这些语句的。如果直接创建就会无限递归创建子进程报错。所以必须把创建子进程的部分用那个 if 判断保护起来,import 的时候 name 不是 main ,就不会递归运行了。

设置进程名

在threading线程中,我们可以通过其参数name设置线程名,同样的我们也可以通过name参数设置其进程的名字。示例如下:

import multiprocessing
import time

def worker():
    print(multiprocessing.current_process().name, "start")
    time.sleep(2)
    print(multiprocessing.current_process().name, "end")

if __name__ == "__main__":
    p1 = multiprocessing.Process(name='p1', target=worker)
    p2 = multiprocessing.Process(name='p2', target=worker)
    p3 = multiprocessing.Process(name='p3', target=worker)
    p1.start()
    p2.start()
    p3.start()

运行之后,效果如下:

守护进程

和线程一样,在所有子进程没有退出之前,主程序是不会退出的。有时候,我们可能需要启动一个后台进程,它可以一直运行而不阻塞主程序退出。

要标志一个守护进程,可以将其添加第3个参数daemon,设置为True。默认值为False,不作为守护进程。示例如下:

import multiprocessing
import time

def worker():
    print(multiprocessing.current_process().name, "start")
    time.sleep(1)
    print(multiprocessing.current_process().name, "end")

def worker2():
    print(multiprocessing.current_process().name, "start")
    time.sleep(2)
    print(multiprocessing.current_process().name, "end")

if __name__ == "__main__":
    p1 = multiprocessing.Process(name='p1', target=worker)
    p2 = multiprocessing.Process(name='p2', target=worker2, daemon=True)
    p3 = multiprocessing.Process(name='p3', target=worker2, daemon=True)
    p1.start()
    p2.start()
    p3.start()

运行之后,效果如下:

p2,p3为守护进程,但p1不是所以执行1秒之后,就退出主程序了,也就没有打印p2p3的内容。但是其依旧在执行中,直到执行完成。

join()

同样的,如果你期望强制等待一个守护进程的结束,可以增加join()函数。还是上面的代码,示例如下:

import multiprocessing
import time

def worker():
    print(multiprocessing.current_process().name, "start")
    time.sleep(1)
    print(multiprocessing.current_process().name, "end")

def worker2():
    print(multiprocessing.current_process().name, "start")
    time.sleep(2)
    print(multiprocessing.current_process().name, "end")

if __name__ == "__main__":
    p1 = multiprocessing.Process(name='p1', target=worker)
    p2 = multiprocessing.Process(name='p2', target=worker2, daemon=True)
    p3 = multiprocessing.Process(name='p3', target=worker2, daemon=True)
    p1.start()
    p2.start()
    p3.start()
    p1.join()
    p2.join()
    p3.join()

运行之后,和设置进程名的运行结果一样,这里不在展示。唯一与守护进程代码的区别就是最后三行join()函数代码。当然,也可以像线程一样,给join()函数传入一个时间,超过这个时间,主进程不再等待。

强制结束进程

如果一个进程已经挂起或者不小心进入了死锁状态,那么这个时候,我们往往会强制的结束进程。对一个进程对象调用terminate()会结束子进程。示例如下:

import multiprocessing
import time

def worker():
    print(multiprocessing.current_process().name, "start")
    time.sleep(5)
    print(multiprocessing.current_process().name, "end")

if __name__ == "__main__":
    p1 = multiprocessing.Process(name='p1', target=worker)
    p1.start()
    print("是否还在运行", p1.is_alive())
    p1.terminate()
    print("是否还在运行", p1.is_alive())
    p1.join()
    print("是否还在运行", p1.is_alive())

运行之后,输出如下:

终止进程后要使用join()函数等待进程的退出。使进程管理代码有足够的时间更新对象的状态,以反应进程已经终止。

进程退出状态码

进程退出时,生成的状态码可以通过exitcode属性访问。下表就是其状态码的取值范围以及其意义:

退出码 含义
0 未生成任何错误
>0 进程有一个错误,并以该错误码退出
<0 进程以一个-1*exitcodde信号结束

测试如下:

import multiprocessing
import time

def worker():
    print(multiprocessing.current_process().name, "start")
    time.sleep(5)
    print(multiprocessing.current_process().name, "end")

if __name__ == "__main__":
    p1 = multiprocessing.Process(name='p1', target=worker)
    p2 = multiprocessing.Process(name='p2', target=worker)
    p1.start()
    p2.start()
    print("是否还在运行", p1.is_alive())
    p1.terminate()
    print("是否还在运行", p1.is_alive())
    print(p1.exitcode)
    p1.join()
    print("是否还在运行", p1.is_alive())
    print(p1.exitcode)
    time.sleep(5.5)
    print(p2.exitcode)

运行之后,效果如下:

可以看到,强制退出的进程状态码为负数,正常退出的进程状态码为0。

日志

调试并发问题时,如果能够访问multiprocessing所提供对象的内部状态,那么这会很有用。在实际的项目中,我们可以使用一个方便的模块级函数启用日志记录,它使用logging建立一个日志记录器对象,并增加一个处理器,使日志消息被发送到标准错误通道。

示例如下:

import multiprocessing
import logging
import sys

def worker():
    print("运行工作进程")
    sys.stdout.flush()

if __name__ == "__main__":
    multiprocessing.log_to_stderr(logging.DEBUG)
    p1 = multiprocessing.Process(name='p1', target=worker)
    p1.start()
    p1.join()

运行之后,效果如下:

派生进程

与线程一样,我们可以自定义进程,而不必只是传入一个函数进行进程的创建。

创建的进程的方式也是派生自进程类即可。示例如下:

import multiprocessing

class WorkerProcess(multiprocessing.Process):
    def run(self):
        print(self.name)
        return

if __name__ == "__main__":
    for i in range(5):
        p = WorkerProcess()
        p.start()
        p.join()

运行之后,效果如下:

multiprocessing库的进程知识与threading一样长,因为本篇的内容已经够长了,剩下的知识我们将在下一篇博文中接着讲解。

标签:__,p1,name,Python,进程,线程,print,multiprocessing
From: https://www.cnblogs.com/arena/p/17721470.html

相关文章

  • python爬虫简易demo
    以下是一个简单的Python爬虫示例,用于从指定的网页中提取标题和链接:importrequestsfrombs4importBeautifulSoupdefcrawl(url):#发送HTTPGET请求获取网页内容response=requests.get(url)#使用BeautifulSoup解析网页内容soup=BeautifulSoup(r......
  • Python集合
    #集合是一个无序的不重复元素序列numset={1,2,2,3}#如果存在重复元素保留一个print(numset)sqared={x**2forxin[1,2,3]}#也支持集合推导式print(sqared)set1=set([1,2,3])#从列表和元组通过set()都可转集合print(set1)set1=set(range(1,5))print(set1)s......
  • python实现消消乐游戏界面
    功能需求创建一个简单的10x10的游戏区域,其中包含了6种颜色的方块。实现思路1.首先导入pygame和random库。2.设置屏幕大小为800x600像素。3.定义一个颜色列表,包含了6种不同的颜色。 定义方块的大小为40像素。4.创建一个10x10的游戏区域,每个格子的颜色从颜色列表中随机选择。5.......
  • python: Bubble Sort
     #encoding:utf-8#版权所有2023涂聚文有限公司#许可信息查看:#描述:#Author:geovindu,GeovinDu涂聚文.#IDE:PyCharm2023.1python311#Datetime:2023/9/2121:55#User:geovindu#Product:PyCharm#Project:EssentialAlgor......
  • Python - 读取CSV文件发现有重复数据,如何清洗以及保存为CSV文件,这里有完整的过程!!!!
    语言:Python功能:1、清洗CSV文件中重复数据。2、保存为CSV文件大体流程:1、首先观察CSV文件中的数据布局格式如何?2、通过csv包读取数据。并根据规则使用continue,来跳过本次循环,并将所需数据保存到列表A中,当列表A中的数据变成len(列表A)==2时,将此数据保存到列......
  • Python中numpy出现has no attribute '_no_nep50_warning'错误怎么办?
      本文介绍在Python中,numpy库出现报错module'numpy'hasnoattribute'_no_nep50_warning'的解决方法。  一次,在运行一个Python代码时,发现出现报错module'numpy'hasnoattribute'_no_nep50_warning',如下图所示。  其中,这一代码本来在Windows平台下运行是没有问题的,......
  • 编译 OpenCV 的 Python 依赖
    这一次编译OpenCV的Python依赖为了方便运行我们使用Docker进行编译,环境准备如下:系统依赖:Ubuntu18.04Python版本:3.6,Ubuntu18.04官方源安装的默认版本OpenCV版本:3.4.16,是目前3.x的最新版CMake版本:3.10GCC版本(含C++):7.5我们首先拉取并进入镜像:dock......
  • 20230921-python的get请求和post请求区别
    1.。get请求  2。post请求   ......
  • python+playwright 学习-81 page.expect_request()捕获网络请求
    前言page.expect_request()可以捕获网页上发出去的请求,当有多个请求时,可以根据请求url,请求方式判断。expect_request官方文档示例withpage.expect_request("http://example.com/resource")asfirst:page.get_by_text("triggerrequest").click()first_request=firs......
  • python: Essential Algorithms
     #encoding:utf-8#版权所有2023涂聚文有限公司#许可信息查看:#描述:#Author:geovindu,GeovinDu涂聚文.#IDE:PyCharm2023.1python311#Datetime:2023/9/2121:28#User:geovindu#Product:PyCharm#Project:EssentialAlgor......