5

サーバー上で、さまざまな辞書をピクルおよびアンピクルするスクリプトをいくつか実行しています。以下に示すように、それらはすべて酸洗に同じ基本コードを使用します。

SellerDict=open('/home/hostadl/SellerDictkm','rb')
SellerDictionarykm=pickle.load(SellerDict)
SellerDict.close()

SellerDict=open('/home/hostadl/SellerDictkm','wb')
pickle.dump(SellerDictionarykm,SellerDict)
SellerDict.close()

スクリプトの 1 つを除いて、すべてのスクリプトが正常に実行されます。問題のあるものは、さまざまな Web サイトにアクセスしてデータをスクレイピングし、辞書に格納します。このコードは、一日中酸洗い辞書と解凍辞書を実行し、真夜中に停止します。cronjob は、翌朝に再び開始します。このスクリプトは問題なく数週間実行できますが、月に約 1 回、辞書を開こうとしたときに EOFError が原因でスクリプトが停止します。辞書のサイズは通常約 80 MB です。夜がフラッシュされていることを確認するためにデータをピクルするときに、SellerDict.close()の前にSellerDict.flush()を追加しようとさえしました。

これを引き起こしている可能性のあるアイデアはありますか?Python はかなりしっかりしているので、ファイルのサイズが原因ではないと思います。コードが死ぬ前に長い間正常に実行される場合、この問題の原因となっている辞書に何かが保存されている可能性があると思われますが、私にはわかりません。

また、ピクル以外の辞書を保存するためのより良い方法を知っている場合は、オプションを用意しています. 先ほど言ったように、辞書は常に開いたり閉じたりしています。明確にするために、同じ辞書を使用するのは 1 つのプログラムのみであるため、複数のプログラムが同じ辞書にアクセスしようとしても問題は発生しません。

アップデート:

ログファイルから取得したトレースバックを次に示します。

Traceback (most recent call last):
  File "/home/hostadl/CompileRecentPosts.py", line 782, in <module>
    main()
  File "/home/hostadl/CompileRecentPosts.py", line 585, in main
    SellerDictionarykm=pickle.load(SellerDict)
EOFError
4

2 に答える 2

10

したがって、これは実際にはメモリの問題であることが判明しました。コンピューターのRAMが不足し、データの選択を解除またはロードしようとすると、プロセスはこのEOFErrorの要求に失敗します。コンピューターのRAMを増やしましたが、これが再び問題になることはありませんでした。

すべてのコメントと助けてくれてありがとう。

于 2013-01-08T06:24:54.980 に答える
4

ロックを使用しない場合は次のようになります。

import pickle

# define initial dict
orig_dict={'foo':'one'}

# write dict to file
writedict_file=open('./mydict','wb')
pickle.dump(orig_dict,writedict_file)
writedict_file.close()

# read the dict from file
readdict_file=open('./mydict','rb')
mydict=pickle.load(readdict_file)
readdict_file.close()

# now we have new data to save
new_dict={'foo':'one','bar':'two'}
writedict_file=open('./mydict','wb')
#pickle.dump(orig_dict,writedict_file)
#writedict_file.close()

# but...whoops!  before we could save the data
# some other reader tried opening the file
# now they are having a problem
readdict_file=open('./mydict','rb')
mydict=pickle.load(readdict_file) # errors out here
readdict_file.close()

出力は次のとおりです。

python pickletest.py
Traceback (most recent call last):
  File "pickletest.py", line 26, in <module>
    mydict=pickle.load(readdict_file) # errors out here
  File "/usr/lib/python2.6/pickle.py", line 1370, in load
    return Unpickler(file).load()
  File "/usr/lib/python2.6/pickle.py", line 858, in load
    dispatch[key](self)
  File "/usr/lib/python2.6/pickle.py", line 880, in load_eof
    raise EOFError
EOFError

最終的に、一部の読み取りプロセスがピクルされたファイルを読み取ろうとしますが、書き込みプロセスは既に書き込み用に開いています。読み取りを試みる前に、別のプロセスが既にファイルを書き込み用に開いているかどうかを確認する方法があることを確認する必要があります。

非常に簡単な解決策については、Filelock の使用について説明しているこのスレッドをご覧ください

于 2012-04-21T22:47:59.963 に答える