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

除了其中一个之外,所有脚本都运行良好。有问题的人会去各种网站并抓取数据并将其存储在字典中。此代码整天运行酸洗和解酸字典,并在午夜停止。一个 cronjob 然后在第二天早上再次启动它。该脚本可以运行数周而不会出现问题,但大约每月一次,该脚本在尝试打开字典时由于 EOFError 而死。字典的大小通常约为 80 MB。我什至尝试在提取数据时在 SellerDict.close() 之前添加 SellerDict.flush() 以确保晚上被刷新。

有什么想法可能导致这种情况吗?Python 非常可靠,所以我认为这不是文件大小的原因。代码在死前运行了很长时间,这让我相信,也许字典中保存了一些导致这个问题的东西,但我不知道。

此外,如果您知道除了 pickle 之外还有更好的方法来保存字典,我愿意接受选择。就像我之前说的,字典不断地被打开和关闭。只是为了澄清,只有一个程序会使用同一个字典,所以这个问题不是由几个程序试图访问同一个字典引起的。

更新:

这是我从日志文件中获得的回溯。

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 并尝试 unpickle 或加载数据时,该进程将失败并声明此 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 回答