在绘图期间,Python多处理挂起

时间:2017-12-21 22:13:54

标签: python python-2.7 matplotlib multiprocessing hang

我使用Python的多处理模块运行的代码挂起时没有任何警告或错误。我想我已经把它缩小到生成情节的时候。多处理和matplotlib之间是否存在一些不兼容性?

我正在使用Python(使用numpy,scipy,pandas)预处理大量数据集。每个数据集由一组独立的数据文件组成。我读入原始数据并为每个数据集编写一个.pkl文件和一些.png文件。使用matplotlib和seaborn生成图。数字保存到文件而不显示。每个数据集的预处理应完全相互独立。

处理连续工作。 preprocess.main_debug()接受path / filename / flags并返回状态字符串('complete','skipped'等):

import preprocess

# Serial processing
dataroot = '/Volumes/ExtData/'
study = 'study0'
datasets = ['data0', 'data1', 'data2']
force_preprocess = True
quiet_console = False

status = [preprocess.main_debug(dataroot, study, dataset,
                                force_preprocess, quiet_console)
          for dataset in datasets]

# Print summary
print('\n---- Summary --------------')
for d, s in zip(datasets, status):
    print(' {}:\t{}'.format(d, s))

但多处理暂停:

import multiprocessing as mp
import logging
import preprocess

dataroot = '/Volumes/ExtData/'
study = 'study0'
datasets = ['data0', 'data1', 'data2']
force_preprocess = True
quiet_console = True  # Suppress console output

# Send multiprocessing logs to console
mp.log_to_stderr()
logger = mp.get_logger()
logger.setLevel(logging.INFO)

# Parallel process
pool = mp.Pool(processes=3, maxtasksperchild=1)
results = [pool.apply_async(preprocess.main_debug,
                            args=(dataroot, study, dataset,
                            force_preprocess, quiet_console)) 
           for dataset in datasets]
status = [p.get(timeout=None) for p in results]

# Print summary
print('\n---- Summary --------------')
for d, s in zip(datasets, status):
  print(' {}:\t{}'.format(d, s))

我已经摆弄了进程数量,maxtasksperchild和超时无效。我在网上发现了一些链接,表明日志记录和多处理之间可能存在一些不兼容性,因此我删除了所有日志记录代码,但执行方式仍然相同。

当我运行代码的多处理版本时,我在控制台中看到了这一点。

$ python batchpreprocess.py 
[INFO/PoolWorker-1] child process calling self.run()
[INFO/PoolWorker-2] child process calling self.run()
[INFO/PoolWorker-3] child process calling self.run()

大约7分钟后,CPU使用率从100%下降到0%,内存使用量从~12GB下降到~3MB。然后我看到又开始了3个子进程。事情一直停留在这种状态(至少一夜之间)。对我来说似乎很奇怪,因为我只测试了3个数据集,所以我预计总共只有3个子进程。

$ python batchpreprocess.py 
[INFO/PoolWorker-1] child process calling self.run()
[INFO/PoolWorker-2] child process calling self.run()
[INFO/PoolWorker-3] child process calling self.run()
[INFO/PoolWorker-4] child process calling self.run()
[INFO/PoolWorker-5] child process calling self.run()
[INFO/PoolWorker-6] child process calling self.run()  

我用记录语句撒了我的代码。它崩溃了我有绘图代码,将生成波形图。如果我删除了绘图代码,执行将继续执行该点,但随后它将挂起到下一个绘图。

preprocess.main_debug()的内容如下所示:

def main_debug(dataroot, study, dataset, force_preprocess, quiet_console):  
    try:
        status = main(dataroot, study, dataset,
                      force_preprocess, quiet_console)
        return status
    except:
        print('Problem in dataset {}'.format(dataset))
        return 'Exception'

def main(dataroot, study, dataset, force_preprocess, quiet_console):
    ...
    [load files, do signal processing, make plots, save .pkl file]
    ...
    return 'Done'

我需要将图块作为预处理的一部分。 (从保存的pkl文件中绘图是可能的,但需要重新执行大部分代码。)我希望其他人遇到类似的事情,并且知道解决方法。

谢谢,

德里克

Python 2.7,OSX High Sierra,刚刚使用anaconda更新了我的所有软件包。

1 个答案:

答案 0 :(得分:2)

如果你有matplotlib set使用交互式后端,那么这些图将创建需要关闭主循环才能继续的窗口。

要避免这种情况,请使用非交互式后端,例如“agg”。

您可以在matplotlibrc文件中设置参数。

你也可以之前导入pyplot,你可以这样做:

import matplotlib
matplotlib.use('agg')