2012-07-16 42 views
1

我在用我的項目內的內部進口困難共享的模塊。這是我的項目的部分樹結構:訪問來自子包

app 
    |- Gui.py 
    |- Main.py 
    |- logger.py 
    |- config.py 
    |- WebParser (package) 
     |- __init__.py 
     |- LinksGrabber.py 
     |- LyricsGrabber.py 
     |- ImagesGrabber.py 
    |- (Many other packages...) 

logger.pyconfig.py模塊均要求在每個包的模塊,並且是獨立的(僅使用儲存卡式模塊)。從包內部訪問這些模塊是非常棘手的。

這是我怎樣努力去實現它,用於啓用配置訪問和WebParser\LinksGrabber.py日誌記錄功能:

# WebParser\__init__.py: 
sys.path.append('..') # for outside-package modules 
import config 
from logger import log 

# WebParser\LinksGrabber.py: 
import WebParser 
config = WebParser.config 
log = WebParser.log 

的問題:

  • 這有碼味。我敢打賭有一個更好的方法來實現這種行爲。
  • 我想打電話給import WebParser和使用WebParser.LinksGrabberWebParser.LyricsGrabber向右走,毫不隱晦地導入它們。這可與進口內__init__.py模塊來完成,但是因爲每個包的模塊導入包本身是不可能的,它會發出遞歸進口。

您能否提供一個更好的FPGA實現,或不同的代碼設計?

+0

當你說「每個模塊自己導入包」時,你的意思是哪些模塊?你的意思是外部目錄(config,Gui等)中的所有模塊導入WebParser,而且WebParser內部的所有模塊都導入這些外部模塊?或者你只是表示WebParser內的模塊導入WebParser本身? – BrenBarn 2012-07-16 18:23:14

+0

我的意思是WebParser內的每個模塊都會導入WebParser本身。 – iTayb 2012-07-16 18:25:40

回答

1

你應該給它一個__init__.py文件做出app包。 python相對導入系統只能在包內運行。然後在你的WebParser模塊裏面,你可以做from .. import config,from .. import Gui等。

至於從裏面的包裏導入WebPackage,這有點代碼味道。你爲什麼需要這樣做?例如,使用相對導入,您可以在ImagesGrabber等內部有from . import LinksGrabber來訪問您所需的內容。如果有許多子模塊需要WebParser軟件包的一部分功能,則應該將這些功能分別放入WebParser中的單獨模塊中。

+0

不是'來自。導入LinksGrabber'和'導入LinksGrabber'一樣嗎?而不是'__init__'應該實現許多子模塊所需的功能?也許我不明白'__init __。py'文件的用途,除了將特定的文件夾定義爲一個包。 – iTayb 2012-07-16 18:37:16

+1

'__init__'應該初始化包。通常它只是一個空文件。有時它會導入特定的子模塊,以便您可以更輕鬆地訪問它們。但它並不是真正意義上的「軟件包範圍」通用功能。這些應該在包內的一個單獨的模塊中。原因正是您發現的:如果您嘗試使用'__init__'來保存通用函數*和*以導入子模塊,但子模塊需要常用函數,則會導致循環導入問題。將初始化與常用功能分開。 – BrenBarn 2012-07-16 18:40:23

+0

另外'從。如果沒有啓用絕對導入(即,如果沒有'from __future__ import absolute_import'),那麼導入LinksGrabber和import LinksGrabber在Python 2中是相同的。如果啓用了絕對導入(因爲它們總是在Python 3中),那麼'import LinksGrabber'將不起作用。另外請注意'from。 import LinksGrabber'與'import WebParser'不一樣,這就是你所說的你所做的。 – BrenBarn 2012-07-16 18:45:08

0

看來,你可以使用relative imports這裏:

from .. import config 
from ..logger import log 
+0

這不會起作用,除非你通過給它一個'__init __。py'使外部'app'目錄成爲一個包。 – BrenBarn 2012-07-16 18:23:43

+0

@BrenBarn - 同意。我想我只是假設這是一個給定的,但也許這是一個不好的假設......並且可能增加'__init __。py'是OP所要求的「更好的實現」; ^)。 – mgilson 2012-07-16 18:24:31

1

我想使整個外(APP)目錄Python包(具有__ init__.py)。

app_files 
    |- ***setup.py*** 
    |- app 
    |- ***__init__.py*** 
    |- Gui.py 
    |- Main.py 
    |- logger.py 
    |- config.py 
    |- WebParser (package) 
      |- __init__.py 
      |- LinksGrabber.py 
      |- LyricsGrabber.py 
      |- ImagesGrabber.py 
    |- (Many other packages...) 

setup.py會一些簡單的像這樣:

#!/usr/bin/env python 

from distutils.core import setup 

setup(name='app', 
     version='1.0', 
     description='My app', 
     author='Greg Ward', 
     packages=['app'], 
    ) 

,那麼你可以運行python setup.py install,以 '應用' 永久安裝到Python路徑。 這一點,在我看來,最好的辦法做到這一點,而不訴諸到處sys.path的黑客。

然後,從蟒蛇的任何地方,你可以參考你的任何文件從全虛線路徑

import app.logger 
import app.config 
import app.WebParser 

使從剛剛導入應用LinksGrabber和LyricsGrabber的唯一途徑。 WebParser會從應用程序中導入它們。WebParser .__ init__。

+0

請注意,「app」是否是一個包的問題與是否使用'setup.py'在系統範圍內安裝是分開的。在許多情況下(例如開發時),您可能不希望使用'setup.py'來安裝它。但是,如果你給它一個'__init __。py'並確保軟件包目錄位於系統路徑中,那麼它將起作用。 – BrenBarn 2012-07-16 18:33:28

+0

在開發時,我建議您使用'python setup.py develop'將它安裝到系統路徑中(實際上)是從您安裝的目錄的符號鏈接。通過這種方式,您可以立即將它們傳播到系統。 BrenBarn說的是正確的,你不需要一個setup.py來安裝到系統路徑上......但是其他任何方法都會感到噁心。 – jdeuce 2012-07-16 18:36:47

+0

我不確定是否將頂級文件夾永久追加到'PYTHONPATH'中是正確的選擇。問題不在於「做到」還是「暫時」,而是要找到一種不太古怪的方式。相對進口似乎是一個更好的主意。儘管如此,+1還是不錯的方法。 – iTayb 2012-07-16 18:42:30