『Python』多进程处理

尝试学习python的多进程模组,对比多线程,大概的区别在:

  1.多进程的处理速度更快

  2.多进程的各个子进程之间交换数据很不方便

多进程调用方式

  进程基本使用multicore()

  进程池优化进程的调用multicore_pool(),在使用进程池的时候,运许函数有return,而基本用法中进程是接收不了return的

  进程队列用法,大部分方法和python的基本队列是一致的,

q=mp.Queue() 声明
q.put() 添加
q.get() 释放
q.empty() 判断是不是空的

"""
Created on Tue Dec  5 09:00:00 2017

@author: hellcat
"""

import time
import numpy as np
import threading as td
import multiprocessing as mp

def job(q):
    for i in range(3):
        q.put(i)
    
def multicore():
    q=mp.Queue()
    ps = [mp.Process(target=job,args=(q,)),
         mp.Process(target=job,args=(q,))]  # 基本的子进程创建方法
    for p in ps:
        p.start()
        
    time.sleep(3)
    
    for p in ps:
        p.join()                            # 需要协调结束
        
    while True:
        if q.empty() != True:
            print(q.get())
        else:
            break

def multithread():  
    q=mp.Queue()
    ps = [td.Thread(target=job,args=(q,)),
         td.Thread(target=job,args=(q,))]  # 基本的子线程创建方法
    for p in ps:
        p.start()
        
    time.sleep(3)
    
    for p in ps:
        p.join()
        
    while True:
        if q.empty() != True:
            print(q.get())
        else:
            break

def job_pool(q):
    res0 = 0
    for i in range(np.random.randint(10)):
        res0 += i**3
    return res0

def multicore_pool():
    pool = mp.Pool(processes=2)                                  # 初始化进程池,可以指定进程数
    res1 = pool.map(job_pool,range(20))                          # map方法在线程池中同时添加多个线程
    print(res1)                              # 返回值为函数的return
    res2 = [pool.apply_async(job_pool,(i,)) for i in range(20)]  # 在进程池中单个添加进程
    print([res.get() for res in res2])                           # 注意此时每个进程的返回并不直接是return,需要get方法得到的才是return
    # for res in res2:
    #     print(res.get())
    
if __name__=='__main__':
    # multicore()
    # multithread()
    multicore_pool()

 进程共享变量 & 进程锁

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Tue Dec  5 10:15:58 2017

@author: hellcat
"""

import time
import multiprocessing as mp

def job(v,num,l):  # 需要把共享变量实例作为参数传入才行
    l.acquire()  # 进程锁锁住
    for _ in range(10):
        time.sleep(0.1)
        v.value += num # 获取共享变量的值,并进行操作
        print(v.value)
    l.release()  # 进程锁释放

def muticore():
    l = mp.Lock()  # 实例化进程锁
    v = mp.Value('i',0)  # 实例化共享变量
    # p = mp.Pool(processes=2)
    
    # p.map(job,((v,1,l),(v,3,l)))
    p1 = mp.Process(target=job,args=(v,1,l))
    p2 = mp.Process(target=job,args=(v,3,l))
    p1.start()
    p2.start()
    p1.join()
    p2.join()
    
if __name__=='__main__':
    muticore()

  不同于多线程使用全局变量就可以以共享变量,多进程必须使用 v = mp.Value('i',0)这样的语句声明变量(其实还可以是mp.Array('i',[1,2,3]),注意,这里只能是1维的list,[[1,2]]这样都是不可以的),并将v作为参数传给函数,在函数内部使用的时候也需要使用v.value来唤醒其值。

  进程锁会在锁住时阻止其他进程使用共享变量,所以可以看到输出中先执行了10次+1,然后执行了10次+3,而不使用进程锁+1和+3会无规律的交替进行:

注释掉进程锁:

1
4
5
8
9
12
13
16
17
20
21
24
25
28
29
32
33
36
37
40

使用进程锁(上面代码没有注释掉进程锁):

1
2
3
4
5
6
7
8
9
10
13
16
19
22
25
28
31
34
37
40

 

posted @ 2017-12-05 10:29  叠加态的猫  阅读(1358)  评论(0编辑  收藏  举报