如何提前退出 __enter__ 并跳过 Python 中的 with 块?
How can I prematurely exit __enter__ and skip the with block in Python?
如果 __enter__
函数中存在错误,我一直在尝试找到一种方法来完全 exit/skip 我的 with BaseObject.ethernet_device(ip_addr) as obj:
代码块。
在下面的示例中,如果该设备不在网络中,则会出现这种情况。任何解决方案都有望取代 return None
行(我知道这不是必需的)。
class BaseObject(object):
@class_method
def ethernet_device(cls, host:str):
return EthernetDevice(host)
def __enter__(self):
return self
def __exit__(self, *args):
self._inst.close()
class EthernetDevice(BaseObject):
def __init__(self, host: str):
self._host = host
def __enter__(self):
try:
socket.inet_ntoa(self._host)
ip_addr = self._host
except:
logger.debug(f'{self._host} is not a valid IP address: trying as a hostname')
try:
logger.debug(f"Trying to resolve host {self._host}")
ip_addr = socket.gethostbyname(self._host)
except socket.gaierror:
logger.error(f"Couldn't resolve host {self._host}")
return None
self._inst = vxi11.Instrument(ip_addr)
return super().__enter__()
用法:
with BaseObject.ethernet_device(ip_addr) as device:
print(device.id)
这里唯一的答案是在 __enter__
中引发异常;如果 __enter__
无异常退出,__exit__
将始终 运行(假设您没有设法对解释器进行段错误或调用 os._exit
故意终止程序而没有 运行宁清理块)。
这将使调用者捕获异常(用 try
/except
包装 with
)以防止它在程序的其余部分冒泡。
如果调用者不喜欢为此缩进整个块,他们可以使用 an ExitStack
缩小范围,但这是唯一可用的“改进”,它仍然需要 __enter__
引发异常:
with contextlib.ExitStack() as stack:
try:
device = stack.enter_context(BaseObject.ethernet_device(ip_addr)
except CustomException:
return # Or do something else to skip remaining code
# Rest of code using device
# device is cleaned up for you if it exists
如果 __enter__
函数中存在错误,我一直在尝试找到一种方法来完全 exit/skip 我的 with BaseObject.ethernet_device(ip_addr) as obj:
代码块。
在下面的示例中,如果该设备不在网络中,则会出现这种情况。任何解决方案都有望取代 return None
行(我知道这不是必需的)。
class BaseObject(object):
@class_method
def ethernet_device(cls, host:str):
return EthernetDevice(host)
def __enter__(self):
return self
def __exit__(self, *args):
self._inst.close()
class EthernetDevice(BaseObject):
def __init__(self, host: str):
self._host = host
def __enter__(self):
try:
socket.inet_ntoa(self._host)
ip_addr = self._host
except:
logger.debug(f'{self._host} is not a valid IP address: trying as a hostname')
try:
logger.debug(f"Trying to resolve host {self._host}")
ip_addr = socket.gethostbyname(self._host)
except socket.gaierror:
logger.error(f"Couldn't resolve host {self._host}")
return None
self._inst = vxi11.Instrument(ip_addr)
return super().__enter__()
用法:
with BaseObject.ethernet_device(ip_addr) as device:
print(device.id)
这里唯一的答案是在 __enter__
中引发异常;如果 __enter__
无异常退出,__exit__
将始终 运行(假设您没有设法对解释器进行段错误或调用 os._exit
故意终止程序而没有 运行宁清理块)。
这将使调用者捕获异常(用 try
/except
包装 with
)以防止它在程序的其余部分冒泡。
如果调用者不喜欢为此缩进整个块,他们可以使用 an ExitStack
缩小范围,但这是唯一可用的“改进”,它仍然需要 __enter__
引发异常:
with contextlib.ExitStack() as stack:
try:
device = stack.enter_context(BaseObject.ethernet_device(ip_addr)
except CustomException:
return # Or do something else to skip remaining code
# Rest of code using device
# device is cleaned up for you if it exists