我的自定义上下文管理器的退出功能似乎在计算完成之前运行。我的上下文管理器旨在简化编写并发/并行代码。这是我的上下文管理器代码:
import time
from multiprocessing.dummy import Pool, cpu_count
class managed_pool:
'''Simple context manager for multiprocessing.dummy.Pool'''
def __init__(self, msg):
self.msg = msg
def __enter__(self):
cores = cpu_count()
print 'start concurrent ({0} cores): {1}'.format(cores, self.msg)
self.start = time.time()
self.pool = Pool(cores)
return self.pool
def __exit__(self, type_, value, traceback):
print 'end concurrent:', self.msg
print 'time:', time.time() - self.start
self.pool.close()
self.pool.join()
我已经用multiprocessing.Pool
而不是multiprocessing.dummy.Pool
尝试过这个脚本,它似乎总是失败。
以下是使用上下文管理器的示例:
def read_engine_files(f):
engine_input = engineInput()
with open(f, 'rb') as f:
engine_input.parse_from_string(f.read())
return engine_input
with managed_pool('load input files') as pool:
data = pool.map(read_engine_files, files)
所以,在read_engine_files
里面我打印文件的名称。您会注意到在__exit__
函数中,我还会在计算完成时打印出来并且需要多长时间。但是当查看stdout时,__exit__
消息在计算完成之前出现。比如,计算完成前几分钟。但htop
表示我的所有内核仍在使用中。这是输出的一个例子
start concurrent (4 cores): load engine input files
file1.pbin
file2.pbin
...
file16.pbin
end concurrent: load engine input files
time: 246.43829298
file17.pbin
...
file45.pbin
为什么__exit__
如此早就被召唤?
你确定你刚刚打电话给pool.map()
吗?这应该阻止,直到所有项目都已映射。
如果您正在调用Pool
的异步方法之一,那么您应该能够通过更改__exit__()
中的事物顺序来解决问题。在完成摘要之前,只需加入池。
def __exit__(self, type_, value, traceback):
self.pool.close()
self.pool.join()
print 'end concurrent:', self.msg
print 'time:', time.time() - self.start
最可能的解释是发生了异常。上面的代码示例不解析type
语句的value
,traceback
或__exit__
参数。因此,发生异常(并且未被更早捕获),将被移交给退出语句,而退出语句又不会对其作出反应。进程(或其中一些)继续运行。