python多进程程序设计 之一

python多进程程序设计 之一

multiprocessing

multiprocessing 是一个python模块,它使用类似于线程模块的 API生成进程。multiprocessing模块提供本地和远程并行运行,通过使用子进程代替线程,有效地回避python全局解释器锁。因此,多处理模块允许程序员充分利用给定机器上的多个处理器。

multiprocessing模块还引入了线程模块中没有API。一个典型的例子是 Pool 对象,它提供了一种方便的方法,跨多个输入值并行执行函数,跨进程分配输入数据(数据并行性)。

Process类

在 multiprocessing中,通过创建Process对象,然后调用其 start() 方法来生成进程。

产生进程

根据平台的不同,多处理支持三种启动进程的方式。这些启动方法是

  • spawn, 父进程启动一个新的Python解释器进程。子进程只会继承运行进程对象的 run() 方法所需的资源。特别是,来自父进程的,不必要的文件描述符和句柄将不会被继承。与使用 fork 或 forkserver 相比,使用此方法启动进程相当慢。
  • fork, 父进程使用 os.fork() 来 fork Python 解释器。子进程在启动时实际上与父进程相同。父进程的所有资源都被子进程继承。
  • forkserver, 当程序选择 forkserver 启动方法时,会生成一个服务器进程。从那时起,每当需要新进程时,父进程就会连接到服务器并请求它派生一个新进程。 fork 服务器进程是单线程的,除非系统库或预加载的imports产生线程的副作用,因此使用 os.fork() 通常是安全的。不会继承不必要的资源。

在 POSIX 上,使用spawn或forkserver启动方法还将启动一个资源跟踪器进程,该进程跟踪由程序进程创建的未链接的命名系统资源(例如,命名信号量或SharedMemory对象)。当所有进程退出后,资源跟踪器将取消任何剩余跟踪对象的链接。通常应该没有这样的对象,但如果进程被信号杀死,则可能会出现一些"泄漏"资源。

set_start_method()启动

在主模块的 if name == 'main' 子句中,使用 set_start_method() 。

from multiprocessing import *

def subproc():
    print("subprocess")

if __name__ == '__main__':
    set_start_method('spawn')
    p = Process(target=subproc)
    p.start()
    p.join()

显示器输出

javascript 复制代码
subprocess
get_context()启动

使用 get_context() 来获取上下文对象。上下文对象具有与multiprocessing模块相同的 API,并允许在同一程序中多次使用启动方法。

from multiprocessing import *

def subproc():
    print("subprocess")

if __name__ == '__main__':
    print("call get_context...")
    ctx = get_context('spawn')
    p = ctx.Process(target=subproc)
    p.start()
    p.join()

显示器输出

javascript 复制代码
call get_context...
subprocess

成员函数

构造函数

multiprocessing.Process(group=None, target=None, name=None, args=(), kwargs={}, *, daemon=None)

Process对象表示在单独流程中运行的活动。

  • group,应始终为None。
  • target, 是由 run() 方法调用的可调用对象。它默认为 None,这意味着什么都不被调用。
  • name, 是进程名称。
  • args,是目标调用的参数元组。
  • kwargs, 是目标调用的关键字参数的字典。
  • daemon,如果提供,daemon参数将进程的daemon标志设置为 True 或 False。如果 None (默认),该标志将从创建进程继承。

默认情况下,没有参数传递给target。 args 参数默认为 (),可用于指定要传递给target的参数列表或元组。

如果子类重写构造函数,则它必须确保,在对进程执行任何其他操作之前,调用基类构造函数 (Process.init())。

run/start

词法: run()

Process类的成员函数run()表示进程的活动。

在子类中可以重载这个函数。标准run()函数调用可调用对象target,target是作为参数target传递给构造函数。如果该构造函数包含可调用对象target,则构造器的参数args 和 kwargs,将作为参数,传递给可调用对象target。

词法:start()

Process类的成员函数start()启动进程的活动。

每个进程对象最多只能调用一次。它在单独的进程中,调用对象的 run() 方法。

join

词法: join([timeout])

  • 如果可选参数 timeout为None (默认值),则该函数将阻塞,直到调用 join() 函数的进程终止。
  • 如果 timeout 是正数,则最多阻塞 timeout 秒。如果该函数的进程终止,或该函数超时,则该函数将返回 None。检查进程的退出代码,以确定它是否终止。

一个进程可以多次调用join。

进程无法join自身,因为这会导致死锁。在进程启动之前,调用join是错误的。

应用实列

实列说明

该实列使用两种不同的方法产生进程的活动

  • Consumer子进程使用构造函数
  • Producer子进程使用进程子类run()成员函数。在__init__(self,...)中,必须调用super(Producer,self).init()初始化基类的初始化函数。
  • Producer子进程使用进程子类的参数传递方法更方便,灵活。

实列代码

from multiprocessing import *

def Consumer(v1, v2, v3, width):
    print("Consumer v1:{0} v2:{1} v3: {2} width: {3}".format(v1, v2, v3, width))

class Producer(Process):
    def __init__(self, args, keys):
        super(Producer,self).__init__()
        self.args = args;
        self.keys = keys;
        
    def run(self):
        print("Producer args: {0}".format(self.args))
        print("Producer keys: {0}".format(self.keys))
    
if __name__ == '__main__':
    print("call get_context...")
    ctx = get_context('spawn')
    args = [1, 2, 3]
    keys = {"width":"12"}
    
    p1 = ctx.Process(target=Consumer, args=args, kwargs=keys)
    p2 = Producer(args, keys);

    p1.start()
    p2.start()
    
    p1.join()
    p2.join()
    
    print("Consumer exit code:{0}".format(p1.exitcode))
    print("Producer exit code:{0}".format(p2.exitcode))

显示器输出

call get_context...
Consumer v1:1 v2:2 v3: 3 width: 12
Producer args: [1, 2, 3]
Producer keys: {'width': '12'}
Consumer exit code:0
Producer exit code:0
相关推荐
亿牛云爬虫专家11 分钟前
优化数据的抓取规则:减少无效请求
python·数据采集·多线程·爬虫代理·数据抓取·代理ip·房价
程序媛堆堆13 分钟前
解决NotOpenSSLWarning: urllib3 v2 only supports OpenSSL 1.1.1+问题
python
DreamByte16 分钟前
Python Tkinter小程序
开发语言·python·小程序
Python极客之家17 分钟前
基于深度学习的眼部疾病检测识别系统
人工智能·python·深度学习·毕业设计·卷积神经网络
Bigcrab__23 分钟前
Python3网络爬虫开发实战(15)Scrapy 框架的使用(第一版)
爬虫·python·scrapy
易辰君1 小时前
Python编程 - 协程
开发语言·python
宇宙第一小趴菜1 小时前
探索网络世界:TCP/IP协议、Python Socket编程及日常生活比喻
网络·python·tcp/ip
小黑032 小时前
Phoenix使用
开发语言·python
南斯拉夫的铁托2 小时前
(PySpark)RDD实验实战——求商品销量排行
python·spark·pyspark
kay_5452 小时前
YOLOv8改进 | 模块缝合 | C2f 融合SCConv提升检测性能【CVPR2023】
人工智能·python·深度学习·yolo·目标检测·面试·yolov8改进