Python 多处理在绘图期间挂起

Python multiprocessing hangs during plotting

我 运行 使用 Python 的多处理模块的代码挂起,没有任何警告或错误。我想我已经将范围缩小到生成图的时间。 multiprocessing 和 matplotlib 之间是否存在一些不兼容问题?

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

连续处理。 preprocess.main_debug() 接收 path/filename/flags 和 returns 状态字符串('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 更新了我所有的包。

如果您将 matplotlib 设置为使用交互式后端,绘图将创建 windows 需要关闭主循环才能继续。

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

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

您还可以,在导入 pyplot 之前,您可以:

import matplotlib
matplotlib.use('agg')