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
相关推荐
沃洛德.辛肯17 分钟前
PyTorch 的 F.scaled_dot_product_attention 返回Nan
人工智能·pytorch·python
noravinsc29 分钟前
人大金仓数据库 与django结合
数据库·python·django
豌豆花下猫36 分钟前
Python 潮流周刊#102:微软裁员 Faster CPython 团队(摘要)
后端·python·ai
yzx9910131 小时前
Gensim 是一个专为 Python 设计的开源库
开发语言·python·开源
麻雀无能为力1 小时前
python自学笔记2 数据类型
开发语言·笔记·python
Ndmzi1 小时前
matlab与python问题解析
python·matlab
懒大王爱吃狼2 小时前
怎么使用python进行PostgreSQL 数据库连接?
数据库·python·postgresql
猫猫村晨总2 小时前
网络爬虫学习之httpx的使用
爬虫·python·httpx
web150854159352 小时前
Python线性回归:从理论到实践的完整指南
python·机器学习·线性回归
ayiya_Oese2 小时前
[训练和优化] 3. 模型优化
人工智能·python·深度学习·神经网络·机器学习