Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python matplotlib savefig线程安全吗?_Python_Multithreading_Matplotlib_Plot - Fatal编程技术网

Python matplotlib savefig线程安全吗?

Python matplotlib savefig线程安全吗?,python,multithreading,matplotlib,plot,Python,Multithreading,Matplotlib,Plot,我有一个内部分布式计算库,我们一直使用它来进行并行计算工作。在对进程进行分区之后,它们运行数据加载和计算步骤,然后以“保存”步骤结束。通常这涉及到将数据写入数据库表 但是对于一个特定的任务,我需要每个进程的输出是一个带有一些数据图的.png文件。总共有95个进程,所以有95个 在我的“保存”步骤(在每个进程上执行)中,我有一些非常简单的代码,它使用matplotlib的boxplot函数生成一个方框图,还有一些代码使用savefig将其写入一个.png文件,该文件具有基于该进程中使用的特定数据的

我有一个内部分布式计算库,我们一直使用它来进行并行计算工作。在对进程进行分区之后,它们运行数据加载和计算步骤,然后以“保存”步骤结束。通常这涉及到将数据写入数据库表

但是对于一个特定的任务,我需要每个进程的输出是一个带有一些数据图的.png文件。总共有95个进程,所以有95个

在我的“保存”步骤(在每个进程上执行)中,我有一些非常简单的代码,它使用matplotlib的
boxplot
函数生成一个方框图,还有一些代码使用
savefig
将其写入一个.png文件,该文件具有基于该进程中使用的特定数据的唯一名称

但是,我偶尔会看到输出,其中两组或多组数据似乎被写入同一个输出文件,尽管名称是唯一的

matplotlib在制作方框图或保存图形时是否使用临时文件保存?如果是,它是否总是使用相同的临时文件名(从而导致写冲突)?我已经使用
strace
运行了我的进程,但看不到任何明显类似于从matplotlib写入临时文件的内容

import pandas
import numpy as np
import matplotlib.pyplot as plt

def plot_category_data(betas, category_name):
    """
    Function to organize beta data by date into vectors and pass to box plot
    code for producing a single chart of multi-period box plots.
    """
    beta_vector_list = []
    yms = np.sort(betas.yearmonth.unique())
    for ym in yms:
        beta_vector_list.append(betas[betas.yearmonth==ym].Beta.values.flatten().tolist())
    ###

    plot_output = plt.boxplot(beta_vector_list)
    axs = plt.gcf().gca()
    axs.set_xticklabels(betas.FactorDate.unique(), rotation=40, horizontalalignment='right')
    axs.set_xlabel("Date")
    axs.set_ylabel("Beta")
    axs.set_title("%s Beta to BMI Global"%(category_name))
    axs.set_ylim((-1.0, 3.0))

    return plot_output
### End plot_category_data

def save(self):
    """
    Make calls to store the plot to the desired output file.
    """
    out_file = self.output_path + "%s.png"%(self.category_name)
    fig = plt.gcf()
    fig.set_figheight(6.5)
    fig.set_figwidth(10)
    fig.savefig(out_file, bbox_inches='tight', dpi=150)
    print "Finished and stored output file %s"%(out_file)
    return None
### End save
如何确保这是线程安全的?我当然希望并行地进行文件保存,因为我希望大大扩展output.png的数量,因此首先存储所有数据,然后串行执行plot/save部分的选项是非常不可取的

我不可能重现我们正在使用的完全并行的基础设施,但下面是被调用以创建绘图句柄的函数,然后是被调用以保存绘图的函数。为了解决这个问题,您应该假设线程安全与我们的分布式库无关。我们知道这不是源于我们的代码,多年来,我们的多处理作业一直使用这种代码,而没有像这样的线程问题(特别是对于我们不能直接控制的东西,比如matplotlib中的任何临时文件)


在这两个函数中,您调用的是
plt.gcf()
。每次使用
plt.figure()
绘图时,我都会尝试生成一个新图形,并显式引用该图形,这样就可以完全避开整个问题。

不,这些过程使用的内存不同
gcf()
gca()
参考内存中最新的绘图。。。因此,不同的实例无法看到彼此的内存中图形等。您能否验证matplotlib是否使用特定的临时文件来引用相同的当前图形?这将是在不同处理器之间产生问题的唯一方法。对不起,我以为你在说你在使用线程。即便如此,你有什么理由需要使用最新鲜的情节吗?没有特别的原因,但这不应该有什么区别。我正在使用线程和多处理。每个进程只有一个绘图,因此
gcf
应该只引用该绘图。我可以很容易地更改它以提供特定的图形句柄,但我更担心的是它在事务的
savefig
部分,除非有文件证明有理由认为
gcf
使用临时文件,这些文件会在不同的进程中被覆盖。