from __future__ import absolute_import 實際上做了什麼?

| | | | | | | | |

回答了一個關於Python中絕對導入的問題,我認為我在閱讀Python 2.5 變更日誌 和隨附的 PEP。但是,在安裝 Python 2.5 並嘗試製作一個正確使用 from __future__ import absolute_import 的示例時,我意識到事情並不是那麼清楚。

直接從上面鏈接的更改日誌中,這語句準確地總結了我對絕對導入更改的理解:

假設你有一個這樣的包目錄:

pkg/ pkg/__init__.py pkg/main.py pkg/string.py 

這定義了一個名為 pkg 的包,其中包含 pkg.main pkg.string submodules.

考慮 main.py 模塊中的代碼。如果它執行語句 import string 會發生什麼?在 Python 2.4 及更早版本中,它將首先查看包的目錄以執行相對導入,找到 pkg/string.py,將該文件的內容作為 pkg.string 模塊導入,並且該模塊與名稱綁定"string"pkg.main 模塊的名稱中

所以我創建了這個精確的目錄結構:

$ ls -R .: pkg/ ./pkg: __init__.py main.py string .py 

__init__.pystring.py 為空。 main.py 包含以下代碼:

import string print string.ascii_uppercase 

正如預期的那樣,用 Python 2.5 運行它失敗並出現 AttributeError:

$ python2.5 pkg/main.py Traceback(最近一次調用最後):文件“pkg/main.py”,第 2 行, 在<模塊> print string.ascii_uppercase AttributeError: "module" object has no attribute "ascii_uppercase" 

然而,在 2.5 的更新日誌中,我們發現了這個(強調添加):

在 Python 2.5 中,您可以使用 from __future__ import absolute_import 指令將 import 的行為切換為絕對導入。這種絕對導入行為將在未來的版本(可能是 Python 2.7)。一旦默認導入絕對導入,import string 將始終找到標準庫的版本。

我因此創建了 pkg/main2.py,與 main.py 相同,但帶有額外的未來導入指令。它現在看起來像這樣:

from __future__ import absolute_import import string print string.ascii_uppercase 

用 Python 2.5 運行它,但是......失敗了AttributeError:

$ python2.5 pkg/main2.py Traceback(最近一次調用最後):文件“pkg/main2.py”,第 3 行,在 < ;模塊> print string.ascii_uppercase AttributeError: "module" object has no attribute "ascii_uppercase" 

這與 import stringalways 找到啟用了絕對導入的 std-lib 版本。更重要的是,儘管警告說絕對導入計劃成為“新的默認”行為,但我在使用 Python 2.7 時遇到了同樣的問題,無論是否使用 __future__ 指令:

$ python2.7 pkg/main.py Traceback(最近一次調用最後):文件“pkg/main.py”,第 2 行,在<module>打印 string.ascii_uppercase AttributeError:“module”對象沒有屬性“ascii_uppercase”$ python2.7 pkg/main2.py Traceback(最近一次調用最後):文件“pkg/main2.py”,第 3 行,在<module>打印 string.ascii_uppercase AttributeError:“module”對象沒有屬性 "ascii_uppercase" 

以及 Python 3.5,有或沒有(假設 print 語句在兩個文件中都已更改):

$ python3.5 pkg/main.py Traceback(最近一次調用最後):文件“pkg/main.py”,第 2 行,在 <module> print(string.ascii_uppercase) AttributeError: module "string " 沒有屬性 "ascii_uppercase" $ python3.5 pkg/main2.py Trac eback(最近一次調用最後一次):文件“pkg/main2.py”,第 3 行,在 <module> print(string.ascii_uppercase) AttributeError: module "string" has no attribute "ascii_uppercase" 

我已經測試過這個的其他變體。我創建了一個空模塊,而不是 string.py——一個名為 string 的目錄,其中只包含一個空的 __init__.py——而是從 main.py 發出導入,我有 cd"d 到 pkg 並直接從 REPL 運行導入。這些變體都不是(也不是它們的組合)改變了上面的結果。我無法將這與我所讀到的關於 __future__ 指令和絕對導入的內容相一致。

在我看來,這很容易解釋由 以下 (這是來自 Python 2 文檔,但是這個Python 3 的相同文檔中的語句保持不變):

sys.path

(...)

在程序啟動時初始化,此列表的第一項,path[0],是包含用於調用 Python 解釋器的腳本的目錄。如果腳本目錄y 不可用(例如,如果以交互方式調用解釋器或從標準輸入讀取腳本),path[0] 是空字符串,指示 Python 在當前目錄優先。

那麼我錯過了什麼?為什麼 __future__ 語句看起來不像它所說的那樣,這兩個文檔部分之間以及描述和實際行為之間的矛盾的解決方法是什麼?

Shop

Learn programming in R: courses

$

Best Python online courses for 2022

$

Best laptop for Fortnite

$

Best laptop for Excel

$

Best laptop for Solidworks

$

Best laptop for Roblox

$

Best computer for crypto mining

$

Best laptop for Sims 4

$

Latest questions

NUMPYNUMPY

psycopg2: insert multiple rows with one query

12 answers

NUMPYNUMPY

How to convert Nonetype to int or string?

12 answers

NUMPYNUMPY

How to specify multiple return types using type-hints

12 answers

NUMPYNUMPY

Javascript Error: IPython is not defined in JupyterLab

12 answers


Wiki

Python OpenCV | cv2.putText () method

numpy.arctan2 () in Python

Python | os.path.realpath () method

Python OpenCV | cv2.circle () method

Python OpenCV cv2.cvtColor () method

Python - Move item to the end of the list

time.perf_counter () function in Python

Check if one list is a subset of another in Python

Python os.path.join () method