大きなCSVファイルをインポートし、ファイル内の各Wordの出現回数をカウントし、そのカウントを別のCSVファイルにエクスポートするPythonスクリプトがあります。
しかし、起こっていることは、そのカウント部分が終了し、エクスポートが開始されると、用語でKilled
と言うことです。
これはメモリの問題だとは思いません(もしそうなら、Killed
ではなく、メモリエラーが発生すると思います)。
プロセスに時間がかかりすぎている可能性がありますか?もしそうなら、これを回避できるようにタイムアウト期間を延長する方法はありますか?
コードは次のとおりです。
csv.field_size_limit(sys.maxsize)
counter={}
with open("/home/alex/Documents/version2/cooccur_list.csv",'rb') as file_name:
reader=csv.reader(file_name)
for row in reader:
if len(row)>1:
pair=row[0]+' '+row[1]
if pair in counter:
counter[pair]+=1
else:
counter[pair]=1
print 'finished counting'
writer = csv.writer(open('/home/alex/Documents/version2/dict.csv', 'wb'))
for key, value in counter.items():
writer.writerow([key, value])
Killed
はfinished counting
が印刷された後に発生し、完全なメッセージは次のとおりです。
killed (program exited with code: 137)
終了コード137(128 + 9)は、シグナル9(SIGKILL
)を受信したためにプログラムが終了したことを示します。これは、killed
メッセージについても説明しています。問題は、なぜそのシグナルを受信したのですか?
最も可能性の高い理由は、おそらく、プロセスが、使用を許可されているシステムリソースの量の制限を超えたことです。 OSと設定によっては、開いているファイルが多すぎたり、ファイルシステム領域が多すぎたり、他の何かを使用している可能性があります。最も可能性が高いのは、プログラムが使用しているメモリが多すぎることです。システムは、メモリ割り当てが失敗し始めたときに物事が壊れる危険を冒すのではなく、メモリを過剰に使用しているプロセスにキル信号を送信しました。
前にコメントしたように、finished counting
を印刷した後にメモリ制限に達する可能性がある1つの理由は、最終ループでcounter.items()
を呼び出すと、辞書のすべてのキーと値を含むリストが割り当てられるためです。辞書に大量のデータがある場合、これは非常に大きなリストになります。考えられる解決策は、ジェネレーターであるcounter.iteritems()
を使用することです。リスト内のすべてのアイテムを返すのではなく、はるかに少ないメモリ使用量でアイテムを反復処理できます。
したがって、最終ループとしてこれを試してみることをお勧めします。
for key, value in counter.iteritems():
writer.writerow([key, value])
Python 3では、items
はPython 2のバージョンと同じオーバーヘッドのない「辞書ビュー」オブジェクトを返します。 iteritems
を置き換えるため、後でPythonバージョンをアップグレードすると、ループが元の状態に戻ります。
スタックとヒープの2つのストレージ領域が関係します。スタックはメソッド呼び出しの現在の状態(ローカル変数と参照)が保持される場所であり、ヒープはオブジェクトが格納される場所です。 再帰とメモリ
counter
dictにはヒープ領域のメモリを消費しすぎるキーが多すぎると思うので、PythonランタイムはOutOfMemory例外。
保存するには、巨大なオブジェクトを作成しないでください。 カウンター。
1.StackOverflow
あまりにも多くのローカル変数を作成するプログラム。
Python 2.7.9 (default, Mar 1 2015, 12:57:24)
[GCC 4.9.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> f = open('stack_overflow.py','w')
>>> f.write('def foo():\n')
>>> for x in xrange(10000000):
... f.write('\tx%d = %d\n' % (x, x))
...
>>> f.write('foo()')
>>> f.close()
>>> execfile('stack_overflow.py')
Killed
2.OutOfMemory
巨大なdict
を作成するプログラムに含まれるキーが多すぎます。
>>> f = open('out_of_memory.py','w')
>>> f.write('def foo():\n')
>>> f.write('\tcounter = {}\n')
>>> for x in xrange(10000000):
... f.write('counter[%d] = %d\n' % (x, x))
...
>>> f.write('foo()\n')
>>> f.close()
>>> execfile('out_of_memory.py')
Killed
時間がかかるからといって、何もプロセスを停止させているのではないかと思います。強制終了とは、外部から何かがプロセスを終了したことを意味しますが、この場合、Ctrl-Cを押すことはおそらくありません。キーボード割り込み例外でPythonが終了するからです。また、Pythonで問題が発生した場合、MemoryError例外が発生します。何が起こっているのかは、プロセスのクラッシュを引き起こすPythonまたは標準ライブラリコードのバグにぶつかっていることです。