可以创建一个上下文敏感的Python上下文管理器来保存、修改和恢复状态吗?

4 投票
2 回答
4232 浏览
提问于 2025-04-16 23:09

我有一对 Python 函数,它们可以在两个值之间切换一个全局变量。我想把它们改造成上下文管理器,这样我就可以在 with 代码块中使用它们,在代码块内部设置变量,然后在代码块结束后恢复它。下面是我想要的效果:

>>> MODE
'user'
>>> mode_sudo()  # Sets MODE to 'sudo'...
>>> MODE
'sudo'
>>> mode_user()  # Sets MODE to 'user'...
>>> MODE
'user'
>>> with mode_sudo():
...    print MODE
'sudo'
>>> MODE
'user'

这样的组合体可能实现吗?

更新:为了更清楚,这里是仅使用上下文管理器的实现:

from contextlib import contextmanager

@contextmanager
def mode_sudo():
    global MODE
    old_mode = MODE
    MODE = 'sudo'
    yield
    MODE = old_mode

@contextmanager
def mode_user():
    global MODE
    old_mode = MODE
    MODE = 'user'
    yield
    MODE = old_mode

如果不使用 with 关键字来调用这些函数,它们会返回一个生成器。有没有办法让这两个函数在普通调用和上下文管理器中都能实现切换模式的效果呢?

2 个回答

2

简单的方法:

from contextlib import contextmanager
@contextmanager
def mode_user():
    global MODE
    old_mode = MODE
    MODE = "user"
    yield
    MODE = old_mode

对于 mode_sudo() 也是一样的。想了解更多细节,可以查看 这个文档。其实这就是一个简化的方式,用来代替“定义一个实现了 __enter____exit__ 的类”的复杂过程。

8

这样做:

class mod_user:

    def __init__(self):
        global MODE
        self._old_mode = MODE
        MODE = "user"

    def __enter__(self):
        pass

    def __exit__(self, *args, **kws):
        global MODE
        MODE = self._old_mode

MODE = "sudo"

with mod_user():
    print MODE  # print : user.

print MODE  # print: sudo.

mod_user()
print MODE   # print: user.

撰写回答