Python - 如何在 class 实例中使用多处理锁?
Python - How to use multiprocessing Lock in class instance?
我在 Windows 上使用 Python 3.7。
我想做什么:
- 当另一个进程获得相同的锁时,锁定 class 实例的方法。
尝试次数:
我已经成功完成 this,但我不想在这里使用全局变量来锁定,而是完全在 class
内部
from multiprocessing import Lock, freeze_support,Pool
from time import sleep
def do_work(name):
print(name+' waiting for lock to work...',end='')
sleep(2)
with lock:
print('done!')
print(name+' doing work...',end='')
sleep(5)
print('done!')
def init(olock):
global lock
lock = olock
if __name__ == '__main__':
freeze_support()
args_list = [('a'),('b'),('c')]
lock=Lock()
p=Pool(8,initializer=init,initargs=(lock,))
p.map_async(do_work,args_list)
p.close()
p.join()
当最后一段代码运行时,由于锁的缘故,它需要 ~17.3 秒。没有锁需要 ~7 秒.
我尝试在 class 中实现这个,但是锁什么都不做,它总是在 ~7 秒内运行 .
class O():
def __init__(self):
self.lock=Lock()
def __getstate__(self): # used to remove multiprocess object(s) from class, so it can be pickled
self_dict=self.__dict__.copy()
del self_dict['lock']
return self_dict
def __setstate__(self,state): # used to remove multiprocess object(s) from class, so it can be pickled
self.__dict__.update(state)
def _do_work(self,name):
print(name+' waiting for lock to work...',end='')
sleep(2)
with self.lock:
print('done!')
print(name+' doing work...',end='')
sleep(5)
print('done!')
if __name__ == '__main__':
freeze_support()
c = O()
pool = Pool(8)
pool.apply_async(c._do_work,('a',))
pool.apply_async(c._do_work,('b',))
pool.apply_async(c._do_work,('c',))
pool.close()
pool.join()
问题:
那么,当我调用一个通过多处理与资源异步交互的方法时,我该怎么做才能锁定这个 class 实例?
apply_async
将 pickle 函数对象并按队列发送到池工作进程,但由于 c._do_work
是绑定方法,实例也会被 pickle,从而导致错误。你可以将它包装在一个简单的函数中:
c = O()
def w(*args):
return c._do_work(*args)
if __name__ == '__main__':
pool = Pool(1)
pool.apply_async(w, ('a',))
...
你应该删除 __setstate__
/__getstate__
.
我在 Windows 上使用 Python 3.7。
我想做什么: - 当另一个进程获得相同的锁时,锁定 class 实例的方法。
尝试次数:
我已经成功完成 this,但我不想在这里使用全局变量来锁定,而是完全在 class
内部from multiprocessing import Lock, freeze_support,Pool
from time import sleep
def do_work(name):
print(name+' waiting for lock to work...',end='')
sleep(2)
with lock:
print('done!')
print(name+' doing work...',end='')
sleep(5)
print('done!')
def init(olock):
global lock
lock = olock
if __name__ == '__main__':
freeze_support()
args_list = [('a'),('b'),('c')]
lock=Lock()
p=Pool(8,initializer=init,initargs=(lock,))
p.map_async(do_work,args_list)
p.close()
p.join()
当最后一段代码运行时,由于锁的缘故,它需要 ~17.3 秒。没有锁需要 ~7 秒.
我尝试在 class 中实现这个,但是锁什么都不做,它总是在 ~7 秒内运行 .
class O():
def __init__(self):
self.lock=Lock()
def __getstate__(self): # used to remove multiprocess object(s) from class, so it can be pickled
self_dict=self.__dict__.copy()
del self_dict['lock']
return self_dict
def __setstate__(self,state): # used to remove multiprocess object(s) from class, so it can be pickled
self.__dict__.update(state)
def _do_work(self,name):
print(name+' waiting for lock to work...',end='')
sleep(2)
with self.lock:
print('done!')
print(name+' doing work...',end='')
sleep(5)
print('done!')
if __name__ == '__main__':
freeze_support()
c = O()
pool = Pool(8)
pool.apply_async(c._do_work,('a',))
pool.apply_async(c._do_work,('b',))
pool.apply_async(c._do_work,('c',))
pool.close()
pool.join()
问题: 那么,当我调用一个通过多处理与资源异步交互的方法时,我该怎么做才能锁定这个 class 实例?
apply_async
将 pickle 函数对象并按队列发送到池工作进程,但由于 c._do_work
是绑定方法,实例也会被 pickle,从而导致错误。你可以将它包装在一个简单的函数中:
c = O()
def w(*args):
return c._do_work(*args)
if __name__ == '__main__':
pool = Pool(1)
pool.apply_async(w, ('a',))
...
你应该删除 __setstate__
/__getstate__
.