python中进程间数据通讯模块multiprocessing.Manager的介绍

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

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

dict使用说明

import multiprocessing# 1. 创建一个Manger对象manager = multiprocessing.Manager()# 2. 创建一个dicttemp_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.

简单的源码分析

这时我们再看一个例子

立即学习“Python免费学习笔记(深入)”;

import multiprocessing# 1. 创建一个Manger对象manager = multiprocessing.Manager()# 2. 创建一个dicttemp_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. 创建一个dicttemp_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. 创建一个dicttemp_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中进程间数据通讯模块multiprocessing.Manager的介绍的详细内容,更多请关注【创想鸟】其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至253000106@qq.com举报,一经查实,本站将立刻删除。

发布者:PHP中文网,转转请注明出处:https://www.chuangxiangniao.com/p/2533555.html

(0)
上一篇 2025年3月5日 21:16:27
下一篇 2025年2月23日 05:36:59

AD推荐 黄金广告位招租... 更多推荐

相关推荐

  • 怎么找到黑客的联系方式?

    如果你想要找到黑客的联系方式,那么你可能面临以下难题:黑客往往会隐藏他们的身份,并且他们的联系方式很难被发现。php小编草莓在这里为你提供了一份指南,旨在帮助你找到黑客的联系方式。在本指南中,我们将介绍一些常见的黑客使用的联系方式,并提供一…

    2025年3月5日
    200
  • Python中eval() 与exec() 函数的用法解析

    本篇文章给大家带来的内容是关于Python中eval() 与exec() 函数的用法解析,有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。 Python 提供了很多内置的工具函数(Built-in Functions),在最新…

    编程技术 2025年3月5日
    200
  • Python动态赋值的陷阱分析

    本篇文章给大家带来的内容是关于Python动态赋值的陷阱分析,有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。 命名空间与作用域问题,看似微不足道,其实背后大有文章。 由于篇幅所限,还有一个重要的知识内容没谈,即“locals…

    编程技术 2025年3月5日
    200
  • Python eval的常见错误封装及利用原理的介绍

    本篇文章给大家带来的内容是关于python eval的常见错误封装及利用原理的介绍,有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。 最近在代码评审的过程,发现挺多错误使用eval导致代码注入的问题,比较典型的就是把eval当…

    编程技术 2025年3月5日
    200
  • python中eval的用法详解及潜在风险介绍

    本篇文章给大家带来的内容是关于python中eval的用法详解及潜在风险介绍,有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。 eval前言 In [1]: eval(“2+3”)Out[1]: 5In [2]: eval(‘…

    编程技术 2025年3月5日
    200
  • Python实现DES加密解密的方法介绍(代码)

    本篇文章给大家带来的内容是关于python实现des加密解密的方法介绍(代码),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。 DES(Data Encryption Standard)采用64位的分组长度和56位的密钥长度…

    编程技术 2025年3月5日
    200
  • Python字符串的格式化的详细介绍

    本篇文章给大家带来的内容是关于Python字符串的格式化的详细介绍,有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。 相信很多人在格式化字符串的时候都用”%s” % v的语法,PEP 3101 提出一种…

    编程技术 2025年3月5日
    200
  • 如何在Python中打印单个和多个变量?

    请考虑下面python 2.x中的两个python代码片段。 # Code 1 print 1# Output: 1 登录后复制 # Code 2 print(1) # Output: 1 登录后复制 在Python 2.X中单个变量的情况…

    2025年3月5日
    200
  • python中subprocess模块级方法的介绍(附代码)

    本篇文章给大家带来的内容是关于python中subprocess模块级方法的介绍(附代码),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。 subprocess.run() 运行并等待args参数指定的指令完成,返回comp…

    编程技术 2025年3月5日
    200
  • 几款Python类型检查工具的分享

    本篇文章给大家带来的内容是关于几款Python类型检查工具的分享,有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。 近日,微软在 Github 上开源了一个 Python 静态类型检查工具:pyright ,引起了社区内的多方…

    2025年3月5日
    200

发表回复

登录后才能评论