Некоторые примечания о каталогах без __init__.py
файлов:
Неявные пакеты пространства имен
Хотя каталог без __init__.py
является допустимым источником импорта в Python 3, он не являетсяобычный пакет, скорее неявный пакет пространства имен (подробности см. PEP 420 ).Среди других свойств неявные пакеты пространства имен являются гражданами второго сорта, когда речь заходит об импорте. Это означает, что когда в Python есть два пакета с одинаковыми именами в sys.path
, один из которых является обычным пакетом, а другой - неявным пакетом пространства имен, обычныйбудет предпочтительным независимо от того, какой пакет идет первым.Проверьте сами:
$ mkdir -p implicit_namespace/mypkg
$ echo -e "def spam():\n print('spam from implicit namespace package')" > implicit_namespace/mypkg/mymod.py
$ mkdir -p regular/mypkg
$ touch regular/mypkg/__init__.py
$ echo -e "def spam():\n print('spam from regular package')" > regular/mypkg/mymod.py
$ PYTHONPATH=implicit_namespace:regular python3 -c "from mypkg.mymod import spam; spam()"
Будет напечатано spam from regular package
: хотя implicit_namespace
стоит первым в sys.path
, вместо него mypkg.mymod
из regular
импортируется, потому что regular/mypkg
является обычным пакетом.
Теперь вы знаете, что, поскольку ваш пакет code
является неявным пакетом пространства имен, Python предпочтет регулярный импорт code
вашему, если он его встретит.К сожалению для вас, в stdlib есть модуль code
, так что это практически проблема "обратного дублирования имен": у вас есть объект импорта с тем же именем, что и у stdlib, но вместоотслеживая импорт stdlib, он затеняет ваше.
Таким образом, вам нужно сделать две вещи, чтобы сделать ваш макет пригодным для использования:
- дать
code
dir уникальное имя (пустьэто будет mycode
для примера этого ответа) - после этого вам все еще нужно исправить
sys.path
при запуске тестов из корневого каталога проекта, потому что он не находится в sys.path
как таковом.У вас есть несколько возможностей: - добавить пустой файл
conftest.py
в корневой каталог (кроме mycode
dir).Это заставит pytest
добавить корневой каталог к sys.path
(объяснение см. здесь ).Теперь вы можете просто запустить pytest
как обычно, и импорт будет разрешен; - запустить тесты через
python -m pytest
- вызов интерпретатора напрямую добавляет текущий каталог в sys.path
; - addтекущий каталог
sys.path
через PYTHONPATH
env var, например, запустить PYTHONPATH=. pytest
.