Два варианта context manager для timeout-обёртки. Какой защищён от потенциальных
ошибок при исключениях?
middle
correct_vs_wrong
#199
Вариант 1
import signal
class Timeout:
def __init__(self, seconds):
self.seconds = seconds
def __enter__(self):
signal.alarm(self.seconds)
def __exit__(self, *args):
signal.alarm(0)
with Timeout(5):
do_something()
Вариант 2
from contextlib import contextmanager
import signal
class TimeoutError(Exception):
pass
@contextmanager
def timeout(seconds: int):
def handler(signum, frame):
raise TimeoutError(f"after {seconds}s")
old = signal.signal(signal.SIGALRM, handler)
signal.alarm(seconds)
try:
yield
finally:
# Восстанавливаем старый handler и снимаем alarm —
# даже если внутри `with` упало.
signal.alarm(0)
signal.signal(signal.SIGALRM, old)
with timeout(5):
do_something()
Чтобы решить вопрос и сохранить попытку — войди.