python threading multiprocess_Python 多进程multiprocess

Python 多进程multiprocess

阅读 (184) |

发布于 2020-05-19 14:47:26

Python中的multiprocess提供了Process类,实现进程相关的功能。但是它基于fork机制,因此不被windows平台支持。

在multiprocess模块中有 process 和 Process 两个类,大家使用过程中一点要注意区别二者。

multiprocess.Process 类用法:

通过以下示例,可以发现多进程语法上和多线程几乎是一样的。#!/usr/bin/env python

#coding=utf-8

import os

import multiprocessing

def foo(i):

# 当前进程名

print("Current pname:", multiprocessing.current_process().name)

#当前进程的父进程id

print("parents pid:", os.getppid())

#当前进程id

print("Current pid:", os.getpid())

if __name__ == '__main__':

for i in range(3):

p = multiprocessing.Process(target=foo, args=(i,))

p.start()

进程间共享数据

在linux中, 每个进程都是由父进程的。最大的用户进程为1号进程。子进程的数据都是由父进程提供的,每启动一个子进程就从父进程克隆一份数据。

进程的创建需要很大的开销,每个进程都有独立的内存空间。进程之间通常是不能直接共享数据。

进程如果需要数据共享,就要通过中间件来实现。

下面的代码试图用全局列表来实现 进程的数据共享:#!/usr/bin/env python

#coding=utf-8

import multiprocessing

import os

lis = []

def foo(i):

lis.append(i)

print("Pid: %d addr: %s, lis: %s" % (os.getpid(), id(lis), lis))

if __name__ == '__main__':

for i in range(3):

p = multiprocessing.Process(target=foo, args=(i,))

p.start()

print("The End. Pid:%s, addr: %s lis:%s"%(os.getpid(), id(lis), lis))

得到如下结果, 每个进程的lis都是独立的,全局列表并没有改变。Pid: 8974 addr: 20094344, lis: [0]

Pid: 8975 addr: 20094344, lis: [1]

The End. Pid:8973, addr: 20094344 lis:[]

Pid: 8976 addr: 20094344, lis: [2]

multiprocess模块提供了三个类来实现进程之间的数据共享Queues

Array

Manager

Queues类

Queues类的导入方式是 from multiprocessing.queues import Queue。它在multiprocessing包的queues模块中。#!/usr/bin/env python

#coding=utf-8

import os

import multiprocessing

from multiprocessing.queues import Queue

from multiprocessing import Process

def func(i, q):

print("Pid: %s get: %s then put:%s" % (os.getpid(),q.get(), i))

q.put(i)

if __name__ == "__main__":

lis = Queue(1, ctx=multiprocessing)

lis.put(10)

for i in range(5):

p = Process(target=func, args=(i, lis))

p.start()

multiprocessing自己还有一个Queue类,一样能实现queues.Queue的功能,导入方式是from multiprocessing import Queue。

Array类

Array数组类,语法:

arr = Array('i', 5)

'i' 表示内部元素为int类型 ,5表示数组的长度。更多类型 :'c': ctypes.c_char, 'u': ctypes.c_wchar,

'b': ctypes.c_byte, 'B': ctypes.c_ubyte,

'h': ctypes.c_short, 'H': ctypes.c_ushort,

'i': ctypes.c_int, 'I': ctypes.c_uint,

'l': ctypes.c_long, 'L': ctypes.c_ulong,

'f': ctypes.c_float, 'd': ctypes.c_double

示例:#!/usr/bin/env python

import os

from multiprocessing import Process

from multiprocessing import Array

def func(i,temp):

temp[0] += 100

print("Pid:",os.getpid(),"array:", temp[0])

if __name__ == '__main__':

temp = Array('i', [1, 2, 3, 4])

for i in range(5):

p = Process(target=func, args=(i, temp))

p.start()

Manager类

Manager实例化返回一个服务进程,其他进程可以通过代理的方式操作Manager对象。

Manager 支持list, dict, Namespace, Lock, RLock, Semaphore, BoundedSemaphore, Condition, Event, Barrier, Queue, Value ,Array等多种格式。#!/usr/bin/env python

import os

import time

import threading

from multiprocessing import Process

from multiprocessing import Manager

def func(i, dic):

dic["num" + str(i)] = 100+i

print("Pid:", os.getpid(), dic.items())

time.sleep(3)

if __name__ == '__main__':

dic = Manager().dict()

process_lis = []

for i in range(5):

p = Process(target=func, args=(i, dic))

p.start()

process_lis.append(p)

for p in process_lis:

p.join()

注意: 这里在启动子进程时用了join(), 这是必须的。这个join和线程的作用是一样的。是要父进程等所有子进程结束后再结束。

如果没有join()父进程执行完释放了内存。dic也就不存在。其他用到dic的子进程就会报错。

进程锁

与线程锁一样,进程中也有同名的锁,并且用法和作用都是一样的。

在multiprocessing 有锁类: RLock可重入锁, Lock互斥锁,Event事件锁, Condition条件锁,Semaphore信号锁。

这里不多做解释了, 用一个简单的例子来看一下进程锁的使用。#!/usr/bin/env python

import os

import time

from multiprocessing import Array

from multiprocessing import Process

from multiprocessing import RLock, Lock, Event, Condition, Semaphore

def func(i,lis,lc):

lc.acquire()

if i%2 ==0:

lis[0] = lis[0] - 1

else:

lis[0] = lis[0] + 1

lc.release()

if __name__ == "__main__":

array = Array('i', 1)

array[0] = 10

lock = RLock()

process_lis = []

for i in range(1000):

p = Process(target=func, args=(i, array, lock))

p.start()

process_lis.append(p)

for i in process_lis:

p.join()

print(array[0])

以上例子中,枷锁后结果为10, 不加锁 结果不定。

Pool类(进程池类)

创建进程开销较大,频繁的创建销毁进程会消耗大量的内存空间。同线程一样,进程也可以使用进程池来控制开销。

python 给我们内置了一个进程池,导入:from multiprocessing import Pool

Pool类里面的常用方法:apply() 同步执行 (串行)

apply_async() 异步执行 (并行)

terminate() 立刻关闭进程池(强制)

join() 主进程等待进程池内所有进程执行完毕。 (必须在close或terminate之后使用)

close() 等待所有进程池结束后,关闭进程池。

以下示例是异步执行的方式,并行线程数5#!/usr/bin/env python

from multiprocessing import Pool

import time

def func(args):

time.sleep(1)

print("running", args)

if __name__ == '__main__':

p = Pool(5)

for i in range(30):

p.apply_async(func=func, args=(i,))

p.close()

# p.terminate()

p.join()

print("end")

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值