python管理器注册问题或只是我的错误代码

2024-04-23 10:09:20 发布

您现在位置:Python中文网/ 问答频道 /正文

我使用python管理器在进程之间共享数据。我想把我的代码分解成更小的片段,并创建一个函数“soFactory”,它将获取一个名称/对象对字典,并以给定的名称向管理器注册对象。 在下面的简单示例中,我创建了两个列表并向管理器注册它们。如果我使用soFactory,经理只返回一个列表(最后一个注册的列表),而不管我引用哪个名称。 如果我解开了soFactory的逻辑,我就可以通过引用它们的注册名称来访问正确的对象。 我一定错过了一些明显的东西,但没有看到它。你知道吗

# ------------ prototype for SO question -------
from sys import stderr

def soFactory(dictofSo, manager):
    """shared object factory"""
    for n,t in dictofSo.items():
        print >>stderr, 'created item',n,t
        manager.register(n, callable=lambda: t)

def soRoutine(n, t, manager):
    manager.register(n, callable=lambda: t)

def test_soFactory(useFactory=True):
    """tests the soFactory function"""
    from multiprocessing import managers
    m = managers.BaseManager(address='/var/tmp/tqps-test', authkey='abc123')
    mySOlist = {'L1': [1],'L2':[2]}

    if useFactory:
        soFactory(mySOlist, m)
    else:
        for n, t in mySOlist.items():
            soRoutine(n, t, m)

    m.start()

    m.L1().append('only in L1!')
    print >>stderr, m.L1(), m.L2()

>>> test_soFactory()
created item L2 [2]
created item L1 [1]
[1, 'only in L1!'] [1, 'only in L1!']

>>> test_soFactory(useFactory=False)
[1, 'only in L1!'] [2]
>>> 

Tags: 对象intest名称l1only管理器列表
1条回答
网友
1楼 · 发布于 2024-04-23 10:09:20

这是一个常见的python变量作用域陷阱,这是由于lambda创建的闭包记住了变量的名称,而不是对象(或“指针”)。调用lambda时, t的值是在周围的范围内查找的,此时循环已经结束,所以t分配了它的最终值L1,当然,这取决于dictofSo.items()返回值的顺序。你知道吗

您可以通过打开multiprocessing的调试日志来确认这一点:

import logging
import multiprocessing
multiprocessing.util.log_to_stderr(logging.DEBUG)

L1L2具有相同的id:

[DEBUG/MainProcess] requesting creation of a shared 'L1' object
[DEBUG/BaseManager-1] 'L1' callable returned object with id '104aef878'
[DEBUG/MainProcess] INCREF '104aef878'
...
[DEBUG/MainProcess] requesting creation of a shared 'L2' object
[DEBUG/BaseManager-1] 'L2' callable returned object with id '104aef878'

在函数soRoutine()中创建lambda时,因为函数将创建一个新的局部作用域,所以这次t可能会指向您期望的值。另见this post。你知道吗

相关问题 更多 >