Python多进程

原创 2018年04月17日 15:28:55

多进程介绍

上次我们说到Python多线程是鸡肋一般的存在,它无法利用CPU多核的优势。因此在Python开发中,我们一般使用多进程进行并行开发。multiprocessing是类似于threading模块的包。它支持了本地和远程并发性,可以更充分的利用多核资源。

Process类

要运行一个进程需要创建实例化一个Process对象并且调用该类的start()方法。

`

from multiprocessing import Process

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

if __name__ == '__main__':
    p = Process(target=f, args=('bob',))
    p.start()
    p.join()`

Process([group [, target [, name [, args [, kwargs]]]]]),group默认为None,不使用,参数target为调用的对象,name为子进程的名字,args为调用对象的参数元组,kwargs为调用对象的字典。

有关的方法和属性

Process中的方法与threading.Thread中的十分相似。

run():进程启动时运行的方法。

start():启动进程,会调用子进程中的run()方法。

join([timeout]):主线程等待当前线程终止,timeout为可选的超时时间,join只能join住start开启的进程,而不能join住run开启的进程。

terminate():强制终止进程,不会进行任何清理操作,如果创建了子进程,该子进程就成了僵尸进程。如果进程还保存了一个锁那么也将不会被释放,进而导致死锁。

is_alive():判断进程是否在运行,为bool值。

name:进程的名字,它是string类型,没有语义,只是用于标志进程,多进程中允许使用同一个名字。

dameon:必须在start()调用前设置,默认为false,如果设为True,代表当前进程为后台运行的守护进程,当前进程的父进程终止时,它也随之终止,并且设定为True后,不能创建自己的新进程。

pid:进程的id

每个进程还有特有的id号,可以通过os.getpid()得到当前进程的ID号,也可以直接使用p.pid得到ID。

from multiprocessing import Process
import os

def info(title):
    print(title)
    print('module name:', __name__)
    print('parent process:', os.getppid())#得到父进程的id号
    print('process id:', os.getpid())#得到当前进程的id号

def greet(name):
    info('function greet')
    print('hello', name)

if __name__ == '__main__':
    info('main Process')
    p = Process(target=greet, args=('bob',))
    p.start()
    p.join()

进程间的通信

多进程支持两种进程间通信的方式:队列和管道。

队列

队列具有先进先出的特点,并且它是线程和进程安全的,通过q.put()方法将数据插入到队列中,然后使用q.get()方法将数据取出。

from multiprocessing import Process, Queue

def greet(q):
    q.put("hello")

if __name__ == '__main__':
    q = Queue()
    p = Process(target=f, args=(q,))
    p.start()
    print(q.get())    # 打印hello 
    p.join()

管道

Pipe()函数返回一对双向的连接对象,它们代表管道的两端。每个连接对象有send()和recv()方法。当两个进程或者线程试图同时写入或读取管道的一端时,管道中的数据会被损坏,当然同一时刻使用不同的管道端口不会有损坏的风险。

from multiprocessing import Process, Pipe

def greet(p):
    p.send("hello")
    p.close()

if __name__=='__main__':
    left_p,right_p=Pipe()
    p=Process(target=greet,args=(right_p,))
    p.start()
    print(left_p.recv()) #输出hello
    p.join()

进程间的同步

多进程包含与多线程中等价的同步原语。例如可以使用锁机制确保某一时刻只有一个进程打印到标准输出。

from multiprocessing import Process, Lock

def greet(lock,num):
    lock.acquire()  #获取锁
    print("hello",num)
    lock.release()  #将锁释放

if __name__=='__main__':
    lock=Lock()
    for num in range(5):
        Process(target=greet,args=(lock,num),).start()

进程间分享状态

在进行并发编程时,最好尽量避免使用共享状态,尤其是使用多进程时。但是,如果你确实要使用一些共享的数据,多进程也提供一些方法。

共享内存

数组可以利用Value和Array存储在共享内存映射中。

from multiprocessing import Process, Value, Array

def share(val,arr):
    val.value=1
    for i in range(len(arr)):
        arr[i]=arr[i]+1

if __name__=='__main__':
    val=Value('d',0.0)
    arr=Array('i',range(10))

    p=Process(target=share,args=(val,arr))
    p.start()
    p.join()

    print(val.value)
    print(arr[:])

输出值为:

`1.0
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

`

其中d和i分别代表创建Value和Array中存储的数字类型为double和signed integer。这些共享对象都是线程和进程安全的。

服务器进程

通过Manager()创建一个管理类,它可以控制一个服务器进程,这些服务器进程持有Python对象,并且允许其他进程利用代理来操纵Python对象。

from multiprocessing import Process, Manager
def func(dic,li):
    dic['hello']=1
    dic[1]='Bob'
    dic[2.01]=None
    li.reverse()

if __name__=='__main__':

    manager=Manager() 
    dic=manager.dict()
    li=manager.list(range(5))

    p=Process(target=func,args=(dic,li))
    p.start()
    p.join()
    print(dic)
    print(li)

输出结果为:

{'hello': 1, 1: 'Bob', 2.01: None}
[4, 3, 2, 1, 0]

服务器进程管理比使用共享内存对象更加的灵活,因为它可以支持任意类型的对象。manager也可以通过进程进行共享,只不过比使用共享内存慢。

进程池

进程池中有许多进程,它有方法让进程池中的进程以不同的方式运行任务。 可以创建一个池池,这些进程将执行池类向它提交的任务。
多进程编程并不是进程越多越好,还与CPU核数有关,进程数过多反而会降低效率。

Pool([processes[, initializer[, initargs[, maxtasksperchild]]]])

相关方法

apply(func[, args[, kwds]]):在一个池工作进程中执行func(*args,**kwargs),然后返回结果。需要强调的是:此操作并不会在所有池工作进程中并执行func函数。如果要通过不同参数并发地执行func函数,必须从不同线程调用p.apply()函数或者使用
p.apply_async()

apply_async(func [, args [, kwargs]]):在一个池工作进程中执func(*args,**kwargs),然后返回结果。此方法的结果是AsyncResult类的实例,callback是可调用对象,接收输入参数。当func的结果变为可用时,将理解传递给callback。callback禁止执行任何阻塞操作,否则将接收其他异步操作中的结果。

close():关闭进程池。如果所有操作持续挂起,它们将在工作进程终止前完成。

P.join():等待所有工作进程退出。此方法只能在close()或teminate()之后调用

from multiprocessing import Pool

def sqr(x):
    return x*x

if __name__=='__main__':
    pool=Pool(processes=5) #开启5个工作进程
    result=pool.apply_async(sqr,[10]) #异步计算sqr(10))
    print(result.get(timeout=1)) #输出100
    print(pool.map(sqr,range(5))) #输出[0,1,4.....16]

参考

https://www.cnblogs.com/smallmars/p/7093603.html
http://docspy3zh.readthedocs.io/en/latest/library/multiprocessing.html

python 系列之 - 多进程

多进程 (multiprocessing) 1 创建一个多进程 创建: multiprocessing.Process([target=函数名], [ name = 别名], [args=(参数...
  • songfreeman
  • songfreeman
  • 2016-03-08 15:54:41
  • 2765

python进阶——多进程

1
  • scorpion_zs
  • scorpion_zs
  • 2016-11-18 16:39:09
  • 1491

python多进程并发编程

Python提供了非常好用的多进程包multiprocessing,你只需要定义一个函数,Python会替你完成其他所有事情。 借助这个包,可以轻松完成从单进程到并发执行的转换。 一、单进...
  • fireroll
  • fireroll
  • 2015-06-16 10:32:47
  • 2682

python爬虫——多进程multiprocessing

其实多进程相对来说不是特别适合用来做爬虫,因为多进程比较适用于计算密集型,而爬虫是IO密集型,因此多进程爬虫对速度的提升不是特别明显,但是将爬虫改为多进程比较简单,只需简单的几行代码即可搞定,所以在修...
  • qq_23926575
  • qq_23926575
  • 2017-07-30 10:57:59
  • 1266

python实现多进程

在这里用Python程序来实现多进程并加深对多进程并发的理解
  • u014556057
  • u014556057
  • 2017-03-12 14:02:48
  • 8494

51.[Python]使用multiprocessing进行多进程编程

介绍多进程的基础知识,及使用multiprocessing进行多进程编程的方法,给出了代码示例及github项目地址。...
  • a464057216
  • a464057216
  • 2016-10-04 21:41:07
  • 4123

python爬虫学习多进程下载图片

import requests import urllib.request from bs4 import BeautifulSoup import os,re import datetime f...
  • lxslx
  • lxslx
  • 2017-07-14 13:33:25
  • 784

python 多进程实现文件下载传输

需求: 实现文件夹拷贝功能(包括文件内的文件),并打印拷贝进度模块: 利用 os模块 multiprocessing 模块import multiprocessing import os def...
  • wf134
  • wf134
  • 2017-11-15 23:17:47
  • 283

python中的多进程处理

  众所周知,python本身是单线程的,python中的线程处理是由python解释器分配时间片的;但在python 3.0中吸收了开源模块,开始支持系统原生的进程处理——multiprocessi...
  • jj_liuxin
  • jj_liuxin
  • 2008-12-20 15:31:00
  • 32560

Python中多进程在爬虫中的使用

如何利用多进程的方法来提高Python爬虫的速度和效率。介绍了multiprocessing库的使用,并且用验证爬到的代理IP可用性作为例子来讲述多进程方法的具体使用。...
  • sinat_22594309
  • sinat_22594309
  • 2016-12-18 13:53:17
  • 4168
收藏助手
不良信息举报
您举报文章:Python多进程
举报原因:
原因补充:

(最多只允许输入30个字)