簡體   English   中英

腳本突然使用所有 RAM

[英]Script suddenly using all RAM

我有一個 python 腳本,用於將一些格式非常密集的 csv 文件轉換為我需要的另一種格式。 csv 文件非常大(3GB),所以我分塊讀取它們以避免使用所有 RAM(我正在使用的機器上有 32GB 的 RAM)。

奇怪的是,腳本使用幾 GB 的內存(根據 top 所說的大約 3GB)處理一個文件。

我完成該文件並加載下一個文件,再次分塊。 突然我使用 25GB,寫入交換,進程被殺死。 我不確定第一次和第二次迭代之間發生了什么變化。 我已經放入了一個 os.sleep(60) 試圖讓垃圾收集器趕上來,但它仍然從 ~10% 的內存到 ~85% 到終止進程。

這是腳本的主要部分:

for file in files:
    sleep(60)
    print(file)
    read_names = True
    count = 0
    for df in pd.read_csv(file, encoding= 'unicode_escape', chunksize=1e4, names=['all']):
        start_index = 0
        count += 1
        if read_names:
            names = df.iloc[0,:].apply(lambda x: x.split(';')).values[0]
            names = names[1:]
            start_index = 2
            read_names = False
        for row in df.iloc[start_index:,:].iterrows():
            data = row[1]
            data_list = data['all'].split(';')
            date_time = data_list[0]
            values = data_list[1:]
            date, time = date_time.split(' ')
            dd, mm, yyyy = date.split('/')
            date = yyyy + '/' + mm + '/' + dd
            for name, value in zip(names, values):
                try:
                    data_dict[name].append([name, date, time, float(value)])
                except:
                    pass
        if count % 5 == 0:
            for name in names:
                start_date = data_dict[name][0][1]
                start_time = data_dict[name][0][2]
                end_date = data_dict[name][-1][1]
                end_time = data_dict[name][-1][2]
                start_dt = start_date + ' ' + start_time
                end_dt = end_date + ' ' + end_time
                dt_index = pd.date_range(start=start_dt, freq='1S', periods=len(data_dict[name]))
                df = pd.DataFrame(data_dict[name], index=dt_index)
                df = df[3].resample('1T').mean().round(10)
                with open(csv_dict[name], 'a') as ff:
                    for index, value in zip(df.index, df.values):
                        date, time = str(index).split(' ')
                        to_write = f"{name}, {date}, {time}, {value}\n"
                        ff.write(to_write)

我能做些什么來更好地管理這個問題嗎? 我需要為這個任務循環超過 50 個大文件。

數據格式:輸入

time sensor1 sensor2 sensor3 sensor....
2022-07-01 00:00:00; 2.559;.234;0;0;0;.....
2022-07-01 00:00:01; 2.560;.331;0;0;0;.....
2022-07-01 00:00:02; 2.558;.258;0;0;0;.....

輸出

sensor1, 2019-05-13, 05:58:00, 2.559 
sensor1, 2019-05-13, 05:59:00, 2.560 
sensor1, 2019-05-13, 06:00:00, 2.558 

編輯:有趣的發現 - 我正在寫入的文件突然沒有被更新,如果寫入正常發生,它們應該在幾分鍾后。 當我檢查文件的尾部時,文件中的數據也沒有改變。 因此,我假設數據正在字典中積累並淹沒 RAM,這是有道理的。 現在要了解為什么寫作沒有發生。

編輯 2:更有趣的發現!! 該腳本在填滿 RAM 並崩潰之前運行良好的第一個 csv 和第二個 csv 的一大塊。 似乎 ram 問題從第二個文件開始,所以我跳過了處理那個文件,並且神奇地我運行的時間比到目前為止沒有內存問題的時間長。 這可能是破壞了某些東西的損壞數據。

給定file.csv看起來完全像:

time sensor1 sensor2 sensor3 sensor4 sensor5
2022-07-01 00:00:00; 2.559;.234;0;0;0
2022-07-01 00:00:01; 2.560;.331;0;0;0
2022-07-01 00:00:02; 2.558;.258;0;0;0

你做的遠不止這些,不使用正確的pandas方法會按時殺死你( iterrows基本上從來都不是最好的選擇)。 基本上,如果你手動循環一個 DataFrame,你可能做錯了。

但是,如果您遵循這種將其用作上下文管理器的模式,而不是將其視為迭代器(這是一種已棄用的方法),您將不會遇到內存問題。

files = ['file.csv']
for file in files:
    with open(file) as f:
        # Grab the columns:
        cols = f.readline().split()
        # Initialize the context-manager: 
        # You'll want a larger chunksize, 1e5 should even work.
        with pd.read_csv(f, names=cols, sep=';', chunksize=1) as chunks:
            for df in chunks:
                df[['date', 'time']] = df.time.str.split(expand=True)
                df = df.melt(['date', 'time'], var_name='sensor')
                df = df[['sensor', 'date', 'time', 'value']]
                df.to_csv(f'new_{file}', mode='a', index=False, header=False)

new_file.csv的輸出:

sensor1,2022-07-01,00:00:00,2.559
sensor2,2022-07-01,00:00:00,0.234
sensor3,2022-07-01,00:00:00,0.0
sensor4,2022-07-01,00:00:00,0.0
sensor5,2022-07-01,00:00:00,0.0
sensor1,2022-07-01,00:00:01,2.56
sensor2,2022-07-01,00:00:01,0.331
sensor3,2022-07-01,00:00:01,0.0
sensor4,2022-07-01,00:00:01,0.0
sensor5,2022-07-01,00:00:01,0.0
sensor1,2022-07-01,00:00:02,2.558
sensor2,2022-07-01,00:00:02,0.258
sensor3,2022-07-01,00:00:02,0.0
sensor4,2022-07-01,00:00:02,0.0
sensor5,2022-07-01,00:00:02,0.0

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM