进程-multiprocessing

如果你打算编写多进程的服务程序,Unix/Linux无疑是正确的选择。由于Windows没有fork调用,难道在Windows上无法

用Python编写多进程的程序?由于Python是跨平台的,自然也应该提供一个跨平台的多进程支持。multiprocessing模

块就是跨平台版本的多进程模块。windows和linux均可运行。

使用子进程代替线程,可以有效避免 Global Interpreter Lock 带来的影响。

在 multiprocessing 中,通过创建一个 Process 对象然后调用它的 start() 方法来生成进程。 Process 和 threadind.Thread API 相同,不再赘述。

 

1. 创建进程

import os
from multiprocessing import Process

def f(name):
    print('hello', name)

def test_multi_process():
    p = Process(target=f, args=('bob',))
    p.start()
    p.join()

if __name__ == '__main__':
    test_multi_process()

   有趣的是如果不把 test_multi_process() 放在  if __name__ == '__main__' 内就会出错,即:

import os
from multiprocessing import Process

def f(name):
    print('hello', name)

def test_multi_process():
    p = Process(target=f, args=('bob',))
    p.start()
    p.join()

test_multi_process()   # 出错

"""
    An attempt has been made to start a new process before the current process has finished its bootstrapping phase.
    This probably means that you are not using fork to start your child processes and you have forgotten to use the 
proper idiom in the main module:
       if __name__ == '__main__':
        freeze_support()
        ...
  The "freeze\_support()" line can be omitted if the program is not going to be frozen to produce an executable.
"""

   分析:由于Python运行过程中,新创建进程后,进程会导入正在运行的文件,代码在运行到 Process(target=f, args=('bob',)) 时,新的进程会重新

   读入该代码,因为在脚本运行过程中读入的代码命名空间都不会被命名为"__main__"。所以没有 if __name__=="__main__" 保护的代码,新进程都认为

   是要再次运行的代码,即子进程又会再次运行 Process(target=f, args=('bob',))。

 

2. 进程池

   Pool 可以提供指定数量的进程供用户调用,当有新的请求提交到pool中时,如果池还没有满,那么就会创建一个新的进程用来执行该请求;但如果池

   中的进程数已经达到规定最大值,那么该请求就会等待,直到池中有进程结束,才会创建新的进程来它。

import os
from multiprocessing import Pool

def long_time_task(name):
    print('Run task %s (%s)...' % (name, os.getpid()))
    start = time.time()
    time.sleep(random.random() * 3)
    end = time.time()
    print('Task %s runs %0.2f seconds.' % (name, (end - start)))

def test_pool():
    print('Parent process %s.' % os.getpid())

    # 因为Pool的默认大小设为是4,因此,最多同时执行4个进程。这是Pool有意设计的限制,并不是操作系统的限制。
    # 如果改成p = Pool(5) 就可以同时跑5个进程。
    p = Pool(4)

    for i in range(5):
        # apply方法是阻塞的。意思就是等待当前子进程执行完毕后,再执行下一个进程。跟单进程串行执行没什么区别了
        # apply_async 是异步非阻塞的。意思就是:不用等待当前进程执行完毕,随时根据系统调度来进行进程切换。
        p.apply_async(long_time_task, args = (i,))  # 开始执行四个子进程
    print('Waiting for all subprocesses done...')
    """
    当进程池close的时候并未关闭进程池,只是会把状态改为不可再插入元素的状态,完全关闭进程池使用
    """
    p.close()
    p.join()  # 等待所有子进程结束
    print('All subprocesses done.')

if __name__ == '__main__':
    test_pool()

 

posted @ 2020-07-06 18:05  _yanghh  阅读(152)  评论(0编辑  收藏  举报