从上下文管理器中止 with 语句的执行
abort execution of with statement from context manager
我对 python 中的装饰器、上下文管理器等比较陌生。
基本上我想做如下的事情:
@contextmanager
def cd(to_dir):
from_dir = os.getcwd()
try:
os.chdir(os.path.expanduser(to_dir))
yield
except Exception:
log.error(traceback.format_exc())
log.error(f"Failed to cd into {to_dir} from {from_dir}")
finally:
os.chdir(from_dir)
我想像这样使用它:
with cd('here'):
...
...
...
我特别想确保如果 cd
到 here
失败时不会执行 with 语句的主体,这就是为什么我试图在上下文管理器中捕获异常并防止它来自 yield
ing。
然而,似乎 python 生成器必须 yield 否则我会收到如下错误:
raise RuntimeError("generator didn't yield") from None |
RuntimeError: generator didn't yield
如果 chdir 失败,我如何禁止执行 with
的主体?
我能想到的一个解决方案是:
@contextmanager
def cd(to_dir):
from_dir = os.getcwd()
try:
os.chdir(os.path.expanduser(to_dir))
yield True
except Exception:
log.error(traceback.format_exc())
log.error(f"Failed to cd into {to_dir} from {from_dir}")
yield False
finally:
os.chdir(from_dir)
然后使用如下:
with cd('here') as success:
if success:
....
....
然而,这确实需要在使用 with 语句的任何地方附加条件,因此在现有程序中的任何地方更改都不方便。另一个问题是,如果在 with
语句的主体内发生异常,它也会被 cd contextmanager 函数内的 except
子句捕获,从而导致有关 cd.[=21 失败的虚假错误=]
上下文管理器无法跳过上下文主体,除非引发错误。 context manager protocol 只允许 return 一个值绑定在正文中(as
的目标),但不表示跳过正文。因此,如果进入上下文可能会失败,要么 a) 不要抑制失败异常,要么 b) 用新异常替换失败异常。
@contextmanager
def cd(to_dir):
from_dir = os.getcwd()
# if this fails, the exception bubbles out of the context manager
os.chdir(os.path.expanduser(to_dir))
try:
yield
finally:
os.chdir(from_dir)
如果初始 os.chdir
失败,异常将“退出”with
语句处的上下文,而不进入正文。
我对 python 中的装饰器、上下文管理器等比较陌生。 基本上我想做如下的事情:
@contextmanager
def cd(to_dir):
from_dir = os.getcwd()
try:
os.chdir(os.path.expanduser(to_dir))
yield
except Exception:
log.error(traceback.format_exc())
log.error(f"Failed to cd into {to_dir} from {from_dir}")
finally:
os.chdir(from_dir)
我想像这样使用它:
with cd('here'):
...
...
...
我特别想确保如果 cd
到 here
失败时不会执行 with 语句的主体,这就是为什么我试图在上下文管理器中捕获异常并防止它来自 yield
ing。
然而,似乎 python 生成器必须 yield 否则我会收到如下错误:
raise RuntimeError("generator didn't yield") from None |
RuntimeError: generator didn't yield
如果 chdir 失败,我如何禁止执行 with
的主体?
我能想到的一个解决方案是:
@contextmanager
def cd(to_dir):
from_dir = os.getcwd()
try:
os.chdir(os.path.expanduser(to_dir))
yield True
except Exception:
log.error(traceback.format_exc())
log.error(f"Failed to cd into {to_dir} from {from_dir}")
yield False
finally:
os.chdir(from_dir)
然后使用如下:
with cd('here') as success:
if success:
....
....
然而,这确实需要在使用 with 语句的任何地方附加条件,因此在现有程序中的任何地方更改都不方便。另一个问题是,如果在 with
语句的主体内发生异常,它也会被 cd contextmanager 函数内的 except
子句捕获,从而导致有关 cd.[=21 失败的虚假错误=]
上下文管理器无法跳过上下文主体,除非引发错误。 context manager protocol 只允许 return 一个值绑定在正文中(as
的目标),但不表示跳过正文。因此,如果进入上下文可能会失败,要么 a) 不要抑制失败异常,要么 b) 用新异常替换失败异常。
@contextmanager
def cd(to_dir):
from_dir = os.getcwd()
# if this fails, the exception bubbles out of the context manager
os.chdir(os.path.expanduser(to_dir))
try:
yield
finally:
os.chdir(from_dir)
如果初始 os.chdir
失败,异常将“退出”with
语句处的上下文,而不进入正文。