通过函数调用(单个进程)访问ZODB对象时,如何防止ZODB FileStorage上的LockError

时间:2019-01-08 22:37:48

标签: python zodb file-storage

我在使用ZODB LockError时遇到问题,但是我相信我只能通过一个进程在数据库上进行操作。

我对项目的目标是仅拥有两个功能,load_project()save_project(),该功能允许用户加载Project对象,对其进行处理,然后与{ {1}},而用户不必直接与ZODB交互。有点像他们只是在处理文档并随其保存。

但是,我注意到我一直在获取save_project():可以加载对象,保存一次,但是随后每次尝试保存LockError时,我都会得到LockError。显然,对于ZODB的工作方式,我做错了或不了解。 如何防止这种LockError

SO上的所有其他LockError问题似乎都涉及多个过程。我正在通过Jupyter Notebook与代码进行交互,我相信这只是一个过程。当我遇到LockError时,我可以重新启动内核(从而开始一个新进程),加载项目,然后再次保存它。 但是后来,我无法再次保存它。

这是我从functions模块导入的两个函数的代码:

def save_project(project: BIMProject):
    """
    Commits the project to the ZODB; including opening and closing the connection
    """
    if not hasattr(project, "filename"):
        project.filename = input("Enter a filename (without extension):")
    if not hasattr(project, "filepath"):
        tk_root = Tk()
        tk_root.withdraw()
        project.filepath = filedialog.askdirectory(title="Please select a directory")

    filename = project.filename
    full_path = project.filepath + "/" + filename

    storage=FileStorage(full_path)
    db=ZODB.DB(storage)
    connection=db.open()
    root=connection.root()
    if 'project' in root:
        root.update({'project': project})
    else:
        root['project'] = project # reassign to change
    transaction.commit()
    connection.close()

def load_project():
    """
    Loads a project from a database file
    """
    tk_root = Tk()
    tk_root.withdraw()
    filepath = filedialog.askopenfilename(title="Please select a database file")

    storage = FileStorage(filepath)
    db = ZODB.DB(storage)
    connection = db.open()
    root = connection.root()
    project = copy.deepcopy(root["project"])
    connection.close()
    db.close()
    return project

任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:0)

因此,在我的头上碰壁了一天之后,我散步了,并决定一个对象而不是仅通过函数访问数据库,而是更适合维护与文件存储和数据库的连接。不完全是我所想像的,但是效果很好。

class LoaderSaver:
    """
    A 'hang around' object to use in conjunction with Project objects to save them
    in a ZODB FileStorage. Carries the ZODB storage, db, and connection objects once 
    they are opened.

    Only one Project file can be open at one time.
    """
    def __init__(self):
        self.storage = None
        self.db = None
        self.connection = None
        self.root = None

    def load(self):
        """
        Returns a Project object stored in a ZODB file storage. File selected by 
        user in a graphical 'file dialog' interface.
        """
        tk_root = Tk()
        tk_root.withdraw()
        filepath = filedialog.askopenfilename(title="Please select a database file")

        self.storage = FileStorage(filepath)
        self.db = ZODB.DB(self.storage)
        self.connection = self.db.open()
        self.root = self.connection.root()
        project = copy.deepcopy(self.root["project"])
        self.connection.close()
        return project

    def save(self, project: Project):
        """
        Commits the project to the ZODB
        """
        if not hasattr(project, "filename"):
            project.filename = input("Enter a filename (without extension):")
        if not hasattr(project, "filepath"):
            tk_root = Tk()
            tk_root.withdraw()
            project.filepath = filedialog.askdirectory(title="Please select a directory")

        filename = project.filename
        full_path = project.filepath + "/" + filename

        if not (self.storage and self.db):
            self.storage=FileStorage(full_path)
            self.db=ZODB.DB(self.storage)
        else:
            self.connection=self.db.open()
            self.root=self.connection.root()

        self.root['project'] = project
        transaction.commit()
        self.connection.close()