python-3.x 如何正确地覆盖上下文管理器?

eufgjt7s  于 2023-11-20  发布在  Python
关注(0)|答案(1)|浏览(126)

这是这个one的后续问题。
我试图创建一个新的上下文管理器,以偶尔关闭一个现有的上下文管理器。这个例子重新定义了一个新的上下文管理器,这样被覆盖的上下文管理器就不会在新的上下文管理器no_autocast中做任何事情。但是我在调用重新定义的上下文管理器with autocast("cuda", dtype=torch.float16):时遇到了错误:'NoneType' object is not callable。有什么办法解决这个问题吗?

import torch
from torch import autocast
print(autocast)
class no_autocast():
    def __init__(self):
        self.autocast = None

    def __enter__(self, *args, **kwargs):
        global autocast
        self.autocast = autocast
        autocast = no_autocast.do_nothing(*args, **kwargs)

    def __exit__(self, exc_type, exc_value, exc_traceback):
        global autocast
        autocast = self.autocast
   
    def do_nothing(*args, **kwargs):
        pass

with no_autocast():
    print("outer 0:", torch.is_autocast_enabled())
    #torch.set_autocast_enabled(False)
    print("outer 1:", torch.is_autocast_enabled())
    with autocast("cuda", dtype=torch.float16):
        def func(a, b): return a @ b
        print("inner ", torch.is_autocast_enabled())

字符串

mepcadol

mepcadol1#

你可能不应该使用全局变量来实现这个目的。这样一来,问题就出在这一行:

autocast = no_autocast.do_nothing(*args, **kwargs)

字符串
你调用do_nothing方法,它返回None。所以你将autocast设置为None
你可能想做:

autocast = no_autocast.do_nothing


但是您应该为它分配一个上下文管理器,而不仅仅是一个什么都不做的方法。

import contextlib

@contextlib.contextmanager
def do_nothing(*args, **kwargs):
    yield

相关问题