Работа импорта при создании «псевдонима» для пакета - PullRequest
0 голосов
/ 23 марта 2020

Реальная цель: у меня есть модуль, который является общим для двух пакетов (скажем, bar и bar2). Я хочу использовать одни и те же тестовые файлы для обоих случаев, поэтому я хочу изменить импорт тестов, чтобы не называть пакет явно. (Почему? Это может быть полезно в процессе извлечения модулей из мегапакета в отдельные пакеты.)

Моя идея состояла в том, чтобы добавить еще один модуль, который импортирует определенный пакет и предоставляет для него «псевдоним». Это почти сработало, но у меня возникла проблема.

Изначально у меня было:

# test.py:
from bar import some_function

Если я не сделаю ничего магического, будет две версии test.py: одна с from bar import some_function и другой с from new_bar import some_function. Я хочу избежать этого, и файлы тестового кода остаются прежними.

После того, как я добавил косвенное обращение:

#foo.py:
import bar as baz

#test.py:
from .foo import baz  # Works!
from .foo.baz import some_function  # ModuleNotFoundError: No module named 'cur_dir.foo.baz'; 'cur_dir.foo' is not a package

, я могу сделать foo пакет:

#foo/__init__.py:
import bar as baz

#test.py:
from .foo import baz  # Works!
from .foo.baz import some_function  # ModuleNotFoundError: No module named 'cur_dir.foo.baz'

Ошибка немного меняется, но все равно остается.

Я знаю, что могу обойти проблему, написав

# test.py:
from .foo import baz
some_function = baz.some_function

Есть ли другой способ? Я хочу, чтобы мой импорт был "нормальным".

Есть ли способ создать "псевдоним" для пакета, который можно использовать со стандартным механизмом импорта?

1 Ответ

1 голос
/ 23 марта 2020

Оператор import просматривает только действительные модули и их пути, а не псевдонимы внутри загруженных модулей. Требуется фактический псевдоним модуля в реестре модулей Python, sys.modules.

import sys
import os

sys.modules["os_alias"] = os  # alias `os` to `os_alias`
import os_alias               # alias import works now
from os_alias import chdir    # even as from ... import ...

После добавления псевдонима модуля к sys.modules он доступен для импорта во всем приложении. .


Обратите внимание, что совмещение имен модулей может приводить к незначительным ошибкам при загрузке подмодулей совмещенных модулей. В частности c, если подмодули не имеют явного псевдонима, создаются отдельные версии, которые не являются идентичными. Это означает, что любые тесты, основанные на идентичности объекта, включая isinstance(original.submodule.someclass(), alias.submodule.someclass), не пройдут, если версии будут смешанными.

Чтобы избежать этого, вы должны использовать псевдоним все подмодули любого пакета с псевдонимами.

...