2017-10-07 120 views
-1

我不認爲任何語言引起這麼簡單的事,作爲大爲頭痛的Python作爲導入其他源文件。所以這裏是問題: 我的模塊導入是否需要取決於代碼應該如何運行?Python模塊的導入取決於代碼的運行方式?

我有以下目錄結構:

./__init__.py 
./config.py 
./kmer 
./kmer/__init__.py 
./kmer/__main__.py 
./kmer/__pycache__ 
./kmer/__pycache__/__init__.cpython-36.pyc 
./kmer/__pycache__/__main__.cpython-36.pyc 
./kmer/__pycache__/bed.cpython-36.pyc 
./kmer/__pycache__/config.cpython-36.pyc 
./kmer/__pycache__/reference.cpython-36.pyc 
./kmer/__pycache__/sets.cpython-36.pyc 
./kmer/bed.py 
./kmer/config.py 
./kmer/reference.py 
./kmer/sets.py 

我想從kmer包內的另一個模塊導入khmer內的模塊。簡單?

所以我添加此在的bed.py的:

import reference 
import config 
import sets 

現在,如果我從kmer目錄運行python bed.py事會工作得很好。如果我返回一個目錄並且致電python kmer/bed.py,那也沒關係。看起來像python搜索相對於給定文件的導入模塊。

再次從kmer目錄中運行它作爲python -m bed工作正常,但回來一個目錄,並運行導致模塊故障。在這裏,python看起來像解釋器當前目錄中的模塊,它可能在文件系統的任何地方,所以相對於它的導入不應該工作。

這基本上意味着,進口量應取決於代碼將如何運行這是沒有意義的。我會很感激一些關於如何工作的解釋。

我已經看了很多資源,其中包括this問題的答案,儘管非常詳細(我找到的最好的描述之一)並沒有解決我的問題,也沒有提供適當的例子。

更新:我認爲這個問題是更側重於相對進口的不同方面,更精確地運行代碼的不同方法如何影響進口量,比它被標記爲的副本之一。這就是爲什麼我首先提到了另一個問題。因此我認爲這不應該是重複的。

+0

你將不得不解釋鏈接的問題不能解決你的問題,因爲它在我看來像它解決了你的問題。 – user2357112

+0

@ user2357112這個問題的不同之處在於混合包和腳本語義部分,戴維斯的答案在下面指出。我並沒有從相關的問題中理解,理解當然是主觀的。 – DarthPaghius

回答

1

當編寫一個包,你必須始終把它作爲一個包。首先,這意味着在包裝中使用相對進口:在bed.py中寫入from . import reference

這也意味着如何訪問它總是一樣的答案:把包含目錄kmersys.path(通常是通過PYTHONPATH)。這是真實的,即使運行一些模塊中的一個包中的腳本,所以它必須是。

不幸的是,這是一個壞主意,運行一個封裝內的模塊作爲腳本:模塊的文件仍然是資格根據其真名被導入再次(而非__main__第一次使用)。唯一可靠的解決方案是寫一個__main__.py和運行爲腳本,避免超載公共模塊名稱。

最後,不要太在意Python的「特性」,將腳本的目錄放在sys.path上。除了不關心名稱衝突的玩具問題之外,這是沒有用的,因爲任何腳本的目錄在sys.path上都是有用的,它必然是一個模塊(除非使用名稱而不是標識符這樣的技巧)。而且,如果你想讓你的庫可用於其他地方的腳本,無論如何它需要以其他方式獲得sys.path

+0

嘗試使用'-m'標誌運行包中的模塊之一仍然給我'SystemError:父模塊''未加載'錯誤。這與你說的不矛盾嗎? – DarthPaghius

+0

@Parsoa:你使用了什麼命令行?這是完整的例外信息嗎? –

相關問題