[解決済み] 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
サブモジュールを使用します。
main.pyモジュールのコードを考えてみましょう。もしそれが以下の文を実行したらどうなるでしょうか?
import string
? Python 2.4 以前では、まずパッケージのディレクトリを探して相対 import を行い、 pkg/string.py を見つけて、そのファイルの中身を
pkg.string
という名前にバインドされ、そのモジュールは
"string"
の中で
pkg.main
モジュールの名前空間です。
そこで、この通りのディレクトリ構造を作りました。
$ ls -R
.:
pkg/
./pkg:
__init__.py main.py string.py
__init__.py
と
string.py
は空です。
main.py
には、次のようなコードが含まれています。
import string
print string.ascii_uppercase
予想通り、Python 2.5でこれを実行すると、以下のようなエラーが発生して失敗します。
AttributeError
:
$ python2.5 pkg/main.py
Traceback (most recent call last):
File "pkg/main.py", line 2, in <module>
print string.ascii_uppercase
AttributeError: 'module' object has no attribute 'ascii_uppercase'
しかし、2.5の変更履歴を見ると、さらに次のようなことが書かれています(強調)。
Python 2.5では、以下のように切り替えることができます。
import
の挙動を絶対インポートに変更するにはfrom __future__ import absolute_import
ディレクティブを使用します。この絶対インポート動作は将来のバージョン(おそらく Python 2.7)でデフォルトとなる予定です。 一旦絶対インポートがデフォルトになります。import string
は常に標準ライブラリのバージョンを見つけます。
こうして私は
pkg/main2.py
と同じです。
main.py
が、future importディレクティブが追加されています。現在では、次のようになります。
from __future__ import absolute_import
import string
print string.ascii_uppercase
Python 2.5でこれを実行すると...
AttributeError
:
$ python2.5 pkg/main2.py
Traceback (most recent call last):
File "pkg/main2.py", line 3, in <module>
print string.ascii_uppercase
AttributeError: 'module' object has no attribute 'ascii_uppercase'
という記述とかなり真っ向から矛盾しています。
import string
意志
常に
は、絶対インポートを有効にした std-lib バージョンを見つけることができます。さらに、絶対インポートが "新しいデフォルトの動作になる予定だという警告にもかかわらず、Python 2.7で
__future__
ディレクティブを使用します。
$ python2.7 pkg/main.py
Traceback (most recent call last):
File "pkg/main.py", line 2, in <module>
print string.ascii_uppercase
AttributeError: 'module' object has no attribute 'ascii_uppercase'
$ python2.7 pkg/main2.py
Traceback (most recent call last):
File "pkg/main2.py", line 3, in <module>
print string.ascii_uppercase
AttributeError: 'module' object has no attribute 'ascii_uppercase'
の有無にかかわらず、Python 3.5 と同じです。
print
ステートメントを両方のファイルで変更します。)
$ python3.5 pkg/main.py
Traceback (most recent call last):
File "pkg/main.py", line 2, in <module>
print(string.ascii_uppercase)
AttributeError: module 'string' has no attribute 'ascii_uppercase'
$ python3.5 pkg/main2.py
Traceback (most recent call last):
File "pkg/main2.py", line 3, in <module>
print(string.ascii_uppercase)
AttributeError: module 'string' has no attribute 'ascii_uppercase'
私はこれの他のバリエーションをテストしました。代わりに
string.py
という名前のディレクトリを作成しました。
string
のみを含む、空の
__init__.py
-- からインポートを発行するのではなく
main.py
を持つ。
cd
にする。
pkg
を実行し、REPLから直接importを実行しました。これらのバリエーションはいずれも(またそれらの組み合わせも)、上記の結果を変えませんでした。このことは、私が読んだ
__future__
ディレクティブと絶対インポート
で簡単に説明できそうです。 以下 (これはPython 2のドキュメントからですが、この文はPython 3でも同じドキュメントで変更されていません)。
sys.path
(...)
プログラム起動時に初期化されるため、このリストの最初の項目となります。
path[0]
は、Python インタープリタを起動するために使用されたスクリプトを含むディレクトリです。スクリプトディレクトリが利用できない場合(インタープリタが対話的に起動された場合や、スクリプトが標準入力から読み込まれた場合など)。path[0]
は空文字列です。 これは Python に現在のディレクトリのモジュールを最初に検索するように指示します。
では、何が足りないのでしょうか?なぜ
__future__
また、この2つの文書、および記述と実際の動作の間の矛盾はどのように解決されるのでしょうか?
解決方法は?
変更履歴がぞんざいな表現になっている。
from __future__ import absolute_import
は、何かが標準ライブラリの一部であるかどうかを気にしません。
import string
は、常に絶対インポートをオンにした標準ライブラリ・モジュールを与えるとは限りません。
from __future__ import absolute_import
というのは、もしあなたが
import string
は、Python が常にトップレベルの
string
モジュールではなく
current_package.string
. しかし、Python がどのファイルが
string
モジュールになります。を実行すると
python pkg/script.py
pkg/script.py
は、Pythonにとってはパッケージの一部には見えません。通常の手続きに従って
pkg
ディレクトリがパスに追加され、すべての
.py
のファイルは
pkg
ディレクトリは、トップレベルのモジュールのように見えます。
import string
見つける
pkg/string.py
は、相対インポートを行っているからではなく
pkg/string.py
はトップレベルのモジュールであるように見える
string
. これが標準ライブラリでないことは
string
モジュールは出てきません。
の一部として実行するには
pkg
パッケージの場合、次のようになります。
python -m pkg.script
この場合
pkg
ディレクトリはパスに追加されません。しかし、カレント・ディレクトリはパスに追加されます。
また、いくつかのボイラープレートを
pkg/script.py
の一部としてPythonに扱わせることができます。
pkg
パッケージとして実行された場合でも
if __name__ == '__main__' and __package__ is None:
__package__ = 'pkg'
しかし、これは
sys.path
. を削除するには、いくつかの追加処理が必要です。
pkg
ディレクトリをパスから削除し、もし
pkg
の親ディレクトリがパス上にない場合は、それもパス上に貼り付ける必要があります。
関連
-
Python Decorator 練習問題
-
[解決済み】ImportError: sklearn.cross_validation という名前のモジュールがない。
-
[解決済み】Python: OverflowError: 数学の範囲エラー
-
[解決済み] パラメータに**(ダブルスター/アスタリスク)、*(スター/アスタリスク)がありますが、これはどういう意味ですか?
-
[解決済み] フルパスでモジュールをインポートするには?
-
[解決済み] 億の相対的輸入
-
[解決済み] 相対パスからモジュールをインポートする
-
[解決済み】if __name__ == "__main__": は何をするのでしょうか?
-
[解決済み】__str__と__repr__の違いは何ですか?
-
[解決済み】Pythonに三項条件演算子はありますか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
Python カメの描画コマンドとその例
-
pyCaret効率化乗算器 オープンソース ローコード Python機械学習ツール
-
Python LeNetネットワークの説明とpytorchでの実装
-
Python Pillow Image.save jpg画像圧縮問題
-
[解決済み】numpyの配列連結。"ValueError:すべての入力配列は同じ次元数でなければならない"
-
[解決済み】socket.error: [Errno 48] アドレスはすでに使用中です。
-
[解決済み】syntaxError: 'continue' がループ内で適切に使用されていない
-
[解決済み】ImportError: bs4という名前のモジュールがない(BeautifulSoup)
-
[解決済み】 'numpy.float64' オブジェクトは反復可能ではない
-
[解決済み】django インポートエラー - core.managementという名前のモジュールがない