2017-08-18 48 views
1

我的程序有一個結構,像這樣:相對進口結構

scripts/ 
    __init__.py 
    mod1.py 
    mod2.py 
    sub1/ 
     __init__.py 
     mod3.py 
    sub2/ 
     __init__.py 
     mod4.py 

所有程序都開始mod1.py該選擇哪些後續腳本(mod3/mod4.py)來運行基於切斷提供系統參數。所以導入的頂級目錄是scripts/

說我運行我的程序,使>mod1.py 3執行sub1.mod3。在mod3我需要在mod2中定義的函數(該模塊包含用於mod3/mod4的重用代碼塊)。

當我嘗試from .. import mod2我得到ValueError,我試圖超過頂級目錄的相對導入。我在語法上引用docs,如果我們將它們與我的情況進行比較,則mod3.py將是當前模塊(在mod1.py之後)調用它。

我如何嘗試進行相對進口有什麼問題?

mod1.py

import sys 

def imp(module): 
    m = __import__(module) # equivalent to import module as m 
    m.start() 

if __name__ == '__main__': 
    mods = {'3': 'sub1.mod3', 
      '4': 'sub2.mod4'} 

    imp(mods[sys.argv[1]]) 

mod3.py

from .. import mod2 # fails 
import mod2 # works; guessing since import considers mod1 location top-level 
. 
. 
. 
def start(): 
    # do stuff 
+0

'mod2'不在'scripts.sub2' – datta

回答

2

你說:

所有程序被啓動與選擇,後續mod1.py腳本(mod3/mod4.py)基於提供的系統運行參數。所以導入的頂級目錄是scripts /。

From the docs(6.4.2幀內包參考):

注意,相對導入基於當前模塊的名稱。由於主模塊的名稱始終爲「__main__」,因此用作Python應用程序主模塊的模塊必須始終使用絕對導入。

因此,您必須在文件中使用絕對導入。

所以,你的代碼應該閱讀

from scripts.mod2 import X 

from scripts import mod2 

另外,我不知道你爲什麼要這麼做。 它會更簡單,以保持分開包裝兩個模塊,並與if條件加載它們,同時保持文件都在同一個目錄中,SAN的__init__.py

if sys.argv[1] == '3': 
    import mod3 
elif sys.argv[2] == '4': 
    import mod4 

如果你必須讓他們在不同的文件夾,使用此結構:

scripts/ 
    mod1.py 
    pkg/ 
     __init__.py 
     mod2.py 
     sub1/ 
      __init__.py 
      mod3.py 
     sub2/ 
      __init__.py 
      mod4.py 

有了這個結構,您的相對導入應該可以工作。然後導入將是:

if sys.argv[1] == '3': 
    from pkg.sub1 import mod3 
elif sys.argv[2] == '4': 
    from pkg.sub2 import mod4 

這是值得指出的是,無論你導入的庫或包的一部分,整個包被無論如何進口的 - 它只是沒有在範圍內的所有可用的。

+1

您應該包含指向文檔源的鏈接。 –

+0

好點,完成! – nlsdfnbch

+0

當我執行其中任何一個時,我都會得到''no module named scripts''。同樣,只要調用'import mod2'即可,即使它在'mod3/mod4'中。但我應該可以做你說的話;不知道爲什麼我不能。 – datta