Именование модулей Python: рекомендации и варианты

Раздел: Python -> Структура модулей

Соглашения об именовании модулей Python

Какое соглашение об именовании модулей является наиболее распространённым и рекомендуемым?

Основное правило, описанное в PEP 8, предписывает использовать для модулей имена в стиле snake_case - все буквы строчные, слова разделяются символом подчёркивания. Это обеспечивает единообразие, читаемость и избегает путаницы с именами классов (CamelCase) и констант (UPPER_CASE).


# имя модуля: my_module.py
# содержимое: def my_function(): pass

Python module naming (соглашения об именовании модулей python)

Цель: соответствие стандартным библиотекам Python (os, json, datetime) и упрощение импорта. Используется для любых модулей: утилит, вспомогательных функций, конфигураций.

Типичные ошибки: использование заглавных букв (MyModule.py) или дефисов (my-module.py) - Python не разрешает импорт модулей с дефисом, так как это недопустимый синтаксис. Решение: всегда заменять дефис на подчёркивание.

Как назвать модуль, состоящий из одного слова?

Если имя модуля короткое и однозначное, допустимо использовать одно слово без подчёркиваний. Примеры: utils.py, config.py, models.py. Это подходит для часто используемых модулей с широкой областью. Однако стоит избегать совпадений с именами встроенных модулей (math, sys).


# config.py
DATABASE_URL = 'sqlite:///test.db'

Python modules (модули python)

Проблема: конфликт имён с модулями из стандартной библиотеки. Например, создание файла string.py перекроет стандартный модуль string. Решение: проверять имя на уникальность, использовать префикс, например app_config.py.

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

Модули, предназначенные только для внутреннего использования внутри пакета, принято начинать с одного подчёркивания: _internal.py. Это сигнал разработчикам, что модуль не является частью публичного API.


# пакет mypackage/
# __init__.py
# _helpers.py (внутренний)

Python module main (основной модуль __main__)

Цель: скрыть вспомогательные функции от пользователей пакета. При импорте from mypackage import * такие модули не попадают в область видимости (если не задан __all__).

Ошибка: попытка импортировать модуль с подчёркиванием как публичный - возможно, но считается нарушением соглашения. Решение: явно экспортировать только нужные имена через __all__.

Как быть с модулями, содержащими цифры?

Цифры в именах модулей допустимы, но только если они несут смысловую нагрузку (например, версия: v2_api.py). Не рекомендуется начинать имя с цифры (2api.py - синтаксическая ошибка).


# v2_schema.py

Проблема: цифры в начале имени файла недопустимы в Python. Решение: всегда ставить цифры в середине или конце, или использовать буквенный префикс.

Какое имя выбрать для модуля с тестовыми функциями?

Для тестов принято добавлять суффикс _test или префикс test_. Например, test_math_utils.py или math_utils_test.py. Это позволяет инструментам (pytest, unittest) автоматически находить тесты.


# test_calculator.py
import pytest
from calculator import add

def test_add(): ...

Цель: соответствие стандартам тестовых фреймворков. Используется в проектах с тестированием.

Ошибка: нерегулярные имена, не соответствующие шаблону test_*.py - pytest может их пропустить. Решение: придерживаться шаблона, заданного в конфигурации pytest.

Выбор соглашения об именовании модулей зависит от контекста, но основным остаётся snake_case с учётом уникальности и читаемости.

Расширенные примеры именования модулей Python

Ниже приведены подробные примеры, демонстрирующие различные соглашения и их практическое применение.

Пример 1: Базовый модуль в стиле snake_case

Пример

# file: data_processing.py

def clean_data(data):
    return [x.strip() for x in data if x]

def transform_data(data):
    return [x.upper() for x in data]
# Импорт:
>>> import data_processing
>>> dp.clean_data([' a ', 'b ', '  c'])
['a', 'b', 'c']

Пример 2: Модуль с одним словом и конфликт имён

Пример

# file: json.py (плохо! перекрывает стандартный json)
def custom_load(data):
    return {'custom': data}

# другой файл:
import json  # теперь это локальный модуль, а не стандартный
print(json.custom_load('test'))
# Ошибка: AttributeError: module 'json' has no attribute 'loads'
# Решение: переименовать модуль в my_json.py или json_utils.py

Пример 3: Внутренний модуль с подчёркиванием

Пример

# пакет mypackage/
# __init__.py
from ._helpers import internal_func
__all__ = ['public_func']

# _helpers.py
def internal_func():
    return "internal"

# другой код:
import mypackage
print(mypackage.internal_func())  # работает, но не рекомендуется
print(mypackage.__all__)  # ['public_func']
# При from mypackage import * внутренний модуль не импортируется автоматически.

Пример 4: Тестовый модуль с префиксом test_

Пример

# file: test_math_ops.py
import pytest
from math_ops import add, divide

def test_add():
    assert add(2, 3) == 5

def test_divide():
    with pytest.raises(ZeroDivisionError):
        divide(5, 0)
# Запуск pytest:
$ pytest test_math_ops.py -v
============================= test session starts ==============================
test_math_ops.py::test_add PASSED
test_math_ops.py::test_divide PASSED

Пример 5: Модули с цифрами в имени

Пример

# file: api_v2.py
VERSION = 2
def process_request(data):
    return {'version': VERSION, 'data': data}

# Неправильно: 2api.py (синтаксическая ошибка при импорте)
>>> import api_v2
>>> api_v2.process_request('test')
{'version': 2, 'data': 'test'}

Пример 6: Пакет с несколькими модулями (структура)

Пример

# дерево:
my_package/
    __init__.py
    core.py
    utils/
        __init__.py
        file_io.py
        _config.py

# __init__.py (my_package)
from .core import main_func
from .utils.file_io import read_file

# utils/file_io.py
def read_file(path):
    with open(path, 'r') as f:
        return f.read()

# utils/_config.py (внутренний)
import os
DEFAULT_PATH = os.getcwd()
# Импорт:
>>> from my_package import main_func, read_file
>>> read_file('test.txt')
'...'
# _config не импортируется через from my_package import *

Эти примеры показывают типичные случаи применения соглашений и предостерегают от распространённых ошибок.

Соглашения об именовании модулей Python - comments

En
Python module naming (python)