Большинство решений для контекста времени ожидания используют сигналы.Но сигналы перезаписываются и остается только последний обработчик сигнала.Следствием этого является то, что вы не можете использовать контекст тайм-аута, если код уже находится в контексте тайм-аута (который мог быть запущен вами, другим разработчиком, библиотекой, фреймворком, кто знает?).
Итак,в основном мой упрощенный вариант использования таков:
with Timeout(1): #A
with Timeout(100): #B
sleep(10) #C
print('Fail')
Этот код никогда не должен печатать "Fail".Но каждая реализация Timeout (), которую я видел до сих пор, делает одно и то же:
- Timeout A запускает контекст тайм-аута
- Timeout B запускает новый контекст тайм-аута (перезаписывая Timeoutконтекст из A)
- Тайм-аут никогда не наступает, поскольку вычисления в C занимают менее 100 с
- Выполнение возобновляется без контекста тайм-аута и длится более 1 с
Предыдущий пример кажется немного глупым, но реальный вариант использования больше похож на:
with Timeout(30):
for a in list:
with Timeout(10):
heavy_computing(a)
Я не знаю длину «списка», я не хочу брать больше 10 секунд наэлемент списка и не более 30 с.
Итак, мой вопрос: какова будет лучшая реализация контекста Timeout (), который не использует сигнал и поддерживает встроенные контексты внутри контекстов?
Редактировать:
- Решение не должно быть поточно-ориентированным, просто безопасным из другого контекста времени ожидания с более высоким уровнем области видимости.
- Если возможноЯ бы предпочел растворЭто менее инвазивная возможность, так как я могу использовать ее для вызова библиотеки, которую я не писал.
Edit2:
Хорошо, небольшое пояснение относительно того, как я считаюТайм-аут.Для меня Timeout - это ненавязчивое решение для возврата частичного результата (или вообще никакого результата), если операция «черного ящика» занимает слишком много времени.Результат должен быть возвращен быстро, но может быть неполным.
def function(argument):
results = []
with Timeout(50):
for a in arguments:
with Timeout(20):
results.append(black_box(a))
return results
Если функция занимает более 50 с, выполнение прекращается и возвращается неполный результат.И если для black_box требуется более 10 секунд, он будет пропущен, чтобы перейти к следующему результату.
Пример: arguments = [a, b, c, d] black_box (a) берет 25 секунд и возвращает w black_box (b) берет 20 секунд и возвращает x black_box (c) берет 5 секунд и возвращает y black_box (d) берет 10 секунд и возвращает z результаты = [x, y]
объяснения: a заняло более 20 секунд и было пропущено b занятоНа 20 секунд больше (всего 40 секунд) и была успешно рассчитана c потребовалось 5 секунд больше (всего 45 секунд), но менее 50 секунд d было прервано из-за тайм-аута 50 секунд
Функция blackbox не знает, что онавызывается из контекста времени ожидания и не содержит кода, зависящего от времени ожидания.
Этот код является примером и может немного отличаться.Может быть, нам нужна попытка ... кроме как для обнаружения ошибок тайм-аута и т. Д. Но black_box нельзя изменить.