Есть ли способ предотвратить перехват исключения SystemExit, вызванного из sys.exit()?

StackOverflow https://stackoverflow.com/questions/173278

Вопрос

В документах говорится, что вызов sys.exit() вызывает исключение SystemExit, которое может быть перехвачено на внешних уровнях.У меня есть ситуация, в которой я хочу окончательно и бесспорно выйти из тестового примера, однако модуль unittest перехватывает SystemExit и предотвращает выход.Обычно это здорово, но конкретная ситуация, с которой я пытаюсь справиться, заключается в том, что наша тестовая платформа обнаружила, что она настроена указывать на нетестовую базу данных.В этом случае я хочу завершить работу и предотвратить запуск любых дальнейших тестов.Конечно, поскольку unittest ловит SystemExit в ловушку и счастливо продолжает свой путь, это мешает мне.

Единственный вариант, о котором я думал до сих пор, - это использование ctypes или чего-то подобного для прямого вызова exit (3), но это кажется довольно сложным взломом для чего-то, что должно быть действительно простым.

Это было полезно?

Решение

Ты можешь позвонить os._exit() для прямого выхода, без создания исключения:

import os
os._exit(1)

Это обходит всю логику завершения работы python, такую как atexit модуль, и не будет выполняться через логику обработки исключений, которой вы пытаетесь избежать в этой ситуации.Аргумент - это код выхода, который будет возвращен процессом.

Другие советы

Как сказал Иеруб, os._exit (1) - это ваш ответ. Но, учитывая, что он обходит все процедуры очистки, включая блоки finally: , закрытие файлов и т. Д., И его действительно следует избегать любой ценой, могу ли я представить " более безопасный МОГ & Quot; способ его использования?

Если вы столкнулись с тем, что SystemExit перехватывается на внешних уровнях (т. е. unittest), тогда будьте сами внешним уровнем! Оберните свой основной код в блоке try / Кроме, поймать SystemExit и вызвать там os._exit, и only там! Таким образом, вы можете вызвать sys.exit обычно в любом месте кода, позволяя ему всплыть на верхний уровень, изящно закрывая все файлы и выполняя все очистки, и затем вызывая os._exit.

Вы даже можете выбрать, какие выходы являются «аварийными». из них. Код ниже является примером такого подхода:

import sys, os

EMERGENCY = 255  # can be any number actually

try:
    # wrap your whole code here ...
    # ... some code
    if x: sys.exit()
    # ... some more code
    if y: sys.exit(EMERGENCY)  # use only for emergency exits
    # ...
except SystemExit as e:
    if e.code != EMERGENCY:
        raise  # normal exit, let unittest catch it
    else:
        os._exit(EMERGENCY)  # try to stop *that*, sucker!
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top