多处理基础

生成秒的最简单方法是使用目标函数实例化 Process对象并调用start() 使其开始工作。


import  multiprocessing 

def  worker (): 
    """worker function""" 
    print  'Worker' 
    return 

if  __name__  ==  '__main__' : 
    jobs  =  [] 
    for  i  in  range ( 5 ): 
        p  =  multiprocessing 。处理(目标=工人)
        工作。追加( p ) 
        p 。开始()


输出包括打印了五次的“Worker”这个词,尽管根据执行顺序它可能并不完全干净。


$蟒蛇multiprocessing_simple.py

工人
,工人
,工人
,工人
,工人


能够产生一个带有参数的进程来告诉它要做什么通常更有用。与线程不同,要将参数传递给多处理 进程,参数必须能够使用pickle进行序列化。这个例子传递给每个工人一个数字,所以输出更有趣一些。


import  multiprocessing 

def  worker ( num ): 
    """thread worker function""" 
    print  'Worker:' ,  num 
    return 

if  __name__  ==  '__main__' : 
    jobs  =  [] 
    for  i  in  range ( 5 ): 
        p  =  multiprocessing 。处理( target = worker ,  args = ( i ,))
        作业。追加( p ) 
        p. 开始()


整数参数现在包含在每个工作人员打印的消息中:


$ python multiprocessing_simpleargs.py

工人:0
工人:1
工人:2
工人:3
工人:4


可导入的目标函数

在之间的一个区别线程多处理 的例子是额外的保护__main__在使用 多处理的例子。由于新进程的启动方式,子进程需要能够导入包含目标函数的脚本。将应用程序的主要部分包装在对__main__的检查中,确保它不会在导入模块时在每个子项中递归运行。另一种方法是从单独的脚本中导入目标函数。

例如,这个主程序:



import  multiprocessing 
import  multiprocessing_import_worker 

if  __name__  ==  '__main__' : 
    jobs  =  [] 
    for  i  in  range ( 5 ): 
        p  =  multiprocessing 。处理(目标= multiprocessing_import_worker 。工人)
        的作业。追加( p ) 
        p 。开始()



使用这个工作函数,定义在一个单独的模块中:



def  worker (): 
    """worker function""" 
    print  'Worker' 
    return



并产生与上面第一个示例类似的输出:



$蟒蛇multiprocessing_import_main.py

工人
,工人
,工人
,工人
,工人


确定当前进程

传递参数来标识或命名过程很麻烦,而且没有必要。每个Process实例都有一个带有默认值的名称,可以在创建流程时更改该名称。命名进程对于跟踪它们很有用,尤其是在同时运行多种类型进程的应用程序中。



import  multiprocessing 
import  time 

def  worker (): 
    name  =  multiprocessing . current_process () 。名称
    打印 名称, “开始”
    时间。sleep ( 2 )
    打印 名称, '退出' 

def  my_service (): 
    name  =  multiprocessing 。current_process () 。名称
    打印 名称, “开始”
    时间。睡觉(3 )
    打印 名称, '退出'

如果 __name__  ==  '__main__' : 
    service  =  multiprocessing 。Process ( name = 'my_service' ,  target = my_service ) 
    worker_1  =  multiprocessing 。进程( name = 'worker 1' ,  target = worker ) 
    worker_2  =  multiprocessing 。进程(目标=工人) # 使用默认名称

    worker_1 。开始() 
    worker_2 。启动()
    服务。开始()



调试输出的每一行都包含当前进程的名称。名称列中带有Process-3的行对应于未命名的进程worker_1。



$ python multiprocessing_names.py 

worker 1 启动
worker 1 退出
进程3 启动
进程3 退出
my_service 启动
my_service 退出


守护进程

默认情况下,直到所有子程序都退出后,主程序才会退出。有时启动后台进程运行时不会阻止主程序退出是很有用的,例如在可能没有简单方法中断工作程序的服务中,或者在工作过程中让它死掉不会丢失或损坏数据(例如,为服务监控工具生成“心跳”的任务)。

要将进程标记为守护进程,请使用布尔值设置其守护进程属性。默认情况下,进程不是守护进程,因此传递 True 会打开守护进程模式。



import  multiprocessing 
import  time 
import  sys 

def  daemon (): 
    p  =  multiprocessing . current_process ()
    打印 'Starting:' ,  p 。姓名, 页码。pid
    系统。标准输出。冲洗()
    时间。sleep ( 2 )
    打印 'Exiting:' ,  p 。姓名, 页码。pid
    系统。标准输出。flush () 

def  non_daemon (): 
    p  =  multiprocessing 。current_process ()
    打印 'Starting:' ,  p 。姓名, 页码。pid
    系统。标准输出。flush ()
    打印 'Exiting :' ,  p 。姓名, 页码。pid
    系统。标准输出。flush () 

if  __name__  ==  '__main__' : 
    d  =  multiprocessing. 进程( name = 'daemon' ,  target = daemon ) 
    d . 守护进程 = 真

    n  = 多处理。进程( name = 'non-daemon' ,  target = non_daemon ) 
    n 。守护进程 = 假

    d . 开始()
    时间。睡眠( 1 ) 
    n 。开始()