在不同python模块的函数中无法识别锁



我有一个多处理锁,我将其定义为

import multiprocessing
lock1 = mp.Lock()

要在不同的子进程之间共享此锁,我需要:

def setup_process(lock1):
global lock_1
lock_1 = lock1
pool = mp.Pool(os.cpu_count() - 1,
initializer=setup_process,
initargs=[lock1])

现在我注意到,如果进程调用以下函数,并且该函数是在同一个python模块(即同一个文件(中定义的:

def test_func():
print("lock_1:", lock_1)
with lock_1:
print(str(mp.current_process()) + " has the lock in test function.")

我得到的输出像:

lock_1 <Lock(owner=None)>
<ForkProcess name='ForkPoolWorker-1' parent=82414 started daemon> has the lock in test function.
lock_1 <Lock(owner=None)>
<ForkProcess name='ForkPoolWorker-2' parent=82414 started daemon> has the lock in test function.
lock_1 <Lock(owner=None)>
<ForkProcess name='ForkPoolWorker-3' parent=82414 started daemon> has the lock in test function.

然而,如果test_function是在另一个文件中定义的,那么Lock就无法识别,我得到:

NameError:
name 'lock_1' is not defined

这似乎发生在每个函数中,其中重要的区别是函数是在这个模块中定义的还是在另一个模块中定义。我确信我遗漏了一些关于全局变量的非常明显的东西,但我是新手,我还没能弄清楚。如何使Locks在任何地方都能被识别?

好吧,我今天学到了关于python的一些新东西:global实际上并不是真正的全局性的。它只能在模块范围内访问

有很多方法可以与模块共享锁,以便使用它,文档甚至建议使用"锁";规范的";在模块之间共享全局变量的方式(尽管我觉得这不适合这种情况(。对我来说,这种情况首先说明了使用全局变量的一个缺点,尽管我必须承认,在multiprocessing.Pool初始化程序的特定情况下,使用全局变量将数据传递给工作函数似乎是公认的,甚至是预期的用例。实际上,全局变量不能跨越模块边界是有道理的,因为这会使单独的模块100%依赖于由特定脚本执行,因此它不能真正被视为单独的独立库。相反,它可以被包含在同一个文件中。我认识到,这可能与拆分代码不一致,不是为了创建可重复使用的库,而是为了将代码逻辑地组织在较短的可读段中,但这显然是python设计者的风格选择。

为了解决您的问题,在一天结束时,您将不得不将锁作为参数传递给另一个模块,因此您不妨将test_func接收lock_1作为参数。但是,您可能已经发现,这将导致RuntimeError: Lock objects should only be shared between processes through inheritance消息,那么该怎么办呢?基本上,我会保留您的初始值设定项,并将test_func放在__main__作用域中的另一个函数中(因此可以访问您的global lock_1(,该函数获取锁,然后将其传递给该函数。不幸的是,我们不能使用外观更好的装饰器或包装器函数,因为它们返回的函数只存在于本地范围中,并且在使用"时无法导入;"产卵";作为启动方法。

from multiprocessing import Pool, Lock, current_process
def init(l):
global lock_1
lock_1 = l
def local_test_func(shared_lock):
with shared_lock:
print(f"{current_process()} has the lock in local_test_func")
def local_wrapper():
global lock_1
local_test_func(lock_1)
from mymodule import module_test_func #same as local_test_func basically...
def module_wrapper():
global lock_1
module_test_func(lock_1)
if __name__ == "__main__":
l = Lock()
with Pool(initializer=init, initargs=(l,)) as p:
p.apply(local_wrapper)
p.apply(module_wrapper)

相关内容

  • 没有找到相关文章

最新更新