从库的深处导入含子模块的模块

0 投票
2 回答
1183 浏览
提问于 2025-04-15 13:14

在我们办公室,有一个以公司名字命名的库,里面有一些子库,基本上是按项目分类的,每个子库里可能还有更多的模块或库。我们使用的是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 呢?那 specificbase 在当前的命名空间中是什么呢?

如果先导入子模块,然后再导入包含它们的库,模块的初始化会发生什么呢?

也许最简洁的方式是最后一种,至少对我来说很清楚,我先导入了这两个模块,并且直接把它们的名字放到了当前的命名空间中,第二次导入则是把 model 子模块添加到刚刚导入的两个模块里。

另一方面,(1) 让我只导入内部模块,并且可以用一种简洁而清晰的方式来引用它们(specific.modelsbase.models)。

我不太确定这是不是个问题,但我很想看看大家的评论。

2 个回答

0

上面这三个例子在实际使用中是等价的。不过,它们都有点奇怪。没有必要这样做:

from company.productline import specific

还有

import company.productline.specific.models

通常情况下,你可以在第一次导入后直接通过 specific.models 来访问模型。

在这种情况下,做以下操作似乎是合理的:

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

然后你可以像这样访问它们:base.modelsspecific.whatever,等等。如果“specific”是一个模块,你还需要在 __init__.py 文件中做一个 import model,这样才能访问到 specific.module

0

我深入研究了一下,使用了这个看起来没什么用的包:

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'))))

注意到 C1C2 各自包含两个不同的模块,它们在各自的命名空间中都叫 D。我需要这两个模块,但我不想每次都写完整的路径 A.B.C1.D 和 A.B.C2.D,因为那样看起来太繁琐了。而且我不能把它们都放在当前的命名空间里,因为一个会覆盖另一个。而且,我不想改它们的名字。我想要的是在当前命名空间中同时使用 C1C2,并加载这两个 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 中做到这一点。所以如果我在 A.B.C1__init__.py 文件中加上 import D 这一行,结果会是这样的:

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 变得困难或不可能),我觉得我更喜欢第三种风格。

撰写回答