импорт модулей с подмодулями из глубины библиотеки

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

Я немного озадачен различиями между следующими инструкциями импорта:

1:

import company.productline.specific.models, company.productline.base.models
specific, base = company.productline.specific, company.productline.base
2:

import company.productline.specific.models, company.productline.base.models
from company.productline import specific, base

3:

from company.productline import specific, base
import company.productline.specific.models, company.productline.base.models

первый стиль импортирует только models? какие тогда имена specific и base доступны в текущем пространстве имен?

что происходит при инициализации модулей, если импортировать сначала подмодули и только потом содержащие библиотеки?

возможно, самый аккуратный стиль — последний, где ясно (по крайней мере, мне), что я сначала импортирую два модуля и помещаю их имена непосредственно в текущее пространство имен, а второй импорт добавляет подмодуль model к обоим только что импортированным модулям.

с другой стороны, (1) позволяет мне импортировать только внутренние модули и ссылаться на них в компактной, но понятной форме (specific.models и base.models)

не уверен, что это вопрос, но мне любопытно читать комментарии.


person mariotomo    schedule 29.07.2009    source источник


Ответы (2)


Все три приведенных выше примера на практике эквивалентны. Хотя все они странные. Нет причин делать

from company.productline import specific

а также

import company.productline.specific.models

Вы можете (в большинстве случаев) просто получить доступ к моделям с помощью specific.models после первого импорта.

Представляется разумным в этом случае сделать

from company.productline import base
from company.productline import specific

А затем получите доступ к таким, как base.models, specific.whatever и т. д. Если "специфический" - это, вам также нужно сделать import model в __init__.py, чтобы получить доступ к конкретному модулю.

person Lennart Regebro    schedule 29.07.2009
comment
Я взглянул на стандартный пакет электронной почты, который содержит различные более глубокие модули и не определяет __all__ (полезно только для from package import *), а делает некоторые причудливые вещи с ленивым импортом... довольно интересно. попробовал __init__.py, содержащий import models, но то, что django делает за кулисами, когда python импортирует модели, делает это невозможным (django сканирует INSTALLED_APPS и предполагает, что они уже там, в то время как python все еще импортирует их) - person mariotomo; 29.07.2009
comment
A, правильно все только для *, правильно. Чтобы исправить пустой модуль, вы импортируете подмодуль в файл init. Я вспомнил это в обратном порядке. :) - person Lennart Regebro; 30.07.2009

поэтому я изучил это немного глубже, используя этот бесполезный пакет:

A:(__init__.py: print 'importing A',
   B:(__init__.py: print 'importing B',
      C1:(__init__.py: print 'importing C1',
          D:(__init__.py: print 'importing D'))
      C2:(__init__.py: print 'importing C2',
          D:(__init__.py: print 'importing D'))))

обратите внимание, что C1 и C2 содержат два разных модуля, оба с именами D в разных пространствах имен. Мне понадобятся они оба, я не хочу использовать весь путь A.B.C1.D и A.B.C2.D, потому что это выглядит слишком неуклюже, и я не могу поместить их оба в текущее пространство имен, потому что один перепишет другой и - нет, мне не нравится идея менять их имена. я хочу иметь C1 и C2 в текущем пространстве имен и загрузить два включенных модуля D.

о, да: и я хочу, чтобы код был читаемым.

Я пробовал две формы

from A.B import C1

и гораздо более уродливый

import A.B.C1
C1 = A.B.C1

и я бы сделал вывод, что они эквивалентны:


Python 2.6.2 (release26-maint, Apr 19 2009, 01:56:41) [GCC 4.3.3] on linux2
>>> from A.B import C1
importing A
importing B
importing C1
>>> C1
<module 'A.B.C1' from 'A/B/C1/__init__.pyc'>
>>> 

Python 2.6.2 (release26-maint, Apr 19 2009, 01:56:41) [GCC 4.3.3] on linux2
>>> import A.B.C1
importing A
importing B
importing C1
>>> C1=A.B.C1
>>> C1
<module 'A.B.C1' from 'A/B/C1/__init__.pyc'>
>>> 

При импорте пакета C1 или C2 включенные модули не импортируются только потому, что они есть. и очень плохо, что форма from A.B import C1.D синтаксически не принимается: было бы неплохо иметь компактную вещь.

с другой стороны, мне предлагается сделать это в A.B.C1.__init__.py, если я попрошу. поэтому, если я добавлю строку import D к __init__.py в A.B.C1, произойдет следующее:

Python 2.6.2 (release26-maint, Apr 19 2009, 01:56:41) [GCC 4.3.3] on linux2
>>> from A.B import C1
importing A
importing B
importing C1
importing D
>>> 

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


учитывая все это и учитывая некоторое специфическое поведение django (что делает сложным/невозможным автоматическое import models при импорте пакета), я думаю, что предпочитаю стиль 3.

person mariotomo    schedule 30.07.2009