2012-04-26 71 views
2

Python的導入功能有時候還會讓我感到困惑。這裏有一個例子:Python包和導入 - 需要說明

我的項目有以下封裝結構:

Project/ 
    src/ 
     example/ 
      __init__.py 
      an_example.py 
     top/ 
      __init__.py 
      lin/ 
       __init__.py 
       factory.py 

an_example.py,我想寫

from top import lin 
if __name__ == '__main__': 
    a = lin.factory.AClass() 

然而,這種失敗:

a = lin.factory.AClass() 
AttributeError: 'module' object has no attribute 'factory' 

an_example.py作品寫的像這樣:

from top.lin import factory 
if __name__ == '__main__': 
    a = factory.AClass() 

您能向我解釋爲什麼寫入像第一個版本的導入語句是錯誤的嗎?我更喜歡一個完全合格的名稱,如lin.factory.AClassfactory.AClass

回答

4

這是因爲,除非你告訴lin__init__.py進口factory,然後factory不在lin命名空間。

E.g:

假設現有的項目結構,an_example.py包含:

from top import lin 

lin.factory.AClass() 

隨着top/lin/__init__.py空白,我們得到ImportError: No module named factory

top/lin/__init__.py包含import top.lin.factory,我們得到沒有錯誤。

當您要求使用factory.AClass()時,它的工作原理是因爲它在那裏定義。同樣,如果您想從那裏使用它,則需要在lin中定義工廠。

+1

謝謝,我不知道我必須編輯'__init __。py'嵌套包。然而,令人困惑的是,我必須在'top/lin/__ init __。py'中導入'top.lin.factory'而不是'import factory'(這不起作用)。這意味着'lin/__ init __。py'不僅需要知道'lin /'的內容,還需要知道它包含在('top')中的包,並且在移動時必須進行編輯。這不符合模塊化設計原則嗎? – clstaudt 2012-04-26 13:35:07

+2

@clstaudt嗯,只有當你希望能夠按照你的要求使用它們。您不需*執行此操作以使用嵌套軟件包。至於絕對導入名稱,作爲替代,您可以使用相對導入('from。import factory'')。 – 2012-04-26 13:38:53