2010-11-03 90 views
10

我不清楚如何正確地命名這個問題。Python導入優先級:包或模塊?

案例1

假設我有以下目錄結構。

foo 
| 
+- bar/__init__.py 
| 
+- bar.py 

如果我有

from foo import bar 

我怎麼知道哪個欄(bar.pybar/__init__.py)正在導入?有沒有簡單的方法可以自動檢測這種情況?

案例2

foo 
| 
+- foo.py 
| 
+- other.py 

如果other.py有行

import foo 

我怎麼知道哪些foo的(FOO或foo.foo)正在導入?再次,是否有任何簡單的方法來自動檢測這種情況發生?

在第一種情況下
+2

簡單的方法來檢測它:有bar.py的第一行是'打印(「酒吧.py import「)' – nmichaels 2010-11-03 22:58:21

+2

我應該有RTFM編輯。 http://docs.python.org/tutorial/modules.html是一個很好的資源。 – 2010-11-03 23:18:11

+0

有沒有辦法強制程序使用一種解釋或其他? – Sobi 2017-02-04 01:14:23

回答

6

TLDR;如果包位於同一個目錄中,則它優先於同名的模塊。

從文檔:

「當導入一個名爲spam模塊,解釋搜索一個在當前目錄中名爲spam.py文件,然後在環境變量PYTHONPATH指定的目錄列表。這與shell變量PATH具有相同的語法,即目錄名稱列表。「

這是一個有點誤導,因爲解釋也將尋找一個名爲spam包(一個目錄中稱爲spam包含__init__.py文件)。由於目錄條目是在搜索之前排序的,因此如果它們位於同一目錄中,則包優先於具有相同名稱的模塊,因爲spamspam.py之前。

請注意,「當前目錄」是相對於主腳本路徑(其中__name__ == '__main__' is True)。所以如果你在/home/billg呼叫/foo/bar.py,「當前目錄」是指/foo

+1

有什麼改變?因爲我似乎沒有按照你的建議添加當前目錄。該文檔現在聲明:「當一個名爲spam的模塊被導入時,解釋器首先搜索具有該名稱的內置模塊,如果沒有找到,它將在由該模塊給出的目錄列表中搜索名爲spam.py的文件變量sys.path「。而我沒有看到「當前目錄」列出。但是既然我迷路了,也許我誤解了? – PatrickT 2014-10-05 06:35:42

+1

(我可能會誤解所有這些)之前的一個stackoverflow答案指出,「Python不會將當前目錄添加到sys.path,而是腳本所在的目錄。」 http://stackoverflow.com/questions/2325923/how-to-fix-importerror-no-module-named-error-in-python – PatrickT 2014-10-05 06:39:06

+0

這似乎無法回答**案例1 ** – qff 2017-01-10 21:54:47

0

你想從文件導入功能欄「foo.py」

在你要導入的文件「foo.py」

2

包第二(目錄__init__.py)優先於模塊。這個事實的文檔很難找到,但你可以在源文件中看到:python 2.7,python 3.6(謝謝@qff的發現)。

您需要在foo目錄中使用__init__.py才能工作。

如果other.pyfoo/裏面,然後它會加載foo.py(不是目錄foo/),因爲它看起來在當前目錄中第一個(除非你用PYTHONPATH或sys.path中扮演)。

+0

你怎麼知道它優先? - 我在[Python文檔]找不到它(https://docs.python.org/2/tutorial/modules.html) – qff 2017-01-10 21:56:05

+0

@qff我測試了它。我也測試了python3,它具有相同的行爲。正式文件鏈接的事實將是很好的。如果你找到一個,請隨時編輯我的答案或發表評論,我會編輯它。 – kanaka 2017-01-10 22:14:31

+0

找到了! (種類) - 在嘗試將每一個目錄加載爲包或模塊之前,對目錄條目進行排序。這確保包首先被加載。 [鏈接到CPython源代碼](https://github.com/python/cpython/blob/c30098c8c6014f3340a369a31df9c74bdbacc269/Lib/pkgutil.py#L235) – qff 2017-01-10 22:58:20

5

從一個python外殼:

from foo import bar 

print bar.__file__ 

應該告訴你哪些文件已經導入

羅布

+0

還沒有python3上的屬性__file__ – gabn88 2016-10-06 20:08:36