Python 多处理全局变量更新未返回到父级

Python 多处理全局变量更新未返回到父级,python,multiprocessing,Python,Multiprocessing,我试图从子流程返回值,但不幸的是,这些值不可拼接。所以我成功地在threads模块中使用了全局变量,但在使用多处理模块时无法检索子流程中完成的更新。我希望我错过了什么 最后打印的结果始终与给定VAR的初始值相同dataDV03和dataDV04。子流程正在更新这些全局变量,但这些全局变量在父流程中保持不变 import multiprocessing # NOT ABLE to get python to return values in passed variables. ants = [

我试图从子流程返回值,但不幸的是,这些值不可拼接。所以我成功地在threads模块中使用了全局变量,但在使用多处理模块时无法检索子流程中完成的更新。我希望我错过了什么

最后打印的结果始终与给定VAR的初始值相同
dataDV03
dataDV04
。子流程正在更新这些全局变量,但这些全局变量在父流程中保持不变

import multiprocessing

# NOT ABLE to get python to return values in passed variables.

ants = ['DV03', 'DV04']
dataDV03 = ['', '']
dataDV04 = {'driver': '', 'status': ''}


def getDV03CclDrivers(lib):  # call global variable
    global dataDV03
    dataDV03[1] = 1
    dataDV03[0] = 0

# eval( 'CCL.' + lib + '.' +  lib + '( "DV03" )' ) these are unpicklable instantiations

def getDV04CclDrivers(lib, dataDV04):   # pass global variable
    dataDV04['driver'] = 0  # eval( 'CCL.' + lib + '.' +  lib + '( "DV04" )' )


if __name__ == "__main__":

    jobs = []
    if 'DV03' in ants:
        j = multiprocessing.Process(target=getDV03CclDrivers, args=('LORR',))
        jobs.append(j)

    if 'DV04' in ants:
        j = multiprocessing.Process(target=getDV04CclDrivers, args=('LORR', dataDV04))
        jobs.append(j)

    for j in jobs:
        j.start()

    for j in jobs:
        j.join()

    print 'Results:\n'
    print 'DV03', dataDV03
    print 'DV04', dataDV04
我无法发布我的问题,因此将尝试编辑原始内容

以下是不可拾取的对象:

[1]中的
:来自CCL进口卡车
在[2]中:lorr=lorr.lorr('DV20',无)
在[3]中:卡车
出[3]:
这是我使用multiprocessing.Pool将实例返回父实例时返回的错误:

print 'DV03', shared_dataDV03[:]
线程getCcl(('DV20','LORR'),)
流程池工人-1:
回溯(最近一次呼叫最后一次):
文件“/alma/ACS-10.1/casa/lib/python2.6/multiprocessing/process.py”,第232行,在引导程序中
self.run()
文件“/alma/ACS-10.1/casa/lib/python2.6/multiprocessing/process.py”,第88行,运行中
自我目标(*自我参数,**自我参数)
文件“/alma/ACS-10.1/casa/lib/python2.6/multiprocessing/pool.py”,第71行,在worker中
put((作业、i、结果))
文件“/alma/ACS-10.1/casa/lib/python2.6/multiprocessing/queues.py”,第366行,输入
返回发送(obj)
UnpicklableError:无法pickle对象
[5]中的
dir(卡车)
出[5]:
[“获取环境温度”,
“GET_CAN_ERROR”,
“获取错误计数”,
“获取频道号”,
“每一次行动都能得到计数”,
“获取剩余数量”,
“锁定DCM”,
“获取EFC_125_MHZ”,
“获取EFC梳线PLL”,
'获取错误\u代码\u最后一次\u可以\u错误',
'获取\u内部\u从属\u错误\u代码',
“获得大小摄氏度”,
“获取主要版本级别”,
“获取次要版本级别”,
“获取模块代码日期”,
“每个月获取模块代码”,
'获取模块代码\u DIG1',
“获取模块代码2”,
“获取模块代码4”,
“获取模块代码”,
“获取模块代码序列”,
“获取模块代码版本主版本”,
“获取模块代码版本小版本”,
“获取模块代码\u年”,
“获取节点地址”,
“关闭光学电源”,
“获取输出125MHZ锁定”,
“获得输出2GHZ锁定”,
“获取补丁级别”,
“获取电源\u 12V\u不正常”,
'获取电源\u 15V\u不正常',
“获取协议、主要版本级别”,
“获取协议级别、次要级别、修订级别”,
“获取协议补丁级别”,
“获取协议版本级别”,
“获得125兆赫”,
“获得25兆赫”,
“得到2千兆赫”,
'获取读取模块代码',
“获取RX选择PWR”,
“获取序列号”,
“得到签名”,
“获取您的状态”,
“获取软件版本级别”,
“获取长度”,
“获取长旗集”,
“获取偏移计数器”,
“获取短标志集”,
“GET_TRANS_NUM”,
“获取VDC_12”,
“获取VDC_15”,
“获取VDC_7”,
'获取VDC_减去_7',
“设置清除标志”,
“设置FPGA逻辑复位”,
“设置/重置/设置”,
“设置重置设备”,
“设置重新同步”,
"地位",,
'硬件设备\组件名称',
“硬件设备”,
"硬件设备",,
“"洛基"记录器",,
"德尔",,
"医生",,
"初始化",,
'模块'',
"设备",,
“clearDeviceCommunicationErrorAlarm”,
“getControlList”,
“getDeviceCommunicationErrorCounter”,
“getErrorMessage”,
“getHwState”,
“getInternalSlaveCanErrorMsg”,
“getLastCanErrorMsg”,
“getMonitorList”,
“hwConfigure”,
"hw诊断",,
“HW初始化”,
"运作",,
"模拟",,
“hwStart”,
"停止",,
“无核国家”,
“isMonitoring”,
“isSimulated”]
在[6]中:

使用
多进程
时,在进程之间传递对象的唯一方法是使用
队列
管道
;全局文件不共享。对象必须是可pickle的,因此,
multi-process
在这里对您没有帮助。

@DBlas在回答中为您提供了一个快速url和对Manager类的引用,但我认为它仍然有点模糊,所以我认为只要看到它的应用,可能会对您有所帮助

import multiprocessing
from multiprocessing import Manager

ants = ['DV03', 'DV04']

def getDV03CclDrivers(lib, data_dict):  
    data_dict[1] = 1
    data_dict[0] = 0

def getDV04CclDrivers(lib, data_list):   
    data_list['driver'] = 0  


if __name__ == "__main__":

    manager = Manager()
    dataDV03 = manager.list(['', ''])
    dataDV04 = manager.dict({'driver': '', 'status': ''})

    jobs = []
    if 'DV03' in ants:
        j = multiprocessing.Process(
                target=getDV03CclDrivers, 
                args=('LORR', dataDV03))
        jobs.append(j)

    if 'DV04' in ants:
        j = multiprocessing.Process(
                target=getDV04CclDrivers, 
                args=('LORR', dataDV04))
        jobs.append(j)

    for j in jobs:
        j.start()

    for j in jobs:
        j.join()

    print 'Results:\n'
    print 'DV03', dataDV03
    print 'DV04', dataDV04
因为多处理实际上使用单独的进程,所以不能简单地共享全局变量,因为它们将位于内存中完全不同的“空间”。您在一个流程下对一个全局对象所做的操作不会反映在另一个流程中。虽然我承认,从你的角度来看,这似乎令人困惑,但它都存在于同一段代码中,所以“为什么这些方法不能访问全局?”?很难想象它们将在不同的进程中运行

提供的作为数据结构的代理,可以在进程之间来回传递信息。您将要做的是从管理器创建一个特殊的dict和list,将它们传递到您的方法中,并在本地对它们进行操作

不可pickle的数据

对于specialize LORR对象,您可能需要创建代理之类的东西来表示实例的可拾取状态

不是超级健壮或测试过很多,但给你的想法

class LORRProxy(object):

    def __init__(self, lorrObject=None):
        self.instance = lorrObject

    def __getstate__(self):
        # how to get the state data out of a lorr instance
        inst = self.instance
        state = dict(
            foo = inst.a,
            bar = inst.b,
        )
        return state

    def __setstate__(self, state):
        # rebuilt a lorr instance from state
        lorr = LORR.LORR()
        lorr.a = state['foo']
        lorr.b = state['bar']
        self.instance = lorr

当您使用
multiprocessing
打开第二个进程时,将创建一个具有自己全局状态的全新Python实例。该全局状态不共享,因此子进程对全局变量所做的更改对父进程不可见

此外,
多处理
提供的大多数抽象都使用pickle来传输数据。使用代理传输的所有数据;其中包括所创建的所有对象。相关报价(我的重点):

确保代理方法的参数是可拾取的

和(在
管理器
部分):

其他进程可以使用代理访问共享对象

队列
也需要可pickle的数据;医生没有这么说,但快速测试证实了这一点:

import multiprocessing
import pickle

class Thing(object):
    def __getstate__(self):
        print 'got pickled'
        return self.__dict__
    def __setstate__(self, state):
        print 'got unpickled'
        self.__dict__.update(state)

q = multiprocessing.Queue()
p = multiprocessing.Process(target=q.put, args=(Thing(),))
p.start()
print q.get()
p.join()
输出:

$ python mp.py 
got pickled
got unpickled
<__main__.Thing object at 0x10056b350>
我使用p.map()将许多进程剥离到远程服务器,并在不可预知的时间返回时打印结果:

Servers=[...]
from multiprocessing import Pool
p=Pool(len(Servers))
p.map(DoIndividualSummary, Servers)
如果
DoIndividualSummary
us,这个方法很有效
import sqlite3
conn=sqlite3.connect('servers.db') # need conn for commit and close
db=conn.cursor()
try: db.execute('''drop table servers''')
except: pass
db.execute('''CREATE TABLE servers (server text, serverdetail text, readings     text)''')
conn.commit()
db.execute('''INSERT INTO servers VALUES (?,?,?)''',         (server,serverdetail,readings))
conn.commit()
return
db.execute('''select * from servers order by server''')
rows=db.fetchall()
for server,serverdetail,readings in rows: print serverdetail,readings
shared_dataDV03 = multiprocessing.Array ('i', (0, 0)) #a shared array
j = multiprocessing.Process(target=getDV03CclDrivers, args=('LORR',shared_dataDV03))
def getDV03CclDrivers(lib,arr):  # call global variable
    arr[1]=1
    arr[0]=0
print 'DV03', shared_dataDV03[:]
DV03 [0, 1]