Python多进程共享变量实现方法

news/2024/6/3 16:53:56 标签: python, windows, linux, 学习, pycharm, 开发语言

前言

大家早好、午好、晚好吖 ❤ ~欢迎光临本文章

话不多说,直接开搞,如果有什么疑惑/资料需要的可以点击文章末尾名片领取源码

一、错误的实现方式

最初以为是没添加global声明导致修改未生效,但实际操作发现global方式在多进程中也只能读不能写。

错误示例代码如下:

python">import multiprocessing

# 声明一个全局变量
share_var = ["start flag"]

def sub_process(process_name):
    # 企图像单个进程那样通过global声明使用全局变量
    global share_var
    share_var.append(process_name)
    # 但是很可惜,在多进程中这样引用只能读,修改其他进程不会同步改变
    for item in share_var:
        print(f"{process_name}-{item}")
    pass

def main_process():
    process_list = []
    # 创建进程1
    process_name = "process 1"
    tmp_process = multiprocessing.Process(target=sub_process,args=(process_name,))
    process_list.append(tmp_process)
    # 创建进程2
    process_name = "process 2"
    tmp_process = multiprocessing.Process(target=sub_process, args=(process_name,))
    process_list.append(tmp_process)
    # 启动所有进程
    for process in process_list:
        process.start()
    for process in process_list:
        process.join()

if __name__ == "__main__":
    main_process()

执行结果如下,可以看到进程1中的修改未表现在进程2中

(不过要注意,和多线程一样,如果运算量再大一点进程1并不一定比进程2先执行):

二、共享普通类型变量实现方法

python">'''
遇到问题没人解答?小编创建了一个Python学习交流QQ群:702813599
寻找有志同道合的小伙伴,互帮互助,群里还有不错的视频学习教程和PDF电子书!
'''
import multiprocessing

# 不能将共享变量和共享锁定义成全局变量然后通过global引用那样会报错,只能传过来
def sub_process(process_name,share_var,share_lock):
    # 获取锁
    share_lock.acquire()
    share_var.append(process_name)
    # 释放锁
    share_lock.release()
    for item in share_var:
        print(f"{process_name}-{item}")
    pass

def main_process():
    # 单个值声明方式。typecode是进制类型,C写法和Python写法都可以,见下方表格;value是初始值。
    # 这种单值形式取值赋值需要通过get()/set()方法进行,不能直接如一般变量那样取值赋值
    # share_var = multiprocessing.Manager().Value(typecode, value)
    # 数组声明方式。typecode是数组变量中的变量类型,sequence是数组初始值
    # share_var = multiprocessing.Manager().Array(typecode, sequence)
    # 字典声明方式
    # share_var = multiprocessing.Manager().dict()
    # 列表声明方式
    share_var = multiprocessing.Manager().list()
    share_var.append("start flag")
    # 声明一个进程级共享锁
    # 不要给多进程传threading.Lock()或者queue.Queue()等使用线程锁的变量,得用其进程级相对应的类
    # 不然会报如“TypeError: can't pickle _thread.lock objects”之类的报错
    share_lock = multiprocessing.Manager().Lock()
    process_list = []

    process_name = "process 1"
    tmp_process = multiprocessing.Process(target=sub_process,args=(process_name,share_var,share_lock))
    process_list.append(tmp_process)

    process_name = "process 2"
    tmp_process = multiprocessing.Process(target=sub_process, args=(process_name,share_var,share_lock))
    process_list.append(tmp_process)

    for process in process_list:
        process.start()
    for process in process_list:
        process.join()

if __name__ == "__main__":
    main_process()

执行结果如下,可以看到进程1中的修改已表现在进程2中

(不过要注意,和多线程一样,如果运算量再大一点进程1并不一定比进程2先执行):


typecode如果是数值或单个字符,可为以下类型(注意有引号):


如果是字符串类型,typecode可为以下第一列形式(注意无引号):

三、共享实例化对象实现方法

1 共享不需要修改实例化对象实现方法----使用global

但我们前面说过global方式不可以修改,但读还是没问题的;

所以对象引用还是可以使用global方式。

python">'''
遇到问题没人解答?小编创建了一个Python学习交流QQ群:702813599
寻找有志同道合的小伙伴,互帮互助,群里还有不错的视频学习教程和PDF电子书!
'''
import multiprocessing
import threading

# 实例化一个全局文件对象
file_obj = open("1.txt","a")
share_lock = threading.Lock()

def sub_process(process_name):
    global file_obj,share_lock
    share_lock.acquire()
    file_obj.writelines(f"{process_name}")
    share_lock.release()
    pass

def main_process():
    process_list = []
    # 创建进程1
    process_name = "process 1"
    tmp_process = multiprocessing.Process(target=sub_process,args=(process_name,))
    process_list.append(tmp_process)
    # 创建进程2
    process_name = "process 2"
    tmp_process = multiprocessing.Process(target=sub_process, args=(process_name,))
    process_list.append(tmp_process)
    # 启动所有进程
    for process in process_list:
        process.start()
    for process in process_list:
        process.join()

if __name__ == "__main__":
    main_process()

2 共享需要修改实例化对象实现方法----使用BaseManager

global方式不能修改变量(如要修改其成员变量),在大多时候也是可以了,但总让人觉得不是一种完美的实现方法。

有没有可以修改的实现方法呢,答案是有的,可以使用BaseManager。

示例代码如下:

python">import multiprocessing
from multiprocessing.managers import BaseManager
import threading

# 锁可以通过global也可以在Process中传无所谓
share_lock = threading.Lock()

# 定义一个要共享实例化对象的类
class Test():
    def __init__(self):
        self.test_list = ["start flag"]

    def test_function(self,arg):
        self.test_list.append(arg)

    def print_test_list(self):
        for item in self.test_list:
            print(f"{item}")

def sub_process(process_name,obj):
    global share_lock
    share_lock.acquire()
    obj.test_function(f"{process_name}")
    share_lock.release()
    obj.print_test_list()
    pass

def main_process():
    # 如果是想注册open方法这样操作
    # manager = BaseManager()
    # # 一定要在start前注册,不然就注册无效
    # manager.register('open', open)
    # manager.start()
    # obj = manager.open("1.txt","a")

    # 为了更加直接我们直接以一个Test类的实例化对象来演示
    manager = BaseManager()
    # 一定要在start前注册,不然就注册无效
    manager.register('Test', Test)
    manager.start()
    obj = manager.Test()
    '''
     遇到问题没人解答?小编创建了一个Python学习交流QQ群:702813599
     寻找有志同道合的小伙伴,互帮互助,群里还有不错的视频学习教程和PDF电子书!
    '''
    process_list = []
    # 创建进程1
    process_name = "process 1"
    tmp_process = multiprocessing.Process(target=sub_process,args=(process_name,obj))
    process_list.append(tmp_process)
    # 创建进程2
    process_name = "process 2"
    tmp_process = multiprocessing.Process(target=sub_process, args=(process_name,obj))
    process_list.append(tmp_process)
    # 启动所有进程
    for process in process_list:
        process.start()
    for process in process_list:
        process.join()


if __name__ == "__main__":
    main_process()

执行结果如下,可以看到进程1中的修改已表现在进程2中

(不过要注意,和多线程一样,如果运算量再大一点进程1并不一定比进程2先执行):

尾语

好了,今天的分享就差不多到这里了!

对下一篇大家想看什么,可在评论区留言哦!看到我会更新哒(ง •_•)ง

喜欢就关注一下博主,或点赞收藏评论一下我的文章叭!!!

最后,宣传一下呀~👇👇👇 更多源码、资料、素材、解答、交流 皆点击下方名片获取呀👇👇👇


http://www.niftyadmin.cn/n/5013523.html

相关文章

【面试】Redis的热key问题如何发现和解决?

文章目录 背景一、怎么发现热key1.1 方法一:凭借业务经验,进行预估哪些是热key1.2 方法二:在客户端进行收集1.3 方法三:在Proxy层做收集1.4 方法四:用redis自带命令1.5 方法五:自己抓包评估 二、如何解决2.1. 利用二级缓存2.2. 备份热key2.3 永不过期2.4 分布式锁 三…

mkp勒索病毒的介绍和防范,勒索病毒解密,数据恢复

mkp勒索病毒是一种新兴的电脑病毒,它会对感染的电脑进行加密,并要求用户支付一定的赎金才能解锁。这种病毒已经引起了全球范围内的关注,因为它不仅具有高危害性,而且还有很强的传播能力。本文将对mkp勒索病毒进行详细介绍&#xf…

【C++】静态库lib和动态库dll的优缺点、使用方法

创作不易&#xff0c;本篇文章如果帮助到了你&#xff0c;还请点赞 关注支持一下♡>&#x16966;<)!! 主页专栏有更多知识&#xff0c;如有疑问欢迎大家指正讨论&#xff0c;共同进步&#xff01; &#x1f525;c系列专栏&#xff1a;C/C零基础到精通 &#x1f525; 给大…

无涯教程-JavaScript - IMSINH函数

描述 MSINH函数以x yi或x yj文本格式返回复数的双曲正弦值。复数的双曲正弦通过以下公式计算- $$\sinh(x yi) \sinh(x)\cos(y)-\cosh(x)\sin(y)i $$ 语法 IMSINH (inumber)争论 Argument描述Required/OptionalInumberA complex number for which you want the hyperbol…

MJDK 如何实现压缩速率的 5 倍提升?

MJDK 是基于 OpenJDK 构建的美团 JDK 发行版。本文主要介绍 MJDK 是如何在保障 java.util.zip.* API 及压缩格式兼容性的前提下&#xff0c;实现压缩/解压缩速率提升 5-10 倍的效果。希望相关的经验能够帮助到更多的技术同学。 1 前言 数据压缩技术[1]因可有效降低数据存储及…

直播 | 丹望医疗王晓林博士“基于微流控的血管化器官/类器官芯片构建及其应用”

类器官模型具有高仿真性&#xff0c;与人体器官有高度相似的组织学特征和功能&#xff0c;尤其在肿瘤模型中能够较好保留肿瘤异质性等优势&#xff0c;在精准医疗及药物筛选等领域具有广泛的应用前景。同时&#xff0c;基于微流控技术的器官芯片能在微流体装置上实现多重微环境…

C/C++之链表的建立

个人主页&#xff1a;点我进入主页 专栏分类&#xff1a;C语言初阶 C语言程序设计————KTV C语言小游戏 C语言进阶 C语言刷题 欢迎大家点赞&#xff0c;评论&#xff0c;收藏。 一起努力&#xff0c;一起奔赴大厂。 目录 1.头插 1.1简介 1.2代码实现头插 …

PostgreSQL在进行除法时要注意

背景 整型除以整型&#xff0c;正常情况下当然得到的应该也是整型。数据库也是这么干的。 但是在数据库应用中&#xff0c;通常业务的需求是得到NUMERIC&#xff0c;不能直接把小数干掉。 数据库的行为给用户带来了诸多不便&#xff0c;例如1除以2&#xff0c;如果是整型除法会…