首页 > 解决方案 > 在上下文管理器中处理文件系统撤消操作的简洁有效的方法

问题描述

我正在为个人项目开发资产管理系统。我的问题是如何干净有效地处理 python 中的文件系统操作,以便在出现问题时可以回滚或撤消更改。

一个典型的操作可能看起来像这样

 try
   file system operation(s)
   update database
 except Exceptions
   undo file system operations already performed
   rollback database transaction
   handle exceptions

文件系统操作可以是创建、复制、链接和删除文件/目录

我的想法是为文件系统操作和数据库管理提供一个上下文管理器。执行将是这样的:

# create new asset
with FileSystemCM as fs, DatabaseCM as db:

    fs.create_dir(path_to_asset)
    fs.create_file(path_to_a_file_this_asset_needs)
    db.insert('Asset_Table', asset_name)

现在,例如 db.insert 失败,FileSystemCM 删除新创建的文件和新创建的目录,并且 DatabaseCM 回滚 db 事务

我的 FileSystemCM 实现的一个简单方法是这样的:

class FileSystemCM(object):
    """ File System Context Manager """

    def __init__(self):

        self.undo_stack = [] # list of (fn, args, kwargs)

    def __enter__(self):

        return self

    def __exit__(self, exception_type, exception_val, traceback):

        if exception_type:
            # pop undo actions off the stack and execute
            while self.undo_stack:
                undo_fn, args, kwargs = self.undo_stack.pop()
                undo_fn(*args, **kwargs)

    def create_dir(self, dir_path):

        create_file(dir_path)
        self.undo_stack.append((remove_dir, [dir_path], {'force': True}))

    def create_file(self, file_path):

        create_file(file_path)
        self.undo_stack.append((remove_file, [file_path], {'force': True}))

有更好的方法吗?在某些情况下,此实现无法处理,我可以使用反馈

标签: pythonassets

解决方案


我的意思是这是评论,但它太长了,不适合评论部分。首先让我说这听起来是一个非常有趣的项目(至少在我看来)。

前一段时间(我不记得在哪里)我读过一篇关于实现撤消/重做功能的文章,他们所做的是维护两个独立的堆栈(一个用于撤消,一个用于重做)。当用户执行一个动作时,一对带有参数的动作/它的反转被推入撤消堆栈。每当用户执行撤消操作时,都会执行该对的反向操作,然后将该对移动到重做堆栈中,当执行重做操作时,执行该对的操作并将该对返回到撤消堆栈.

每当用户执行新操作时,重做堆栈就会被清除。这种方法的唯一缺点是不可逆转的动作。我能想到的一种方法是使用某种事件溯源模式来保持系统的整个状态及其差异。这可能看起来非常低效,但它通常用于软件中。


推荐阅读