前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >浅谈 python multiprocessing(多进程)下如何共享变量

浅谈 python multiprocessing(多进程)下如何共享变量

作者头像
用户1177713
发布于 2018-02-24 08:28:18
发布于 2018-02-24 08:28:18
3.8K00
代码可运行
举报
文章被收录于专栏:数据之美数据之美
运行总次数:0
代码可运行

1、问题:

群中有同学贴了如下一段代码,问为何 list 最后打印的是空值?

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
from multiprocessing import Process, Manager
import os

manager = Manager()
vip_list = []
#vip_list = manager.list()

def testFunc(cc):
    vip_list.append(cc)
    print 'process id:', os.getpid()

if __name__ == '__main__':
    threads = []

    for ll in range(10):
        t = Process(target=testFunc, args=(ll,))
        t.daemon = True
        threads.append(t)

    for i in range(len(threads)):
        threads[i].start()

    for j in range(len(threads)):
        threads[j].join()

    print "------------------------"
    print 'process id:', os.getpid()
    print vip_list

其实如果你了解 python 的多线程模型,GIL 问题,然后了解多线程、多进程原理,上述问题不难回答,不过如果你不知道也没关系,跑一下上面的代码你就知道是什么问题了。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
python aa.py
process id: 632
process id: 635
process id: 637
process id: 633
process id: 636
process id: 634
process id: 639
process id: 638
process id: 641
process id: 640
------------------------
process id: 619
[]

将第 6 行注释开启,你会看到如下结果:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
process id: 32074
process id: 32073
process id: 32072
process id: 32078
process id: 32076
process id: 32071
process id: 32077
process id: 32079
process id: 32075
process id: 32080
------------------------
process id: 32066
[3, 2, 1, 7, 5, 0, 6, 8, 4, 9]

2、python 多进程共享变量的几种方式:

(1)Shared memory:

Data can be stored in a shared memory map using Value or Array. For example, the following code

http://docs.python.org/2/library/multiprocessing.html#sharing-state-between-processes

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
from multiprocessing import Process, Value, Array

def f(n, a):
    n.value = 3.1415927
    for i in range(len(a)):
        a[i] = -a[i]

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

    p = Process(target=f, args=(num, arr))
    p.start()
    p.join()

    print num.value
    print arr[:]

结果:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
3.1415927
[0, -1, -2, -3, -4, -5, -6, -7, -8, -9]
(2)Server process:

A manager object returned by Manager() controls a server process which holds Python objects and allows other processes to manipulate them using proxies. A manager returned by Manager() will support types list, dict, Namespace, Lock, RLock, Semaphore, BoundedSemaphore, Condition, Event, Queue, Value and Array. 代码见开头的例子。

http://docs.python.org/2/library/multiprocessing.html#managers

3、多进程的问题远不止这么多:数据的同步

看段简单的代码:一个简单的计数器:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
from multiprocessing import Process, Manager
import os

manager = Manager()
sum = manager.Value('tmp', 0)

def testFunc(cc):
    sum.value += cc

if __name__ == '__main__':
    threads = []

    for ll in range(100):
        t = Process(target=testFunc, args=(1,))
        t.daemon = True
        threads.append(t)

    for i in range(len(threads)):
        threads[i].start()

    for j in range(len(threads)):
        threads[j].join()

    print "------------------------"
    print 'process id:', os.getpid()
    print sum.value

结果:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
------------------------
process id: 17378
97

也许你会问:WTF?其实这个问题在多线程时代就存在了,只是在多进程时代又杯具重演了而已:Lock!

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
from multiprocessing import Process, Manager, Lock
import os

lock = Lock()
manager = Manager()
sum = manager.Value('tmp', 0)


def testFunc(cc, lock):
    with lock:
        sum.value += cc


if __name__ == '__main__':
    threads = []

    for ll in range(100):
        t = Process(target=testFunc, args=(1, lock))
        t.daemon = True
        threads.append(t)

    for i in range(len(threads)):
        threads[i].start()

    for j in range(len(threads)):
        threads[j].join()

    print "------------------------"
    print 'process id:', os.getpid()
    print sum.value

这段代码性能如何呢?跑跑看,或者加大循环次数试一下。。。

再来看个多进程共享变量的例子:该脚本可以在集群中批量执行任意命令并返回结果。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#!/usr/bin/env python
# coding=utf-8
import sys

reload(sys)
sys.setdefaultencoding('utf-8')

import rpyc
from pyUtil import *
from multiprocessing import Pool as ProcessPool
from multiprocessing import Manager

hostDict = {
    '192.168.1.10': 11111
}

manager = Manager()
localResultDict = manager.dict()


def rpc_client(host_port_cmd):
    host = host_port_cmd[0]
    port = host_port_cmd[1]
    cmd = host_port_cmd[2]
    c = rpyc.connect(host, port)
    result = c.root.exposed_execCmd(cmd)
    localResultDict[host] = result
    c.close()


def exec_cmd(cmd_str):
    host_port_list = []
    for (host, port) in hostDict.items():
        host_port_list.append((host, port, cmd_str))

    pool = ProcessPool(len(hostDict))
    results = pool.map(rpc_client, host_port_list)
    pool.close()
    pool.join()
    for ip in localResultDict.keys():
        print ip + ":\t" + localResultDict[ip]

if __name__ == "__main__":

    if len(sys.argv) == 2 and sys.argv[1] != "-h":
        print "======================"
        print "    Your command is:\t" + sys.argv[1]
        print "======================"
        cmd_str = sys.argv[1]
    else:
        print "Cmd Error!"
        sys.exit(1)

    exec_cmd(cmd_str)

需要注意的是 manager.dict() 在遍历时一定要使用 .keys() 方法,否则会抛异常:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Traceback (most recent call last):
  File "test.py", line 83, in <module>
    exec_cmd(cmd_str)
  File "test.py", line 57, in exec_cmd
    for ip in localResultDict:
  File "<string>", line 2, in __getitem__
  File "/opt/soft/python-2.7.10/lib/python2.7/multiprocessing/managers.py", line 774, in _callmethod
    raise convert_to_error(kind, result)
KeyError: 0

4、最后的建议:

Note that usually sharing data between processes may not be the best choice, because of all the synchronization issues; an approach involving actors exchanging messages is usually seen as a better choice. See also Python documentation: As mentioned above, when doing concurrent programming it is usually best to avoid using shared state as far as possible. This is particularly true when using multiple processes. However, if you really do need to use some shared data then multiprocessing provides a couple of ways of doing so.

5、Refer:

[0] 理解Python并发编程一篇就够了 - 线程篇

http://www.dongwm.com/archives/%E4%BD%BF%E7%94%A8Python%E8%BF%9B%E8%A1%8C%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8B-%E7%BA%BF%E7%A8%8B%E7%AF%87/

[1] multiprocessing — Process-based “threading” interface

https://docs.python.org/2/library/multiprocessing.html

[2] Manager()出错,不知道为什么

http://m.newsmth.net/article/Python/100915

[3] Can't iterate over multiprocessing.managers.DictProxy

http://bugs.python.org/issue9733

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
在python中使用多进程multiprocessing
在日常开发中,我们经常遇到一些需要循环批处理的数据,如果处理完一个批次数据后再处理下一批次,这样对服务器是一种浪费,同时也让程序运行时间大大加长,那么如何在python中使用多进程呢?
zhangheng
2020/04/28
9600
Python 进阶(二):多进程
进程:通常一个运行着的应用程序就是一个进程,比如:我启动了一个音乐播放器,现在它就是一个进程。线程:线程是进程的最小执行单元,比如:我在刚启动的音乐播放器上选了一首歌曲进行播放,这就是一个线程。
Python小二
2020/08/18
4150
Python标准库10 多进程初步 (multiprocessing包)
我们已经见过了使用subprocess包来创建子进程,但这个包有两个很大的局限性:1) 我们总是让subprocess运行外部的程序,而不是运行一个Python脚本内部编写的函数。2) 进程间只通过管道进行文本交流。以上限制了我们将subprocess包应用到更广泛的多进程任务。(这样的比较实际是不公平的,因为subprocessing本身就是设计成为一个shell,而不是一个多进程管理包) threading和multiprocessing (请尽量先阅读Python多线程与同步) multiproce
Vamei
2018/01/18
8490
多进程并行计算
我有了一个 Python 脚本,我想用它作为另一个 Python 脚本的控制器。我的服务器有 64 个处理器,所以我想要同时启动最多 64 个此第二个 Python 脚本的子进程。子脚本称为:
用户11021319
2024/04/02
1500
多进程并行计算
Python | Python学习之多进程详解
我们经常迷惑于多进程和多线程,长的好像一样,但是他们有本质上的区别,很多大佬也对进程和线程的概念做了很多通俗易懂的解释,这里我们引用阮一峰老师的博文,大家可以先去看看,理清楚线程和进程的区别。
咸鱼学Python
2019/10/09
1.1K0
Python 编程 | 连载 25 - Python 多进程
对于操作系统来说,一个任务就是一个进程,进程就是程序执行的载体,如Python脚本中执行main函数就启动了一个进程,打开微信或者浏览器就是开启了一个进程,进程的运行需要资源支持,也就需要消耗CPU和内存
RiemannHypothesis
2022/09/26
3710
Python 编程 | 连载 25 - Python 多进程
python进程vs线程
线程切换是有代价的,多任务一旦多到一个限度,就会消耗掉系统所有的资源,结果效率急剧下降,所有任务都做不好
测试加
2022/04/27
4000
Python 3 多进程
进程指的是正在进行的一个过程或者一个任务,而执行这个任务的是CPU。进程与程序的区别,可以理解为程序是我们写的一堆代码,而进程则是CPU执行这堆代码的过程,同一个程序被执行两次,就会产生两个进程。凡是硬件,都需要有操作系统进行管理,只要是操作系统,就会有进程概念,需要有创建进程的方式。进程的三种状态:
用户6184845
2019/10/16
1K0
Python 3 多进程
Python多进程、多线程、协程
在Unix/Linux中系统内核提供了fork系统调用来创建进程,根据不同的返回值来判断当前进程是子进程还是父进程,C语言代码示例如下:
chain
2018/06/05
2.6K14
Python学习记录-多进程和多线程
狭义定义:进程是正在运行的程序的实例(an instance of a computer program that is being executed)。 广义定义:进程是一个具有一定独立功能的程序关于某个数据集合的一次运行活动。它是操作系统动态执行的基本单元,在传统的操作系统中,进程既是基本的分配单元,也是基本的执行单元。
py3study
2020/01/07
7890
python︱Python进程、线程、协程详解、运行性能、效率(tqdm)
笔者最近在实践多进程发现multiprocessing,真心很好用,不仅加速了运算,同时可以GPU调用,而且互相之间无关联,这样可以很放心的进行计算。
悟乙己
2019/05/26
1.4K0
Python学习(十)---- python中的进程与协程
原文地址: https://blog.csdn.net/fgf00/article/details/52790360 编辑:智能算法,欢迎关注! 上期我们一起学习了python中的线程的相关知识
智能算法
2018/10/08
5160
Python使用multiprocessing实现多进程
程序:程序是一个静态的概念。在一台电脑上,我们安装了很多程序,这些程序是可以运行的。比如我们编写一个xxx.py程序,它是静态的,静静的保存在电脑的硬盘中,等待执行。
Python碎片公众号
2021/02/26
7880
Python使用multiprocessing实现多进程
Python 多进程
上面的代码开启了5个子进程去执行函数,我们可以观察结果,是同时打印的,这里实现了真正的并行操作,就是多个CPU同时执行任务。我们知道进程是python中最小的资源分配单元,也就是进程中间的数据,内存是不共享的,每启动一个进程,都要独立分配资源和拷贝访问的数据,所以进程的启动和销毁的代价是比较大了,所以在实际中使用多进程,要根据服务器的配置来设定。
为为为什么
2022/08/05
3840
Python 多进程开发与多线程开发
进程提供了多道编程,充分发挥了计算机部件的并行性,提高了计算机的利用率,既然进程这么优秀,为什么还要线程呢? 其实,还是有很多缺陷的,主要体现在两点上:
py3study
2020/01/06
5830
【干货】python多进程和多线程谁更快
而python里面的多线程显然得拿到GIL,执行code,最后释放GIL。所以由于GIL,多线程的时候拿不到,实际上,它是并发实现,即多个事件,在同一时间间隔内发生。
未名编程
2024/10/12
900
【干货】python多进程和多线程谁更快
2018年8月25日多进程编程总结
今天遇到的新单词: terminal    n终端 terminate  v结束,使终结 basic        adj基本的
武军超
2018/09/27
6080
python网络-多进程(21)
进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。在早期面向进程设计的计算机结构中,进程是程序的基本执行实体;在当代面向线程设计的计算机结构中,进程是线程的容器。程序是指令、数据及其组织形式的描述,进程是程序的实体。---来自百度百科
Se7eN_HOU
2019/09/11
5160
python网络-多进程(21)
浅谈 multiprocessing
一前言 使用python进行并发处理多台机器/多个实例的时候,我们可以使用threading ,但是由于著名的GIL存在,实际上threading 并未提供真正有效的并发处理,要充分利用到多核CPU,我们需要使用多进程。Python提供了非常好用的多进程包--multiprocessing。multiprocessing 可以利用multiprocessing.Process对象来创建一个进程,该Process对象与Threading对象的用法基本相同,具有相同的方法(官方原话:"The multiprocessing package mostly replicates the API of the threading module.") 比如:start(),run(),join()的方法。multiprocessing包中也有Lock/Event/Semaphore/Condition/Pipe/Queue类用于进程之间的通信。话不多说 show me the code! 二使用 2.1 初识异同
用户1278550
2018/08/08
4330
Python多进程原理与实现
进程就是一个程序在一个数据集上的一次动态执行过程。进程一般由程序、数据集、进程控制块三部分组成。我们编
软件架构师Michael
2022/03/10
4970
相关推荐
在python中使用多进程multiprocessing
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档