Инструмент сравнения версий: оператор match в Python
Сопоставление версии Python с помощью match
Наиболее эффективный способ проверки версии Python в коде, ориентированном на Python 3.10 и выше, это использование оператора match с сопоставлением кортежа sys.version_info. Данный подход позволяет наглядно разделить ветви выполнения в зависимости от мажорной, минорной и микро-версии, а также использовать охранные условия (guards) для сложной логики.
import sys
match sys.version_info:
case (3, 10, _):
print("Python 3.10.x")
case (3, 11, _):
print("Python 3.11.x")
case (3, 12, minor) if minor >= 3:
print("Python 3.12.3 или новее")
case (3, major, _) if major >= 13:
print("Python 3.13 или выше")
case _:
print("Другая версия")
Match python version (сопоставление версии python (match statement))
Здесь _ означает любое значение, а имя переменной (например minor) захватывает конкретное значение. Охранные условия после if добавляют дополнительную фильтрацию.
Как выполнить те же действия в Python 3.9 и ниже?
Для версий Python, не поддерживающих match, применяется цепочка if-elif-else с прямым сравнением кортежей:
import sys
ver = sys.version_info
if ver < (3, 10):
print("Python 3.9 или ниже")
elif ver < (3, 11):
print("Python 3.10.x")
elif ver < (3, 12):
print("Python 3.11.x")
else:
print("Python 3.12 или выше")
Также можно использовать sys.version (строка) и разбирать её с помощью split, но это менее надёжно из‑за возможных суффиксов (b1, rc1).
Как учесть бета- и кандидат-версии?
Для точного сопоставления с пре-релизами следует обращаться к sys.version_info.releaselevel. В match можно использовать кортеж из четырёх элементов:
import sys
match sys.version_info:
case (3, 12, _, 'final'):
print("Стабильная 3.12")
case (3, 12, _, 'beta'):
print("Бета-версия 3.12")
case (3, 13, _, 'candidate'):
print("Кандидат 3.13")
Проблема: releaselevel может быть 'alpha', 'beta', 'candidate' или 'final'. Необходимо учитывать все варианты.
Как проверить минимальную версию без match?
Для простой проверки минимальной версии достаточно сравнения:
import sys
if sys.version_info < (3, 8):
raise RuntimeError("Требуется Python 3.8+")
Это компактнее, чем match, но не даёт гибкости для разных веток.
Типичные ошибки:
- Забывают импортировать sys.
- Сравнивают версии как строки: "3.10" > "3.9" работает, но "3.10" < "3.9" ложно из‑за лексикографического сравнения.
- В match указывают case (3, 10): - это требует точного совпадения кортежа, не захватывает микро-версию. Лучше case (3, 10, _).
- Игнорируют releaselevel при работе с пре-релизами.
Пример 1: Привязка переменной с охранным условием
import sys
match sys.version_info:
case (3, 12, micro) if micro >= 5:
print(f"Python 3.12.{micro} (микро-версия 5 или выше)")
case (3, 12, micro):
print(f"Python 3.12.{micro} (микро-версия менее 5)")
case _:
print("Не 3.12")
При запуске на Python 3.12.3: Python 3.12.3 (микро-версия менее 5) При запуске на Python 3.12.5: Python 3.12.5 (микро-версия 5 или выше)
Пример 2: Сопоставление с OR-паттерном
import sys
match sys.version_info:
case (3, 10 | 11, _):
print("Python 3.10 или 3.11")
case (3, 12, _):
print("Python 3.12")
case _:
print("Другая версия")
На Python 3.11.0: Python 3.10 или 3.11 На Python 3.12.2: Python 3.12
Пример 3: Извлечение всего кортежа version_info
import sys
match sys.version_info:
case (major, minor, micro, releaselevel, serial):
print(f"major={major}, minor={minor}, micro={micro}, release={releaselevel}, serial={serial}")
На Python 3.12.2 (final, serial 0): major=3, minor=12, micro=2, release=final, serial=0
Пример 4: Использование вложенных паттернов для проверки мажорной версии
import sys
match sys.version_info:
case (3, _, _):
print("Это Python 3.x")
case (2, _, _):
print("Это Python 2.x")
case _:
print("Неизвестная мажорная версия")
На Python 3.12: Это Python 3.x
Пример 5: Сопоставление с учётом releaselevel и serial
import sys
match sys.version_info:
case (3, 12, micro, 'final', _):
print(f"Стабильная 3.12.{micro}")
case (3, 12, micro, 'beta', serial):
print(f"Бета 3.12.{micro} (серийный номер {serial})")
case (3, 13, _, 'alpha', serial):
print(f"Альфа 3.13 (серийный номер {serial})")
На Python 3.12.2 final: Стабильная 3.12.2 На Python 3.13.0a1: Альфа 3.13 (серийный номер 1)