Работа с кодами возврата в Python

Раздел: Основы Python -> Вызовы

Основные понятия кода вызова

Код вызова (exit code) в Python – это целое число, которое программа возвращает операционной системе после завершения. По соглашению, код 0 означает успешное выполнение, а любой ненулевой код указывает на ошибку. Понимание механизма кодов вызова помогает создавать надежные скрипты, которые могут быть использованы в автоматизации и конвейерах обработки.

Как правильно завершить программу с заданным кодом вызова?

Наиболее эффективное и рекомендуемое решение – использование функции sys.exit() из модуля sys. Она выбрасывает исключение SystemExit, которое может быть перехвачено, но в любом случае завершает интерпретатор с указанным кодом. При отсутствии аргумента код по умолчанию равен 0.

import sys

# Успешное завершение
sys.exit(0)

# Завершение с кодом ошибки
sys.exit(1)

вызов класса python (вызов класса в python)

После вызова sys.exit() программа немедленно прекращает выполнение, выполнив предварительно очистку (закрытие файлов, вызов деструкторов).

Типичные ошибки:

  • Передача нецелого числа – вызывает TypeError.
  • Использование sys.exit() внутри блока try без повторного возбуждения исключения – может скрыть намерение завершить программу.

Как завершить программу без системного исключения?

Функция os._exit() из модуля os немедленно завершает процесс без вызова обработчиков очистки и без возбуждения SystemExit. Она полезна в дочерних процессах после fork() или в критических ситуациях, где необходима гарантированная остановка.

import os

os._exit(2)  # Код вызова 2

Python вызов переменной (вызов переменной в python)

Проблема:

После os._exit() не выполняются деструкторы объектов и не закрываются открытые ресурсы, что может привести к потере данных или повреждению файлов.

Как использовать код вызова для возврата значения из главной функции?

Еще один способ – явно возбудить исключение SystemExit с кодом в качестве аргумента. Это эквивалентно вызову sys.exit().

raise SystemExit(0)   # успех
raise SystemExit(1)   # ошибка

код вызова python (код вызова в python)

Такой подход часто применяется внутри функций, когда нужно передать код вызова из точки вызова.

Ошибка:

Если SystemExit перехватить в except, программа не завершится, если не выполнить raise повторно.

Как получить код вызова внешней системы?

При запуске сторонних программ из Python через модуль subprocess код вызова доступен в атрибуте returncode объекта CompletedProcess.

import subprocess

result = subprocess.run(['python', '-c', 'exit(5)'], capture_output=True)
print(result.returncode)  # 5

Типичная проблема:

Если запущенная программа была прервана сигналом (например, SIGKILL), returncode будет отрицательным числом, что может быть неверно интерпретировано.

Как использовать константные коды вызова для улучшения читаемости?

Модуль os предоставляет константы EXIT_SUCCESS (0) и EXIT_FAILURE (1). Их применение делает код самодокументируемым.

import os

sys.exit(os.EXIT_SUCCESS)
sys.exit(os.EXIT_FAILURE)

Расширенные примеры использования кодов вызова

Пример 1. Передача кода вызова через аргумент командной строки

Сценарий: пользователь указывает код вызова при запуске скрипта.

Пример
import sys

if len(sys.argv) > 1:
    try:
        exit_code = int(sys.argv[1])
        sys.exit(exit_code)
    except ValueError:
        sys.exit(2)
else:
    sys.exit(0)

Результат выполнения (пример в терминале):

$ python script.py 42
echo $?   # 42

Пример 2. Обработка кода вызова дочернего процесса в многопоточном приложении

Использование os._exit() в потоке может завершить весь процесс, но это опасно. Лучше использовать threading.Event и sys.exit().

Пример
import threading
import sys
import time

def worker(event):
    time.sleep(1)
    event.set()

stop_event = threading.Event()
t = threading.Thread(target=worker, args=(stop_event,))
t.start()
stop_event.wait()
sys.exit(0)  # завершение главного потока

Пример 3. Перехват SystemExit для отложенного завершения

В некоторых случаях требуется перехватить SystemExit, выполнить очистку, а затем завершиться с тем же кодом.

Пример
import sys

try:
    sys.exit(3)
except SystemExit as e:
    print(f"Очистка перед завершением с кодом {e.code}")
    raise

Результат:

Очистка перед завершением с кодом 3

После вывода сообщения программа завершится с кодом 3.

Пример 4. Использование кода вызова в реальном приложении (парсер аргументов)

Программа, которая проверяет наличие файла и возвращает 1, если файл не найден.

Пример
import sys
import os

def main():
    if len(sys.argv) < 2:
        sys.exit(1)
    filename = sys.argv[1]
    if not os.path.exists(filename):
        print(f"Файл {filename} не найден", file=sys.stderr)
        sys.exit(2)
    print("Файл существует")
    sys.exit(0)

if __name__ == '__main__':
    main()

Пример 5. Получение кода вызова из асинхронного выполнения (asyncio)

Асинхронный запуск подпроцесса с ожиданием кода завершения.

Пример
import asyncio

async def run():
    process = await asyncio.create_subprocess_exec('python', '-c', 'exit(9)')
    await process.wait()
    print(f"Код вызова: {process.returncode}")

asyncio.run(run())

Пример 6. Код вызова при ошибке в модуле unittests

Возврат кода вызова из тестового раннера:

Пример
import unittest
import sys

class TestExitCode(unittest.TestCase):
    def test_failure(self):
        self.assertTrue(False)  # тест упадёт

if __name__ == '__main__':
    runner = unittest.TextTestRunner()
    result = runner.run(unittest.defaultTestLoader.loadTestsFromModule(sys.modules[__name__]))
    sys.exit(0 if result.wasSuccessful() else 1)

Код вызова в Python - comments

En
код вызова python (python)