python使用多进程的实例详解

yipeiwu_com5年前Python基础

python多线程适合IO密集型场景,而在CPU密集型场景,并不能充分利用多核CPU,而协程本质基于线程,同样不能充分发挥多核的优势。

针对计算密集型场景需要使用多进程,python的multiprocessing与threading模块非常相似,支持用进程池的方式批量创建子进程。

•创建单个Process进程(使用func)

只需要实例化Process类,传递函数给target参数,这点和threading模块非常的类似,args为函数的参数

import os
from multiprocessing import Process
# 子进程要执行的代码
def task(name):
  print('run child process %s (%s)...' % (name, os.getpid()))
if __name__ == '__main__':
  print('parent process %s.' % os.getpid())
  p = Process(target=task, args=('test',))
  p.start()
  p.join()
  print('process end.') 

•创建单个Process进程(使用class)

继承Process类,重写run方法创建进程,这点和threading模块基本一样

import multiprocessing
import os
from multiprocessing import current_process
class Worker(multiprocessing.Process):
  def run(self):
    name = current_process().name # 获取当前进程的名称
    print('run child process <%s> (%s)' % (name, os.getpid()))
    print('In %s' % self.name)
    return
if __name__ == '__main__':
  print('parent process %s.' % os.getpid())
  p = Worker()
  p.start()
  p.join()
  print('process end.') 
  * 停止进程

terminate()结束子进程,但是会导致子进程的资源无法释放掉,是不推荐的做法,因为结束的时候不清楚子线程的运行状况,有很大可能性导致子线程在不恰当的时刻被结束。

import multiprocessing
import time
def worker():
  print('starting worker')
  time.sleep(0.1)
  print('finished worker')
if __name__ == '__main__':
  p = multiprocessing.Process(target=worker)
  print('执行前:', p.is_alive())
  p.start()
  print('执行中:', p.is_alive())
  p.terminate() # 发送停止号
  print('停止:', p.is_alive())
  p.join()
  print('等待完成:', p.is_alive()) 

•直接创建多个Process进程

import multiprocessing
def worker(num):
  print(f'Worker:%s %s', num)
  return
if __name__ == '__main__':
  jobs = []
  for i in range(5):
    p = multiprocessing.Process(target=worker, args=(i,))
    jobs.append(p)
    p.start() 

•使用进程池创建多个进程

在利用Python进行系统管理的时候,特别是同时操作多个文件目录,或者远程控制多台主机,并行操作可以节约大量的时间。当被操作对象数目不大时,可以直接利用multiprocessing中的Process动态成生多个进程,十几个还好,但如果是上百个,上千个目标,手动的去限制进程数量却又太过繁琐,此时可以发挥进程池的功效。

Pool可以提供指定数量的进程供用户调用,当有新的请求提交到pool中时,如果池还没有满,那么就会创建一个新的进程用来执行该请求;但如果池中的进程数已经达到规定最大值,那么该请求就会等待,直到池中有进程结束,才会创建新的进程来它。

import os
import random
import time
from multiprocessing import Pool
from time import ctime
def task(name):
  print('start task %s (%s)...' % (name, os.getpid()))
  start = time.time()
  time.sleep(random.random() * 3)
  print('end task %s runs %0.2f seconds.' % (name, (time.time() - start)))
if __name__ == '__main__':
  print('parent process %s.' % os.getpid())
  p = Pool() # 初始化进程池
  for i in range(5):
    p.apply_async(task, args=(i,)) # 追加任务 apply_async 是异步非阻塞的,就是不用等待当前进程执行完毕,随时根据系统调度来进行进程切换。
  p.close()
  p.join() # 等待所有结果执行完毕,会等待所有子进程执行完毕,调用join()之前必须先调用close()
  print(f'all done at: {ctime()}') 

如果关心每个进程的执行结果,可以使用返回结果的get方法获取,代码如下

import os
import random
import time
from multiprocessing import Pool, current_process
from time import ctime
def task(name):
  print('start task %s (%s)...' % (name, os.getpid()))
  start = time.time()
  time.sleep(random.random() * 3)
  print('end task %s runs %0.2f seconds.' % (name, (time.time() - start)))
  return current_process().name + 'done'
if __name__ == '__main__':
  print('parent process %s.' % os.getpid())
  result = []
  p = Pool() # 初始化进程池
  for i in range(5):
    result.append(p.apply_async(task, args=(i,))) # 追加任务 apply_async 是异步非阻塞的,就是不用等待当前进程执行完毕,随时根据系统调度来进行进程切换。
  p.close()
  p.join() # 等待所有结果执行完毕
  for res in result:
    print(res.get()) # get()函数得出每个返回结果的值
  print(f'all done at: {ctime()}') 

总结

以上所述是小编给大家介绍的python使用多进程的实现代码,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对【听图阁-专注于Python设计】网站的支持!

相关文章

详解Python中的装饰器、闭包和functools的教程

装饰器(Decorators) 装饰器是这样一种设计模式:如果一个类希望添加其他类的一些功能,而不希望通过继承或是直接修改源代码实现,那么可以使用装饰器模式。简单来说Python中的装饰...

python实战教程之自动扫雷

python实战教程之自动扫雷

前言 自动扫雷一般分为两种,一种是读取内存数据,而另一种是通过分析图片获得数据,并通过模拟鼠标操作,这里我用的是第二种方式。 一、准备工作 1.扫雷游戏 我是win10,没有默认的扫...

Python及Django框架生成二维码的方法分析

本文实例讲述了Python及Django框架生成二维码的方法。分享给大家供大家参考,具体如下: 一、包的安装和简单使用 1.1 用Python来生成二维码很简单,可以看 qrcode 这...

TensorFlow实现卷积神经网络

TensorFlow实现卷积神经网络

本文实例为大家分享了TensorFlow实现卷积神经网络的具体代码,供大家参考,具体内容如下 代码(源代码都有详细的注释)和数据集可以在github下载: # -*- codin...

Python合并字符串的3种方法

目的   将一些小的字符串合并成一个大字符串,更多考虑的是性能 方法    常见的方法有以下几种: 1.使用+=操作符 复制代码 代码如下:   BigString=small...