В документации говорится, что вызов sys.exit () вызывает исключение SystemExit, которое может быть обнаружено на внешних уровнях. У меня есть ситуации, в которой я хочу, чтобы окончательно и бесспорно выхода из внутри теста, однако UnitTest модуль ловит SystemExit и препятствует выходу. Обычно это замечательно, но конкретная ситуация, с которой я пытаюсь справиться, - это ситуация, когда наша тестовая среда обнаружила, что она настроена так, чтобы указывать на нетестовую базу данных. В этом случае я хочу выйти и предотвратить выполнение дальнейших тестов. Конечно, поскольку unittest перехватывает SystemExit и благополучно продолжает свой путь, это мешает мне.
Единственный вариант, о котором я думал до сих пор, - это использовать ctypes или что-то подобное для прямого вызова exit (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 рассматривался как исключение. Итак, спасибо, вы помогли мне проверить, как получить доступ к коду выхода через исключение.
То же самое. Мне нужно было проверить код 0, и это помогло.
Вы также можете использовать quit, см. Пример ниже:
while True:
print('Type exit to exit.')
response = input()
if response == 'exit':
quit(0)
print('You typed ' + response + '.')
Это также актуально при попытке выйти из программы из встроенной оболочки IPython.