Рефакторинг конфигурации модуля Python, чтобы избежать относительного импорта

Это связано с моим предыдущий вопрос.

Я понимаю, как хранить и читать файлы конфигурации. Есть варианты, такие как ConfigParser и ConfigObj.

Рассмотрим эту структуру для гипотетического модуля «яйца»:

eggs/
  common/
    __init__.py
    config.py
  foo/
    __init__.py
    a.py

"egg.foo.a" нужна некоторая конфигурационная информация. То, что я сейчас делаю, это в "а",

import eggs.common.config
. One problem with this is that if 'a' is moved to a deeper level in the module tree, the relative imports break. Absolute imports don't, but they require your module to be on your PYTHONPATH.

Возможной альтернативой вышеуказанному абсолютному импорту является относительный импорт. Таким образом, в 'а'

import .common.config

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

edit - Удален контекст VCS

Связанный вопрос: stackoverflow.com/questions/171785/…

jfs 06.12.2008 08:03
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
3
1
1 052
5

Ответы 5

Требовать оператора от pkg_resources может быть то, что вам нужно.

Как я понял из этого и предыдущих вопросов, вам нужен только один путь в sys.path. Если мы говорим о git как о VCS (упомянутом в предыдущем вопросе), когда только одна ветка извлекается в любое время (один рабочий каталог). Вы можете переключать и объединять ветки так часто, как захотите.

Я удалил контекст VCS, поскольку понял, что он не имеет отношения к моему вопросу. Переключение VCS только что поставило передо мной этот конкретный вопрос дизайна.

saffsd 06.12.2008 07:18

Я думаю о чем-то вроде решения, основанного на выталкивании. Вместо того, чтобы импортировать общие объекты (будь то для конфигурации или каких-либо служебных функций), пусть в этом верхнего уровня экспортирует их, а каждый промежуточный в этом импортирует их из уровня выше и немедленно повторно экспортирует.

Я не уверен, правильно ли я понял терминологию Python, поправьте меня, если я ошибаюсь.

Таким образом, любой модуль, которому необходимо использовать общий объект (который в контексте этого примера представляет информацию о конфигурации), просто импортирует его из в этом на своем собственном уровне.

Это звучит разумно / выполнимо?

"импорт ... требует, чтобы ваш модуль был на вашем PYTHONPATH"

Верно.

Итак, что не так с настройкой PYTHONPATH?

Если у вас одновременно разрабатывается несколько наборов файлов (например, несколько веток), будет сложнее переключаться с одного на другой, если вам нужно каждый раз менять PYTHONPATH; Кроме того, он добавляет зависимость, требующую некоторой работы, чтобы перейти под контроль версий.

William Payne 05.05.2012 22:27

Вы можете обмануть механизм импорта, добавив каждый подкаталог в egg/__init__.py:

__path__.append(__path__[0]+"\\common")
__path__.append(__path__[0]+"\\foo")

затем вы просто импортируете все модули из пространства имен egg; например import egg.bar (при условии, что у вас есть файл egg / foo / bar.py) .
Обратите внимание, что foo и common не должны быть пакетом - другими словами, они не должны содержать файл __init__.py.

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

Другие вопросы по теме