Python,奇怪的内存消耗行为

Python,奇怪的内存消耗行为,python,python-3.x,pickle,Python,Python 3.x,Pickle,我有一个包含数千个.pkl文件的文件夹,每个文件都包含一个对象元组列表。较大的文件为8GB,较小的文件为1KB(空列表)。我正在遍历这些文件并分别加载每个.pkl。因此,我应该得到的最大内存消耗应该是较大的.pkl文件。然而,它的RAM容量上升到了65 Gb,我不知道为什么 在下面的代码中,我提供了创建和读取pickle文件的函数,以及在特定文件夹中调用的绘图函数。我没有提供所使用的所有函数,但它们不应该是这个问题背后的原因 原因:PB等函数只对文件名、字符串起作用。=>低内存消耗。 PB只是一

我有一个包含数千个
.pkl
文件的文件夹,每个文件都包含一个对象元组列表。较大的文件为8GB,较小的文件为1KB(空列表)。我正在遍历这些文件并分别加载每个.pkl。因此,我应该得到的最大内存消耗应该是较大的
.pkl
文件。然而,它的RAM容量上升到了65 Gb,我不知道为什么

在下面的代码中,我提供了创建和读取pickle文件的函数,以及在特定文件夹中调用的绘图函数。我没有提供所使用的所有函数,但它们不应该是这个问题背后的原因

原因:PB等函数只对文件名、字符串起作用。=>低内存消耗。 PB只是一个值,因此列表距离不应太大

导入操作系统
进口腌菜作为腌菜
从matplotlib导入pyplot作为plt
def写入解决方案(解决方案、文件夹路径、文件名):
"""
函数从解决方案列表中写入pickle文件。
此函数覆盖任何现有文件。
"""
打开(连接(文件夹路径、文件名),“wb”)作为输出:
pickle.dump(解决方案,输出,-1)
def读取解决方案(文件夹路径、文件名):
"""
函数读取pickle文件并返回解决方案列表。
"""
以open(连接(文件夹路径、文件名),“rb”)作为输入:
解决方案=pickle.load(输入)
返回解决方案
def绘图\解决方案\空间\线\详细信息(文件夹、输出、N、最大pb、文件=无):
"""
在输入和绘图中使用函数taking.pkl。
"""
如果文件==无:
#加载所有的.pkl文件
files=os.listdir(文件夹)
files=[elt对于文件中的elt,如果elt[len(elt)-4:][=”.pkl“]
数据=dict()
对于范围(2,N+1)内的i:
数据[i]=[list(),list(),list(),list(),list(),list()]
对于文件中的文件:
item=读取解决方案(文件夹、文件)
nfo=文件名\读卡器(文件)
n=len(nfo[0])
所需_pb=pb(文件)
如果长度(项目)==0:
数据[n][3]。追加(1)
数据[n][2]。追加(所需的\u pb)
其他:
数据[n][1]。追加(1.1)
数据[n][0]。追加(所需的\u pb)
#实际最接近PB的计算
距离=[abs(PB(文件名(elt[0]))-项目中elt的期望值]
i=距离。索引(最小(距离))
plot_sol=项目[i][0]
实际值=pb(文件名(绘图)
#急性铅中毒图
数据[n][5]。追加(1.2)
数据[n][4]。追加(实际值)
空=列表()
对于范围(2,N+1)内的i:
如果len(数据[i][0])==0和len(数据[i][2])==0:
空。追加(i)
对于空中的elt:
del数据[elt]
#创建图形
f、 ax=plt.子批次(len(数据),sharex=True,sharey=True,figsize=(10,5))
f、 子批次调整(hspace=0)
plt.setp([a.getxticklabels(),用于f轴中的a[:-1]],visible=False)
对于f轴中的a轴:
a、 勾选参数(
axis='y',#更改适用于x轴
哪个class='tware',#主要和次要蜱虫都受到影响
左class='False',
对='假',
labelleft='False')#左边缘的标签已关闭
#收缩轴
box=a.获取位置()
a、 设置_位置([box.x0,box.y0,box.width*0.9,box.height])
#在最大预算处添加垂直线
a、 axvline(x=max_pb,线型='--',lw=0.4,color=“黑色”)
如果len(数据)>1:
对于范围内的i(len(数据)):
key=list(data.keys())[i]
X=数据[键][0]
Y=数据[键][1]
X2=数据[键][2]
Y2=数据[键][3]
X3=数据[键][4]
Y3=数据[键][5]
散度(X,Y,s=3)
散度(X2,Y2,s=3,color=“crimson”)
散度(X3,Y3,s=3,color=“teal”)
ax[i].set_ylim(0.8,1.4)
ax[i].set_ylabel(“{}信号”。格式(键))
ax[i].文本(1.01,0.6,“带解决方案的Nb:\n{}).格式(len(X)),fontsize=8,transform=ax[i].转换)

ax[i].text(1.01,0.2,“无解的Nb):\n{}.format(len([x代表X2中的x,如果x),您的错误是假设大小相等。pickle中的整数略多于所需的字节数。但内存中的整数(一些小数字无法承受的例外情况)约为28字节


这就是为什么人们通常会使用numpy来保存数据的原因,因为它是固定大小的数字类型的紧凑数组。

你已经看到这个问题了吗?@ChatterOne好的,这是一个简单的问题……我不知道我实际上是如何通过这篇文章的。非常感谢你指出它的x')另外,正如在另一个问题的评论中所建议的,您可以看一看,它允许您逐个读取pickle中的元素,而不是同时将它们全部加载到内存中。@ChatterOne确实,我在编写程序时不知道这种可能性……这将引起巨大的变化,但可能是一个解决方案:/@ChatterOne顺便说一句,你给我的链接似乎很旧。代码总是会引发类型错误(即使有给定的示例):write()参数必须是str,而不是bytes。我的文件存储以下数据:
[(S1,S2,S3),(S4,S5,S6),…,(S7,S8,S9)]
其中
S
是一个自定义对象。如果知道每个文件包含一个列表,并且该列表可以是空的,也可以是千(百万)个列表,您将如何高效地存储此数据对象
S
的元组数?我可能会选择HDF5而不是pickle。希望我现在有一台功能强大的PC,可以打开大的.pkl文件(8 GB=>65 GB的RAM),但这很快就会给我带来问题…因为我不知道s的组成,我不能对它的不同表示发表评论。顺便说一句,HDF5不会影响这一点。出于其他原因,它可能是更好的选择(例如版本比较
import os
import _pickle as pickle
from matplotlib import pyplot as plt

def write_solutions(solutions, folder_path, file_name):
    """
    Function write a pickle file out of the solutions list.
    This function overwrites any existing file.
    """
    with open(join(folder_path, file_name), "wb") as output:
        pickle.dump(solutions, output, -1)

def read_solutions(folder_path, file_name):
    """
    Function reading a pickle file and returning the solutions list.
    """
    with open(join(folder_path, file_name), "rb") as input:
        solutions = pickle.load(input)
    return solutions

def plotting_solution_space_line_detailed(folder, output, N, max_pb, files = None):
    """
    Function taking .pkl in input and plotting.
    """
    if files == None:
        # Load all the .pkl files
        files = os.listdir(folder)
        files = [elt for elt in files if elt[len(elt)-4:] == ".pkl"]

    data = dict()
    for i in range(2, N+1):
        data[i] = [list(), list(), list(), list(), list(), list()]

    for file in files:
        item = read_solutions(folder, file)
        nfo = file_name_reader(file)
        n = len(nfo[0])
        desired_pb = PB(file)

        if len(item) == 0:
            data[n][3].append(1)
            data[n][2].append(desired_pb)

        else:
            data[n][1].append(1.1)
            data[n][0].append(desired_pb)

            # Computation of the actual closest PB
            distance = [abs(PB(file_namer(elt[0])) - desired_pb) for elt in item]
            i = distance.index(min(distance))
            plot_sol = item[i][0]
            actual_pb = PB(file_namer(plot_sol))

            # Plot of the acutal PB
            data[n][5].append(1.2)
            data[n][4].append(actual_pb)

    empty = list()
    for i in range(2, N+1):
        if len(data[i][0]) == 0 and len(data[i][2]) == 0:
            empty.append(i)

    for elt in empty:
        del data[elt]

    # Creates the figure
    f, ax = plt.subplots(len(data), sharex=True, sharey=True, figsize=(10,5))
    f.subplots_adjust(hspace=0)
    plt.setp([a.get_xticklabels() for a in f.axes[:-1]], visible=False)
    for a in f.axes:
        a.tick_params(
        axis='y',           # changes apply to the x-axis
        which='both',       # both major and minor ticks are affected
        left='False',
        right='False',
        labelleft='False')    # labels along the left edge are off

        # Shrink the axes
        box = a.get_position()
        a.set_position([box.x0, box.y0, box.width * 0.9, box.height])

        # Add a vertical line at the max budget
        a.axvline(x=max_pb, linestyle= '--',lw = 0.4, color = "black")

    if len(data) > 1:
        for i in range(len(data)):
            key = list(data.keys())[i]
            X = data[key][0]
            Y = data[key][1]
            X2 = data[key][2]
            Y2 = data[key][3]
            X3 = data[key][4]
            Y3 = data[key][5]
            ax[i].scatter(X, Y, s = 3)
            ax[i].scatter(X2, Y2, s = 3, color = "crimson")
            ax[i].scatter(X3, Y3, s = 3, color = "teal")
            ax[i].set_ylim(0.8, 1.4)
            ax[i].set_ylabel("{} Signals".format(key))
            ax[i].text(1.01, 0.6, "Nb with solution(s):\n{}".format(len(X)), fontsize=8, transform=ax[i].transAxes)
            ax[i].text(1.01, 0.2, "Nb without solution(s):\n{}".format(len([x for x in X2 if x <= max_pb])), fontsize=8, transform=ax[i].transAxes)

    else:
        key = list(data.keys())[0]
        X = data[key][0]
        Y = data[key][1]
        X2 = data[key][2]
        Y2 = data[key][3]
        X3 = data[key][4]
        Y3 = data[key][5]
        ax.scatter(X, Y, s = 3)
        ax.scatter(X2, Y2, s = 3, color = "crimson")
        ax.scatter(X3, Y3, s = 3, color = "teal")
        ax.set_ylim(0.8, 1.4)
        ax.set_ylabel("{} Signals".format(key))
        ax.text(1.01, 0.6, "Nb solutions:\n{}".format(len(X)), fontsize=12, transform=ax.transAxes)
        ax.text(1.01, 0.2, "Nb no solutions:\n{}".format(len([x for x in X2 if x <= max_pb])), fontsize=8, transform=ax.transAxes)

    f.text(0.5, 0.94, 'Solution space', ha='center')
    f.text(0.5, 0.04, 'PB', ha='center')
    f.text(0.04, 0.5, 'Number of signals', va='center', rotation='vertical')

    plt.savefig("{}.png".format(output), dpi = 500)
    plt.close()