2

ファイルが存在する場合、月と年を循環してファイルを相互に追加するために、次のスクリプトを実行しています。出力ファイルのサイズが約 600 MB になると予想されるより大きなデータセットでテストしました。ただし、メモリの問題が発生しています。まず、メモリの問題が発生するのは通常のことですか (私の PC には 8 GB の RAM があります)、どのようにこのメモリ スペースをすべて消費しているのかわかりません。

私が実行しているコード

import datetime,  os
import StringIO

stored_data = StringIO.StringIO()

start_year = "2011"
start_month = "November"
first_run = False

current_month = datetime.date.today().replace(day=1)
possible_month = datetime.datetime.strptime('%s %s' % (start_month, start_year), '%B %Y').date()
while possible_month <= current_month:
    csv_filename = possible_month.strftime('%B %Y') + ' MRG.csv'
    if os.path.exists(csv_filename):
        with open(csv_filename, 'rb') as current_csv:
            if first_run != False:
                next(current_csv)
            else:
                first_run = True
            stored_data.writelines(current_csv)
    possible_month = (possible_month + datetime.timedelta(days=31)).replace(day=1)
if stored_data:
    contents = stored_data.getvalue()
    with open('FullMergedData.csv', 'wb') as output_csv:
        output_csv.write(contents)

私が受け取るトラックバック:

Traceback (most recent call last):
  File "C:\code snippets\FullMerger.py", line 23, in <module>
    contents = stored_output.getvalue()
  File "C:\Python27\lib\StringIO.py", line 271, in getvalue
    self.buf += ''.join(self.buflist)
MemoryError

この問題を解決するために回避策を達成する方法、またはこのコードをより効率的にする方法についてのアイデア。どうもありがとう
AEA

編集1

alKid で提供されたコードを実行すると、次のトレースバックを受け取りました。

Traceback (most recent call last):
  File "C:\FullMerger.py", line 22, in <module>
    output_csv.writeline(line)
AttributeError: 'file' object has no attribute 'writeline'

に変更して上記を修正しましたがwritelines、それでも次のトレースを受け取りました。

Traceback (most recent call last):
  File "C:\FullMerger.py", line 19, in <module>
    next(current_csv)
StopIteration
4

2 に答える 2

5

ではstored_data、ファイル全体を保存しようとしていますが、ファイルが大きすぎるため、表示されているエラーが発生しています。

1 つの解決策は、ファイルを 1 行ごとに書き込むことです。600 MB 全体ではなく、1 行のデータのみをバッファーに格納するため、メモリ効率が大幅に向上します。

要するに、構造は次のようになります。

with open('FullMergedData.csv', 'a') as output_csv: #this will append  
# the result to the file.
    with open(csv_filename, 'rb') as current_csv:
        for line in current_csv:   #loop through the lines
            if first_run != False:
                next(current_csv)
                first_run = True #After the first line,
                #you should immidiately change first_run to true.
            output_csv.writelines(line)  #write it per line

問題を解決する必要があります。お役に立てれば!

于 2013-11-01T03:06:15.533 に答える
3

メモリエラーは、すべてのデータを書き込む前にバッファに保存するためです。ある開いているファイル オブジェクトから別のファイル オブジェクトに直接コピーするようなものを使用することを検討してくださいcopyfileobj。これは一度に少量のデータしかバッファリングしません。行ごとに行うこともできますが、これはほとんど同じ効果があります。

アップデート

を使用copyfileobjすると、ファイルを 1 行ずつ書き込むよりもはるかに高速になります。使用方法の例を次に示しますcopyfileobj。このコードは 2 つのファイルを開き、 が True の場合は入力ファイルの最初の行をスキップし、skip_first_lineそのファイルの残りを出力ファイルにコピーします。

skip_first_line = True

with open('FullMergedData.csv', 'a') as output_csv:
    with open(csv_filename, 'rb') as current_csv:
        if skip_first_line:
            current_csv.readline()
        shutil.copyfileobj(current_csv, output_csv)

を使用している場合は、代わりにcopyfileobjを使用することに注意してください。これは、ファイル オブジェクトを反復処理するとファイルの一部がバッファリングされるためです。これは通常非常に便利ですが、この場合は不要です。詳細はこちらcurrent_csv.readline()next(current_csv)

于 2013-11-01T03:01:27.720 に答える