首页 > 系统相关 >Python3多进程共享变量实现方法

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

时间:2023-04-28 11:11:37浏览次数:50  
标签:变量 process list share long int 共享 Python3 name

今天同事反映一个问题让帮忙看一下:多进程共用一个变量,在一个进程中修改后,在另外的进程中并没有产生修改。

 

一、错误的实现方式

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

复制代码
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先执行):

 

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

参考:https://blog.csdn.net/houyanhua1/article/details/78244288

复制代码
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如果是数值或单个字符,可为以下类型(注意有引号):

Type Code C Type Python Type
'c' char character
'b' signed char int
'B' unsigned char int
'u' Py_UNICODE unicode character
'h' signed short int
'H' unsigned short int
'i' signed int int
'I' unsigned int int
'l' signed long int
'L' unsigned long int
'f' float float
'd' double float

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

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

ctypes type C type Python type

c_bool

_Bool bool (1)
char  char 1-character string
c_wchar wchar_t 1-character unicode string
c_byte char int/long
c_ubyte unsigned char int/long
c_short short int/long
c_ushort unsigned short int/long
c_int int int/long
c_uint unsigned in int/long
c_long long int/long
c_ulong unsigned long int/long
c_longlong __int64 or long long int/long
c_ulonglong unsigned __int64 or unsigned long long int/long
c_float float float
c_double double float
c_longdouble long double float
c_char_p char * (NUL terminated) string or None

c_wchar_p

wchar_t * (NUL terminated) unicode or None
c_void_p void * int/long or None

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

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

同事还想共享一个文件对象,然后问上边的方法是不是只能共享字典、列表,没法共享对象。

回头一看,Value和Array中typecode要求是c语言中存在的类型,其他只有dict()和list()方法没有其他方法,所以似乎上边的方法共享实例化对象是不行的。

 

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

但我们前面说过global方式不可以修改,但读还是没问题的;所以对象引用还是可以使用global方式。

复制代码
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()
复制代码

 

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

global方式不能修改变量(如要修改其成员变量),在大多时候也是可以了,但总让人觉得不是一种完美的实现方法。有没有可以修改的实现方法呢,答案是有的,可以使用BaseManager。示例代码如下。

参考:https://blog.csdn.net/jacke121/article/details/82658471

复制代码
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()

    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先执行):

 

参考:

https://blog.51cto.com/11026142/1874807

https://docs.python.org/3/library/multiprocessing.html#module-multiprocessing

标签:变量,process,list,share,long,int,共享,Python3,name
From: https://www.cnblogs.com/kn-zheng/p/17361569.html

相关文章

  • Python3+WebSockets实现WebSocket通信
    一、说明1.1背景说明前段时间同事说云平台通信使用了个websocket的东西,今天抽空来看一下具体是怎么个通信过程。从形式上看,websocket是一个应用层协议,socket是数据链路层、网络层、传输层的抽像;从应用场合上看,websocket可以使用javascript实现,而socket不能用javascript实现(真......
  • Python3+cgroupspy安装使用教程
    一、系统资源使用限制的必要性探讨对于一个脚本,最基础的限制是要限制单进程实例以保证了不会存在多个进程实例、在运行程序主体逻辑前检测系统资源剩余量确保自己不是压夸系统的最后一根稻草、设置程序运行超时时间以保证进程实例不会无休止地运行下去。进一步,在部署有可用性要......
  • Python3从头/尾删除子符串的正确操作
    一、说明从某个时候发现python的字符串变量自带的strip()方法,除了可以删除字符串头尾的空格,还可以用来删除头尾的字符串觉得很好用。也就一直这么用,一直也没发现什么问题。今天在修复一个bug时使用了strip()方法但从结果看bug并没有按预期被消除,一是没怀疑strip()删除子字符串有......
  • Python3文件路径/目录获取教程
    一、获取文件路径实现1.1获取当前文件路径importoscurrent_file_path=__file__print(f"current_file_path:{current_file_path}")__file__变量其实有个问题,当文件被是被调用文件时__file__总是文件的绝对路径;但当文件是直接被执行的文件时,__file__并不总是文件的绝对......
  • (五) Java变量与数据类型
    目录Java变量Java数据类型基本数据类型整数类型浮点(小数)类型字符型整型细节引用类型Java变量需要先声明,再赋值inta;intb=10;Java数据类型Java数据类型分为两大类:基本数据类型,引用类型基本数据类型基本数据类型有8种,其中6种数值型[byte,short,int,long......
  • Python3压缩和解压缩实现
    一、说明压缩和解压缩是日常常用的操作,不管是windows上图形界面的操作,还是linux上用命令来进行压缩解压缩,总的而言都还是比较方便的。但用代码来实现就没做过,近期也得实现代码压缩与解压缩操作,所以就抽时间来研究一下。 二、zip文件压缩和解压缩实现importosimportzipf......
  • Nuxt3环境变量配置
    Nuxt3正式发布还不到半年,在投入生产环境使用后,遇到了不少问题,很难找到合适的解决方案,其中环境变量配置就是其中一个,之前一直未能解决,最近要上持续集成,无法绕过这个问题,所以花了点时间研究了一下,最终找到了解决方案,记录一下。官方文档面对一个新框架,我们自然是希望官方文档能够......
  • 变量乱变问题(求大佬指点!!!)
    环境:AMD,win10_x64,cygwin64,vscode,coderunner与预期不符的代码:#include<string.h>#include"stdio.h"typedefcharElemType;typedefstructBiTNode{ElemTypedata;structBTNode*lchild;structBTNode*rchild;}BTNode,*BiTree;BTNod......
  • 每日总结2023-04-27——关于全局变量的基础使用
    今天完成了对全局变量的使用packagecom.example.math;/**全局变量**/importandroid.app.Application;publicclassCustomApplicationextendsApplication{privatestaticfinalStringVALUE="111";privateStringvalue;@Overridepublic......
  • 发布Flash跨域策略,CORS跨域资源共享漏洞,设置访问白名单
    1      问题描述:跨域策略文件配置问题:<allow-access-fromdomain="*"/>,允许从任何域进行访问 2      解决方案:找到对应的文件,正确配置白名单,配置样例如下: ......