为什么我的上下文管理器__exit__函数在计算未完成之前运行?

问题描述 投票:-1回答:2

我的自定义上下文管理器的退出功能似乎在计算完成之前运行。我的上下文管理器旨在简化编写并发/并行代码。这是我的上下文管理器代码:

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__如此早就被召唤?

python python-multiprocessing contextmanager
2个回答
1
投票

你确定你刚刚打电话给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

0
投票

最可能的解释是发生了异常。上面的代码示例不解析type语句的valuetraceback__exit__参数。因此,发生异常(并且未被更早捕获),将被移交给退出语句,而退出语句又不会对其作出反应。进程(或其中一些)继续运行。

© www.soinside.com 2019 - 2024. All rights reserved.