本篇文章给大家带来的内容是关于python中进程间数据通讯模块multiprocessing.Manager的介绍,有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。

目前开发中有遇到进程间需要共享数据的情况. 所以研究了下multiprocessing.Manager, 主要会以dict为例子, 说明下进程间共享(同一个父进程).

dict使用说明import multiprocessing

# 1. 创建一个Manger对象

manager = multiprocessing.Manager()

# 2. 创建一个dict

temp_dict = manager.dict()

# 3. 创建一个测试程序

def test(idx, test_dict):

test_dict[idx] = idx

# 4. 创建进程池进行测试

pool = multiprocessing.Pool(4)

for i in range(100):

pool.apply_async(test, args=(i, temp_dict))

pool.close()

pool.join()

print(temp_dict)

too simple.

简单的源码分析

这时我们再看一个例子import multiprocessing

# 1. 创建一个Manger对象

manager = multiprocessing.Manager()

# 2. 创建一个dict

temp_dict = manager.dict()

temp_dict['test'] = {}

# 3. 创建一个测试程序

def test(idx, test_dict):

test_dict['test'][idx] = idx

# 4. 创建进程池进行测试

pool = multiprocessing.Pool(4)

for i in range(100):

pool.apply_async(test, args=(i, temp_dict))

pool.close()

pool.join()

print(temp_dict)

可以看到输出结果是奇怪的{'test': {}}

如果我们简单修改一下代码import multiprocessing

# 1. 创建一个Manger对象

manager = multiprocessing.Manager()

# 2. 创建一个dict

temp_dict = manager.dict()

temp_dict['test'] = {}

# 3. 创建一个测试程序

def test(idx, test_dict):

row = test_dict['test']

row[idx] = idx

test_dict['test'] = row

# 4. 创建进程池进行测试

pool = multiprocessing.Pool(4)

for i in range(100):

pool.apply_async(test, args=(i, temp_dict))

pool.close()

pool.join()

print(temp_dict)

这时输出结果就符合预期了.

为了了解这个现象背后的原因, 我简单去读了一下源码, 主要有以下几段代码很关键.def Manager():

'''

Returns a manager associated with a running server process

The managers methods such as `Lock()`, `Condition()` and `Queue()`

can be used to create shared objects.

'''

from multiprocessing.managers import SyncManager

m = SyncManager()

m.start()

return m

...

def start(self, initializer=None, initargs=()):

'''

Spawn a server process for this manager object

'''

assert self._state.value == State.INITIAL

if initializer is not None and not hasattr(initializer, '__call__'):

raise TypeError('initializer must be a callable')

# pipe over which we will retrieve address of server

reader, writer = connection.Pipe(duplex=False)

# spawn process which runs a server

self._process = Process(

target=type(self)._run_server,

args=(self._registry, self._address, self._authkey,

self._serializer, writer, initializer, initargs),

)

ident = ':'.join(str(i) for i in self._process._identity)

self._process.name = type(self).__name__ + '-' + ident

self._process.start()

...

上面代码可以看出, 当我们声明了一个Manager对象的时候, 程序实际在其他进程启动了一个server服务, 这个server是阻塞的, 以此来实现进程间数据安全.

我的理解就是不同进程之间操作都是互斥的, 一个进程向server请求到这部分数据, 再把这部分数据修改, 返回给server, 之后server再去处理其他进程的请求.

回到上面的奇怪现象上, 这个操作test_dict['test'][idx] = idx实际上在拉取到server上的数据后进行了修改, 但并没有返回给server, 所以temp_dict的数据根本没有变化. 在第二段正常代码, 就相当于先向服务器请求数据, 再向服务器传送修改后的数据. 这样就可以解释这个现象了.

进程间数据安全

这个时候如果出现一种情况, 两个进程同时请求了一份相同的数据, 分别进行修改, 再提交到server上会怎么样呢? 那当然是数据产生异常. 基于此, 我们需要Manager的另一个对象, Lock(). 这个对象也不难理解, Manager本身就是一个server, dict跟lock都来自于这个server, 所以当你lock住的时候, 其他进程是不能取到数据, 自然也不会出现上面那种异常情况.

代码示例:import multiprocessing

# 1. 创建一个Manger对象

manager = multiprocessing.Manager()

# 2. 创建一个dict

temp_dict = manager.dict()

lock = manager.Lock()

temp_dict['test'] = {}

# 3. 创建一个测试程序

def test(idx, test_dict, lock):

lock.acquire()

row = test_dict['test']

row[idx] = idx

test_dict['test'] = row

lock.release()

# 4. 创建进程池进行测试

pool = multiprocessing.Pool(4)

for i in range(100):

pool.apply_async(test, args=(i, temp_dict, lock))

pool.close()

pool.join()

print(temp_dict)

切忌不要进程里自己新建lock对象, 要使用统一的lock对象.

本篇文章到这里就已经全部结束了,更多其他精彩内容可以关注PHP中文网的python视频教程栏目!

python多进程通信manager_python中进程间数据通讯模块multiprocessing.Manager的介绍相关推荐

  1. python 多进程共享变量manager_python 进程间共享数据 multiprocessing 通信问题 — Manager...

    Python中进程间共享数据,处理基本的queue,pipe和value+array外,还提供了更高层次的封装.使用multiprocessing.Manager可以简单地使用这些高级接口. Mana ...

  2. python进程间通信时间开销_python 进程间的通信

    python3,进程间的通信 本文来源于python 3.5版本的官方文档 multiprocessing模块为进程间通信提供了两种方法: 1.进程队列queue The Queue class is ...

  3. VC++中进程间相互通信的十一种方法

    进程通常被定义为一个正在运行的程序的实例,它由两个部分组成: 一个是 操作系统用来管理进程的内核对象.内核对象也是系统用来存放关于进程的统计信息的地方 另一个是地址空间,它包含所有的可执行模块或DLL ...

  4. 进程间数据传递:Queue,Pipe 进程间数据共享:Manager

    进程间数据传递:Queue,Pipe 进程间数据共享:Manager 1.使用multiprocessing模块的Queue实现数据传递 ''' 进程间通讯:Queue,用法跟线程里的Queue一样, ...

  5. Android中进程间通讯 AIDL

    Android中进程间通讯 AIDL IDL Interface Description Language  接口描述语言 AIDL Android IDL 适用场景:    client进程必须是A ...

  6. 【Python数据分析】利用Python替换EXCEL表格中指定的数据

    如何利用Python替换EXCEL表格中指定的数据?今天与大家一起分享一下DataFrame对象的replace()函数,replace()函数可EXCEl中的数据内容,其语法格式如下: 表达式.re ...

  7. python多进程线程学习_python进程、线程的学习心得

    什么是多线程竞争? 线程不是独立的,同一个进程里的线程,线程间的数据是共享的,多线程操作时,容易造成数据的混乱,线程不安全. 如何解决? 互斥锁. 好处:能够保证某段关键代码执行时,只有一个线程操作, ...

  8. python 进程间通信效率_(1)进程间几种通信方式

    管道.消息队列.共享内存.信号量.信号.socket 要知道管道.消息队列.共享内存的本质:内存本质.效率以及传输数据要求,各种使用方式 一.管道 管道通信效率低,不适合进程间频繁地交换数据.好处,简 ...

  9. Python多进程(一)进程及进程池

    进程 进程是操作系统分配资源的基本单元,是程序隔离的边界. 进程和程序 程序只是一组指令的集合,它本身没有任何运行的含义,它是静态的. 进程程序的执行实例,是动态的,有自己的生命周期,有创建有撤销,存 ...

最新文章

  1. shell 编程整合
  2. 解决beautifulsoup代码无效问题
  3. apt的通讯信道是如何发现的?
  4. python中lxml模块的使用
  5. java跨平台的特性_【简答题】什么是跨平台特性?Java怎样实现跨平台特性?
  6. json和字符串/数组/集合的互相转换の神操作总结
  7. matlab安装第三方库,Matlab调用cpp+第三方库
  8. 2020年数据库系统工程师上午真题及答案解析
  9. 第16课 火眼金睛——人脸识别
  10. 《代码大全2》第6章 可以工作的类
  11. 一文了解常用效率记笔记软件(超过20款含有图片和双向链笔记)
  12. PAT题集2019.6.22排名变动
  13. 如何让cmd一直默认以管理员身份打开
  14. 中国超级稻在18个亚非国家试种推广 国稻种芯百团计划行动
  15. 服务器开发系列(四)——网络基础
  16. java获取和风天气_和风天气(一)数据分析
  17. 关于USART波特率、TIM的外设预分频值
  18. php和web前端工作描述,web前端岗位自我评价怎么写
  19. adreno源码系列(五)打开kgsl
  20. 剑侠情缘修改服务器列表名字,剑侠情缘家族个性后缀怎么改好听

热门文章

  1. 2017.9.14 仪仗队 思考记录
  2. 2017.4.21 2^k进制数 思考记录
  3. mysql删除中继日志_mysql 中继日志删除可以自动获取吗
  4. Intel 64/x86_64/IA-32/x86处理器 - SIMD指令集 - MMX技术(2) - 数据转换指令
  5. 典型相关分析_微生物多样研究—微生物深度分析概述
  6. CreateThread、_beginthread与AfxBeginThread的区别及其注意事项
  7. GPU并行计算OpenCL(3)——图像处理
  8. php生成标准excel表格,php导出生成excel表格几种方法介绍
  9. 为虚幻引擎4设置Visual Studio
  10. java几种集合遍历速度对比