Python 在上下文管理器中处理文件系统撤消操作的干净高效的方法

Python 在上下文管理器中处理文件系统撤消操作的干净高效的方法,python,assets,Python,Assets,我正在为一个个人项目开发一个资产管理系统。我的问题是如何在python中干净高效地处理文件系统操作,以便在出现问题时可以回滚或撤消更改 典型的操作可能是这样的 try file system operation(s) update database except Exceptions undo file system operations already performed rollback database transaction handle excepti

我正在为一个个人项目开发一个资产管理系统。我的问题是如何在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)
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}))
现在,如果例如db.insert失败,FileSystemCM将删除新创建的文件和新创建的目录,DatabaseCM将回滚db事务

实现FileSystemCM的简单方法如下:

# 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)
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}))
有没有更好的方法?有些情况下,此实现无法处理,我可以使用反馈

  • 删除文件。我的想法是将要删除的文件移动到临时位置(或创建tmp硬链接),如果一切正常,则删除临时文件或链接,否则将其还原。但这可能导致以下情况

  • __退出__________________________________________


我的意思是作为一个评论,但它太长,无法放在评论部分。让我首先说,这听起来是一个非常有趣的项目(至少对我来说是这样)

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

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