Имена Python-файлов и конфликты импортов
Обновлено:
1. Файл Python тоже может быть модулем
Обычный файл:
weather.py
может быть Python-модулем с именем:
weather
Поэтому при выборе названия файла важно учитывать названия модулей и библиотек, которые используются в проекте.
Python поставляется с большой стандартной библиотекой: например, в неё входят datetime, numbers, random, statistics, decimal и множество других модулей.
2. Рабочая программа
Например, используем стандартный модуль datetime:
from datetime import datetime
def create_time_message():
return f'Текущее время: {datetime.now()}'
print(create_time_message())
Программа работает.
Python находит стандартный модуль:
datetime
и импортирует из него класс:
datetime
3. Создаём свой datetime.py
Теперь в той же папке создадим собственный файл:
datetime.py
Он может быть даже полностью пустым.
Структура проекта:
project/
main.py
datetime.py
После этого снова запускаем main.py.
Программа может перестать работать.
Например:
ImportError: cannot import name 'datetime' from 'datetime'
Причина не в том, что стандартный datetime исчез.
Python импортировал наш локальный файл datetime.py вместо стандартного модуля.
4. Почему Python выбрал наш файл
При обычном импорте Python ищет модуль по определённому пути поиска.
Для модулей, которые не встроены непосредственно в интерпретатор, каталог запускаемого скрипта находится в пути поиска раньше стандартной библиотеки. Поэтому локальный файл с подходящим названием может быть найден первым. Официальная документация прямо предупреждает, что файл в каталоге скрипта может скрыть модуль стандартной библиотеки с таким же именем.
Упрощённо:
Нужно импортировать datetime
↓
Python ищет datetime
↓
находит наш datetime.py
↓
импортирует его
Но в нашем пустом файле нет класса:
datetime
из-за чего дальнейший код ломается.
5. Такое явление называется «затенением»
Ситуацию, когда наше имя скрывает другое имя, часто называют:
shadowing
то есть:
затенение
Наш:
datetime.py
затенил стандартный:
datetime
Поэтому лучше не давать своим файлам имена стандартных модулей, если это может привести к конфликту.
6. Конфликт возможен и со сторонними библиотеками
Проблема относится не только к стандартной библиотеке.
Например, в проекте установлен Django.
Если создать рядом с программой файл:
django.py
такой файл тоже может помешать нормальному импорту установленного пакета django, потому что каталог проекта обычно проверяется раньше site-packages, где находятся сторонние установленные библиотеки.
То же самое потенциально относится к другим установленным пакетам.
7. Пример с numbers.py
В стандартной библиотеке действительно существует модуль:
numbers
Он содержит абстрактную иерархию числовых классов.
Поэтому создавать в проекте файл:
numbers.py
обычно плохая идея.
Но важно уточнить:
Сам файл
numbers.pyне ломает обычные математические операции Python.
Такой код продолжит работать:
print(10 + 5)
print(10 * 5)
print(10 ** 2)
Проблема возникнет, если наша программа или какая-нибудь используемая библиотека попытается импортировать стандартный модуль:
numbers
Python может вместо него загрузить наш numbers.py.
Тогда уже код, который рассчитывал на настоящий стандартный модуль numbers, может завершиться ошибкой.
8. Не каждый стандартный модуль можно затенить одинаково
В стандартной библиотеке есть разные виды модулей.
Некоторые модули встроены непосредственно в интерпретатор. При обычном импорте Python сначала проверяет такие встроенные модули и только затем ищет .py-файлы по sys.path.
Поэтому правило лучше формулировать так:
Не называйте свои файлы именами модулей стандартной библиотеки и сторонних библиотек, если нет осознанной причины это делать.
Так проще избежать труднообъяснимых проблем с импортами.
9. Какие названия лучше не использовать
Например, без необходимости не стоит создавать собственные файлы:
datetime.py
numbers.py
random.py
statistics.py
decimal.py
json.py
logging.py
collections.py
если в проекте могут использоваться одноимённые стандартные модули. Многие из них входят в стандартную библиотеку Python.
А если проект использует стороннюю библиотеку, нужно учитывать и её название.
Например:
django.py
в Django-проекте — плохой выбор.
10. Как назвать файл лучше
Вместо слишком общего:
datetime.py
можно использовать:
time_report.py
Вместо:
numbers.py
например:
calculation_data.py
Вместо:
random.py
например:
random_password_generator.py
Имя должно:
- передавать назначение файла;
- не конфликтовать с используемыми модулями;
- быть понятным другим разработчикам.
11. Если программа неожиданно сломалась после создания файла
Если импорт раньше работал, а после создания или переименования .py-файла перестал работать, стоит проверить:
- не совпадает ли имя нового файла с импортируемым модулем;
- нет ли рядом файла с названием стандартной библиотеки;
- нет ли конфликта с установленным сторонним пакетом.
Например:
main.py
datetime.py
и одновременно:
from datetime import datetime
— очень подозрительная комбинация.
После переименования конфликтующего файла проблема обычно исчезает.
12. Основное правило
Файл Python является модулем, поэтому его название имеет значение.
Если написать:
import datetime
Python должен определить, какой именно модуль datetime нужно загрузить.
Локальный файл может затенить модуль стандартной библиотеки или установленную стороннюю библиотеку.
Поэтому перед выбором имени файла желательно убедиться, что оно не занято важным модулем проекта.
Официальная документация
Полный справочник стандартной библиотеки Python находится в разделе The Python Standard Library официальной документации. Там можно посмотреть названия модулей, которые поставляются вместе с Python.
Также механизм поиска модулей подробно описан в разделе The Module Search Path учебника Python.