Коды выхода в Python

207

Я получил сообщение, говорящее script xyz.py returned exit code 0. Что это значит?

Что означают коды выхода в Python? Сколько их там? Какие из них важны?

Sundeep
источник
1
Где вы видите это сообщение?
Джереми Кантрелл
1
@ Джереми В нижней части PythonWin.
Sundeep

Ответы:

223

То, что вы ищете в сценарии, это вызовы sys.exit(). Аргумент этого метода возвращается в среду в качестве кода выхода.

Вполне вероятно, что скрипт никогда не вызывает метод выхода, и что 0 является кодом выхода по умолчанию.

Дейв Коста
источник
12
Не уверен вообще. В Unix / Linux стандарт таков: выход 0, если все в порядке. Введите команду, затем echo $ ?: если вы прочитали 0, она вернулась без ошибки. Идея состоит в том, чтобы иметь стандартные тесты. Если код xyz.py не обнаружил никакой ошибки, он ДОЛЖЕН вернуть 0!
Бруно фон Пэрис
1
Если вы хотите изменить код выхода, предпочитайте
чистый
101

Из документации дляsys.exit :

Необязательный аргумент arg может быть целым числом, указывающим статус выхода (по умолчанию равен нулю), или объектом другого типа. Если это целое число, ноль считается «успешным завершением», а любое ненулевое значение считается «ненормальным завершением» оболочками и тому подобным. Большинство систем требуют, чтобы он находился в диапазоне 0-127, и в противном случае дают неопределенные результаты. В некоторых системах есть соглашение о назначении определенных значений определенным кодам выхода, но они, как правило, недостаточно развиты; Программы Unix обычно используют 2 для ошибок синтаксиса командной строки и 1 для всех других видов ошибок.

Один из примеров, где используются коды выхода, - в сценариях оболочки. В bash вы можете проверить специальную переменную $?для последнего статуса выхода:

me@mini:~$ python -c ""; echo $?
0
me@mini:~$ python -c "import sys; sys.exit(0)"; echo $?
0
me@mini:~$ python -c "import sys; sys.exit(43)"; echo $?
43

Лично я пытаюсь использовать коды выхода, которые я нахожу /usr/include/asm-generic/errno.h(в системе Linux), но я не знаю, правильно ли это делать.

Eigir
источник
3
Из другого поста я нашел эту ссылку: tldp.org/LDP/abs/html/exitcodes.html Может быть полезным. :)
Eigir
9
errno.h обычно для кодов выхода вызова функции. Попытки стандартизировать коды завершения программы привели к тому, что /usr/include/sysexits.h присутствует в большинстве систем POSIX.
mpounsett
1
Очень хорошо знать, что «программы Unix обычно используют 2 для ошибок синтаксиса командной строки»!
Дантистон
2
@ Dantiston Concur . Безжалостный адвокат Gentoo, крашеный в шерсти, но я никогда не знал этого ... до этого судьбоносного дня. ( Мой позор заканчивается сейчас. ) Кроме того, обратите внимание, что grepнарушает эту тенденцию, выходя с, 1когда ни одна строка не совпадает и 2на реальных ошибках. Большое спасибо, Столлман.
Сесил Карри
32

Для записи вы можете использовать стандартные коды выхода POSIX, определенные здесь .

Пример:

import sys, os

try:
    config()
except:
    sys.exit(os.EX_CONFIG) 
try:
    do_stuff()
except:
    sys.exit(os.EX_SOFTWARE)
sys.exit(os.EX_OK) # code 0, all ok
laffuste
источник
3
Согласно документам они доступны только в операционных системах Unix, поэтому они не полностью переносимы.
Феникс
1
Если вам нужны переносимые коды POSIX, доступные во всех операционных системах, см. exitstatusПакет PyPI.
Феникс
1
Полный пакет составляет 0 для успеха и 1 для отказа.
Павел Минаев
25

Есть errnoмодуль, который определяет стандартные коды выхода:

Например, « Отказано в доступе» - это код ошибки 13 :

import errno, sys

if can_access_resource():
    do_something()
else:
    sys.exit(errno.EACCES)
Oli
источник
36
Это неверно Эти ошибки не предназначены для использования в качестве кодов завершения процесса. Это низкоуровневые коды ошибок, предназначенные для внутреннего использования в программах, особенно написанных на языке Си. Для Python используйте исключения, когда это возможно.
SvdB
2
Ты прав. Они должны быть использованы внутри. Но вы обычно не вызываете исключения на уровне конечного пользователя. Вы используете sys.exit (x), где x является целым числом, которое вы выбираете произвольно. Но вы можете использовать те, которые начинаются с EX_ и определены в модуле 'os'. Как os.EX_OK или os.EX_IOERR
Оли
2
Извините, но я также проголосую против, потому что это вводит в заблуждение. Коды состояния выхода и номера ошибок не являются взаимозаменяемыми / дополняющими. В данном примере «отказано в разрешении» имеет код ошибки 13 (согласно errnoи errno.h ), но код состояния выхода 77 (согласно osи sysexits.h ). Программы, которые испускают первое, являются нестандартными ( де-факто vel jure ) и не будут хорошо работать с другими, которые по праву ожидают второе.
Марк Г.
14

Коды выхода 0 обычно означают «здесь все в порядке». Однако, если программист сценария не следовал соглашению, вам, возможно, придется обратиться к источнику, чтобы понять, что это значит. Обычно ненулевое значение возвращается как код ошибки.

Сэм Кордер
источник
6

Ответ: «Зависит от того, что означает код выхода ноль»

Тем не менее, в большинстве случаев это означает, что «все в порядке»


Мне нравится POSIX:

Итак, на оболочке я бы набрал:

python script.py && echo 'OK' || echo 'Not OK'

Если мой скрипт Python вызывает, sys.exit(0)оболочка возвращает «ОК»

Если мой скрипт Python вызывает sys.exit(1)(или любое ненулевое целое число), оболочка возвращает «Не в порядке»

Ваша задача - научиться работать с оболочкой и прочитать документацию (или исходный код) вашего скрипта, чтобы увидеть, что означают коды выхода.

FlipMcF
источник
Просто для полноты, «Not OK» будет напечатано, если скрипт Python выдал ошибку ИЛИ имел синтаксическую ошибку.
Шиталь Шах
5

Команды операционной системы имеют коды выхода. Ищите коды выхода Linux, чтобы увидеть некоторые материалы по этому вопросу. Оболочка использует коды выхода, чтобы определить, сработала ли программа, возникли проблемы или произошла ошибка. Прилагаются некоторые усилия для создания стандартных (или, по крайней мере, обычно используемых) кодов выхода. Посмотрите эту публикацию Advanced Shell Script .

С. Лотт
источник
5

Я рекомендую чистое завершение с помощью встроенной функции exit (0), а не sys.exit ()

Я не уверен, если это хороший совет.

Сама упомянутая документация гласит:

Модуль сайта (который импортируется автоматически во время запуска, за исключением случаев, когда указана опция командной строки -S) добавляет несколько констант во встроенное пространство имен. Они полезны для оболочки интерактивного интерпретатора и не должны использоваться в программах .

Затем:

Выход (код = нет)

Объекты, которые при печати печатают сообщение типа «Используйте quit () или Ctrl-D (т.е. EOF) для выхода», а при вызове вызываете SystemExit с указанным кодом выхода.

Если мы сравним его с документацией sys.exit () , он использует тот же механизм, который вызывает SystemExitисключение.

weakcamel
источник
4

Коды выхода имеют только значение, назначенное автором сценария. Традиция Unix такова, что код выхода 0 означает «успех», а все остальное - неудача. Единственный способ убедиться, что означают коды выхода для данного сценария, - изучить сам сценарий.

Харпер Шелби
источник
2

Коды выхода на многих языках программирования до программистов. Таким образом, вы должны посмотреть на исходный код вашей программы (или руководство). Ноль обычно означает «все прошло хорошо».

Davide
источник
0

Следующие коды выхода Unix 0 - для успеха / OK, 1 - не успеха / ошибки. Вы можете просто использовать exit(0)или exit(1)позвонить без импорта sysмодуля.

Лукаш Дыновский
источник
-2

Чтобы разрешить выполнение обработчиков исключений и других вещей, я рекомендую чистое завершение с помощью exit(0)встроенной функции, а не использование, sys.exit()которое резко завершает процесс.

vidstige
источник
Так в чем же разница? Откуда эта информация? Вы имеете в виду выполнение обработчиков "на выходе" или на что именно вы ссылаетесь? SystemExitПохоже, что так или иначе поднимается.
0xC0000022L
мм, я перепутал это с os._exitобоими, кажется, поднять SystemExit.
Виджет
1
Неправильно: sys.exit() делает выключение чисто, как exit(). Они оба делают одно и то же : создают SystemExitисключение. На самом деле, exit()предназначен для интерактивных сессий, а не сценариев, так что концептуально sys.exit() это указано. Вы можете быть смущены os._exit(), это тот, который заканчивается внезапно.
МестреЛион