如何同时访问多个python/shelve数据库?

llycmphe  于 2023-02-26  发布在  Python
关注(0)|答案(2)|浏览(127)

我正在构建一个简单的程序,并发保存数据到不同的shelve数据库与多线程,但错误发生时,2线程调用shelve.open()(对于不同的文件):

import threading
import shelve
import time

def parallel_shelve(idx):
    print("thread {}: start".format(idx))
    with shelve.open("cache_shelve_{}".format(idx)) as db:
        time.sleep(4)
        db["0"] = 0
        db.close()
    print("thread {}: done".format(idx))

if __name__ == "__main__":
    threads = []
    for idx in range(2):
        threads += [threading.Thread(target=parallel_shelve, args=(idx,))]

    for idx in range(len(threads)):
        threads[idx].start()

    for idx in range(len(threads)):
        threads[idx].join()

完整日志:
x一个一个一个一个x一个一个二个x
如何修复它以同时访问不同的shelve文件?

5t7ly7z5

5t7ly7z51#

我只能发现dbm.open在第一次被调用时试图找到一个可用的dbm实现,如果这同时并行发生两次,就会发生一些神秘的事情(我无法解释)导致错误。
一种解决方法是在启动线程之前触发实现搜索,例如:

import dbm
try:
    dbm.open(None)
except TypeError:
    pass
amrnrhlw

amrnrhlw2#

从实验中,我发现这个bug只在创建新数据库时触发,在阅读/写现有数据库时也能正常工作。对我来说,最简单的解决方案似乎是在创建数据库时加一个锁:

import threading
import shelve
import time
from threading import Lock

def parallel_shelve(lock, idx):
    print("thread {}: start".format(idx))

    file_name = "cache_shelve_{}".format(idx)

    lock.acquire()
    with shelve.open(file_name) as db:
        db.clear()
    lock.release()

    with shelve.open(file_name) as db:
        time.sleep(1)
        db["0"] = 0

    print("thread {}: done".format(idx))

if __name__ == "__main__":
    threads = []
    lock = Lock()
    for idx in range(10):
        threads += [
            threading.Thread(target=parallel_shelve, args=(
                lock,
                idx,
            ))
        ]

    for idx in range(len(threads)):
        threads[idx].start()

    for idx in range(len(threads)):
        threads[idx].join()

相关问题