【问题标题】:How to prevent LockError on ZODB FileStorage when accessing ZODB objects through function calls (single process)通过函数调用访问ZODB对象时如何防止ZODB FileStorage出现LockError(单进程)
【发布时间】:2019-01-08 22:37:47
【问题描述】:

我在使用 ZODB LockError 时遇到问题,但我相信我只使用单个进程在数据库上运行。

我的项目的目标是只有两个函数,load_project()save_project(),它们允许用户加载 Project 对象,对其进行处理,然后使用 save_project() 间歇性保存它,而无需用户直接与 ZODB 交互。有点像他们只是在处理文档并随时保存。

但是,我注意到我一直收到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

任何帮助将不胜感激。

【问题讨论】:

    标签: python zodb file-storage


    【解决方案1】:

    所以,在碰壁一天后,我走了一圈,并决定与其单独通过函数访问数据库,不如使用对象更适合维护与文件存储和数据库的连接。与我想象的不太一样,但效果很好。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-27
      • 1970-01-01
      相关资源
      最近更新 更多