在Python shelve.open上资源暂时不可用

时间:2018-09-18 07:25:38

标签: python concurrency shelve

我有一个执行以下操作的Python应用程序:

    为了使用with shelve.open(shelvefilename, flag='c')存储对象,
  • 每2-3分钟被另一个进程调用一次。
  • 由另一个进程每分钟很多次调用,以便使用with shelve.open(shelvefilename, flag='r')
  • 读取搁置的文件

问题在于,有时我会遇到_gdbm.error: [Errno 11] Resource temporarily unavailable错误:

   File "/path/to/myprog.py", line 755, in mymethod
    with shelve.open(shelvefilename, flag='r') as shlvfile:
  File "/usr/local/lib/python3.6/shelve.py", line 243, in open
    return DbfilenameShelf(filename, flag, protocol, writeback)
  File "/usr/local/lib/python3.6/shelve.py", line 227, in __init__
    Shelf.__init__(self, dbm.open(filename, flag), protocol, writeback)
  File "/usr/local/lib/python3.6/dbm/__init__.py", line 94, in open
    return mod.open(file, flag, mode)
_gdbm.error: [Errno 11] Resource temporarily unavailable

我的猜测是,发生这种情况是因为有时我已经打开了用于读取和写入操作的搁置文件,其定义为problematic

有什么办法可以在不干扰读取操作的情况下对搁置文件进行更新?

2 个答案:

答案 0 :(得分:1)

这更多是一个概念性问题。如果一个进程修改了文件中的数据,而另一个进程同时读取了该文件,则结果是无法预测的。

想象一下,您读取了文件的一部分,此时该部分值只写入了一半。读取将仅无法正确解析条目,并且可能无法解析所有后续条目。换句话说,它迟早会损坏。

我认为最好的方法是将“货架”集中在一个流程中或使用数据库。

答案 1 :(得分:1)

我只是在一个用于缓存汇率的小模块中搁置了这个问题。您可以使用python线程和全局threading.Lock()对象来解决此问题。

from threading import Lock
import shelve

mutex = Lock()

mutex.acquire()
db = shelve.open(db_name)
# write to db
db.close()
mutex.release()

此代码段和想法的原始来源可以在http://georg.io/2014/06/Python-Shelve-Thread-Safety上找到

threading.Lock()对象的工作方式是阻塞其他python线程,直到释放为止。参见https://docs.python.org/2/library/threading.html#lock-objects