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

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

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

Это также актуально при попытке выйти из программы из встроенной оболочки IPython.

quazgar 10.10.2016 15:17
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
61
1
58 604
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

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

import os
os._exit(1)

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

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

Если ваша проблема заключается в том, что SystemExit перехватывается на внешних уровнях (например, unittest), тогда будьте на внешнем уровне сами! Оберните ваш основной код в блоке try / except, перехватите SystemExit и вызовите os._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!

Один случай, который мне нужно было проверить, - это код 0, что означает, что мы пытаемся нормально выйти без ошибок / сбоев. Это полезно при использовании OptionParser, когда ему передается аргумент -h, и я не хочу, чтобы SystemExit рассматривался как исключение. Итак, спасибо, вы помогли мне проверить, как получить доступ к коду выхода через исключение.

leetNightshade 21.06.2013 22:54

То же самое. Мне нужно было проверить код 0, и это помогло.

BuvinJ 16.11.2015 17:09

Вы также можете использовать quit, см. Пример ниже:

while True:
print('Type exit to exit.')
response = input()
if response == 'exit':
    quit(0)
print('You typed ' + response + '.')

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