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中遇到的小问题及解决方法汇总

Python中遇到的小问题及解决方法汇总

本文会把学习过程中遇到的一些小问题和解决办法放在这里,以便于大家能够更好地学习python。 一、Python的异常处理 因为想到自己不断尝试写小程序的话会用到抛出异常信息来判断哪里出现...

在Python中移动目录结构的方法

来源:http://stackoverflow.com/questions/3806562/ways-to-move-up-and-down-the-dir-structure-in-p...

跟老齐学Python之总结参数的传递

就前面所讲,函数的基本内容已经完毕。但是,函数还有很多值得不断玩味的细节。这里进行阐述。 参数的传递 python中函数的参数通过赋值的方式来传递引用对象。下面总结通过总结常见的函数参数...

python对list中的每个元素进行某种操作的方法

如下所示: ''' 对列表中的每个元素进行某种操作 ''' def add(c): return c**2 l = [1,2,3] d1 = map(add,l) print d...

python实现多线程的方式及多条命令并发执行

一、概念介绍 Thread 是threading模块中最重要的类之一,可以使用它来创建线程。有两种方式来创建线程:一种是通过继承Thread类,重写它的run方法;另一种是创建一个th...