2013-10-04 13 views
42

大規模なCSVファイルをインポートして、ファイル内の各単語の出現数を数え、その数を別の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]) 

そしてfinished countingが印刷された後Killedが発生し、完全なメッセージは次のとおりです。

killed (program exited with code: 137) 
+6

あなたが取得しているエラーメッセージの正確な内容を投稿してください。 –

+2

"kill"とは、プロセスが何らかの信号を受信して​​終了することを意味します。この場合、スクリプトと同時に発生しているので、破損したパイプである可能性が高く、プロセスは相手側で閉じられているファイルハンドルに対して読み書きしようとしています。 –

+1

'killされた'メッセージがどこから来たのかについての答えはありませんが、何らかのシステムのメモリ制限を超えているために、 'counter 'の代わりに' counter.iteritems() 'を使って修正できるかもしれません.items() 'を実行します。 Python 2では、 'items'は辞書内のキーと値のリストを返します。非常に大きい場合は、大量のメモリが必要になるかもしれません。対照的に、「iteritems」は、所与の時間に少量のメモリしか必要としないジェネレータである。 – Blckknght

答えて

55

終了コード137(128 + 9)は、信号9(SIGKILL)のためにプログラムが終了したことを示します。これは、killedメッセージについても説明します。問題は、なぜあなたはそのシグナルを受けたのですか?

おそらく、あなたのプロセスが、使用が許可されているシステムリソースの量の制限を超えている可能性があります。お使いのOSや設定によっては、開いているファイルが多すぎたり、ファイル容量が多すぎたり、何か他のものが使用されている可能性があります。あなたのプログラムが多すぎるメモリを使用していた可能性が最も高いです。メモリ割り当てが失敗したときに問題を起こす危険を冒すのではなく、システムはあまりにも多くのメモリを使用していたプロセスにkillシグナルを送りました。

先ほどコメントしたように、finished countingを印刷した後にメモリ制限に達する理由の1つは、最後のループでcounter.items()を呼び出すと、辞書のすべてのキーと値を含むリストが割り当てられるということです。辞書に大量のデータがあった場合、これは非常に大きなリストになるかもしれません。可能な解決策は、発電機であるcounter.iteritems()を使用することです。リスト内のすべての項目を返すのではなく、メモリ使用量を大幅に減らして繰り返し処理できます。

だから、私はあなたの最後のループとして、これをしようとすることをお勧めしたい:

for key, value in counter.iteritems(): 
    writer.writerow([key, value]) 

注Pythonの3、itemsでPythonの2のバージョンと同じオーバーヘッドを持っていない「辞書ビュー」オブジェクトを返すこと。それはiteritemsに置き換わるので、後でPythonのバージョンをアップグレードすると、ループは元の状態に戻ってしまうでしょう。

+1

正解ですが、辞書自体も多くのメモリを占有します。 OPは、一度にすべてを読み上げるのではなく、ファイルを段階的に読み込んで処理することを検討するべきです。 – Kevin

2

が、私はそれがかかるという理由だけで何がプロセスを殺している疑い長い時間。一般的には、外部から何かがプロセスを終了したことを意味しますが、Ctrl-Cを押すと、KeyboardInterrupt例外でPythonが終了する可能性があります。また、Pythonで問題があった場合は、MemoryError例外が発生します。起こっていることは、プロセスのクラッシュを引き起こすPythonや標準ライブラリコードのバグにぶつかっていることです。

+0

何らかの理由でPythonがコードのどこかに 'raise(SIGKILL)'を持っていない限り、クラッシュするバグは 'SIGKILL'を得るよりもsegfaultになる可能性が非常に高くなります。 – Kevin

14

スタックとヒープの2つの記憶領域があります。スタックはメソッド呼び出しの現在の状態(つまりローカル変数と参照)が保持され、ヒープはオブジェクトが格納される場所です。recursion and memory

は、私はあまりにも多くのキーは、PythonランタイムがのOutOfMemory例外が発生しますので、ヒープ領域のあまりに多くのメモリを消費しますcounter辞書にあるgues。

保存するには、巨大なオブジェクトを作成しないでください。 カウンタ

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があまりにも多くのキーが含まれてcreatsプログラム。

>>> 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 

参照
関連する問題