Last Updated: 2/6/2024, 5:44:57 AM

# PEP 328 - 複数行の import
そして 絶対 import と相対 import

この記事は PEP 328 - Imports: Multi-Line and Absolute/Relative (opens new window) の翻訳になります。この PEP には、複数行の import と相対 import が導入された背景が記されています。

# 括弧付き import 
from Tkinter import (Tk, Frame, Button, Entry, Canvas, Text,
    LEFT, DISABLED, NORMAL, RIDGE, END)
# 相対 import
from .moduleY import spam
from .moduleY import spam as ham
from . import moduleY
from ..subpackage1 import moduleY
from ..subpackage2.moduleZ import eggs
from ..moduleA import foo
from ...package import bar
from ...sys import path

相対 import が導入された背景としては、標準ライブラリ、 pip でインストールしたライブラリの名前を 上書きされるのを避けるためのようです。以下は訳文からの抜粋になります。

  • import はパッケージを取り扱おうとすると不明瞭なものになりうる。 パッケージ内においては import foo がそのパッケージ内のモジュールか それとも外側のモジュールか、はっきりとしない。 (より正確に言えば、ローカルにあるモジュールもしくはパッケージは、 sys.path から直接ハングアップしているモジュールもしくはパッケージを隠すことができる。)

この記事は Python の import 文ってなに? の補足のために PEP 238 を翻訳したものです。

本文

# 概要 - Abstract

import 文には2つの問題がある。

The import statement has two problems:

  • 長い import 文は書くのが難しく、PEP 8 に従おうとすると様々なねじれが起こってしまう。
  • Long import statements can be difficult to write, requiring various contortions to fit Pythonic style guidelines.
  • import はパッケージを取り扱おうとすると不明瞭なものになりうる。 パッケージ内においては import foo がそのパッケージ内のモジュールか それとも外側のモジュールか、はっきりとしない。 (より正確に言えば、ローカルにあるモジュールもしくはパッケージは、 sys.path から直接ハングアップしているモジュールもしくはパッケージを隠すことができる。)
  • Imports can be ambiguous in the face of packages; within a package, it's not clear whether import foo refers to a module within the package or some module outside the package. (More precisely, a local module or package can shadow another hanging directly off sys.path.)

最初の問題に対して、複数の名前を包むのに括弧を使うことを提案する、 これによって、複数行の値に対する Python の標準的なメカニズムを適用できるようになる。

For the first problem, it is proposed that parentheses be permitted to enclose multiple names, thus allowing Python's standard mechanisms for multi-line values to apply.

2つ目の問題に対して、パッケージ相対インポートを参照するときには特別な構文(先頭にドット)を使用して、 その他のすべての import 文はデフォルトで絶対 import (sys.path からのみを検索するように)にすることを提案する。

For the second problem, it is proposed that all import statements be absolute by default (searching sys.path only) with special syntax (leading dots) for accessing package-relative imports.

# 予定 - Timeline

Python 2.5 においては、この新しい絶対 import の仕様を次のように書くことによって使うことができる。

from __future__ import absolute_import

In Python 2.5, you must enable the new absolute import behavior with

相対 import を自由に使うかもしれません。 Python 2.6 では、暗黙の相対 import を行う如何なる import 文に対しても DeprecationWarning が起こります(これは相対 import 構文を使う from <> import にも適用されます)。

You may use relative imports freely. In Python 2.6, any import statement that results in an intra-package import will raise DeprecationWarning (this also applies to from <> import that fails to use the relative import syntax).

# 括弧付き import の背景
- Rationale for Parentheses

現在、モジュールやパッケージからたくさんの名前を import したい場合は、 いくつかあるあまり綺麗ではない書き方から 1 つを選ばなければならない。

Currently, if you want to import a lot of names from a module or package, you have to choose one of several unpalatable options:

バックスラッシュを使い行を継続させる:

Write a long line with backslash continuations:

from Tkinter import Tk, Frame, Button, Entry, Canvas, Text, \
    LEFT, DISABLED, NORMAL, RIDGE, END

複数行の import を書く:

Write multiple import statements:

from Tkinter import Tk, Frame, Button, Entry, Canvas, Text
from Tkinter import LEFT, DISABLED, NORMAL, RIDGE, END

import * という選択肢はない ^^

(import * is not an option ;- )

これらの代わりに、複数行の import 文を書くために Python でよく使われるまとめ方(括弧)を使えるようにするべきだ。

Instead, it should be possible to use Python's standard grouping mechanism (parentheses) to write the import statement:

from Tkinter import (Tk, Frame, Button, Entry, Canvas, Text,
    LEFT, DISABLED, NORMAL, RIDGE, END)

この部分の提案は当初から BDFL から承認を受けていた。

This part of the proposal had BDFL approval from the beginning.

括弧のサポートは Python 2.4 から追加された。

Parentheses support was added to Python 2.4.

# 絶対 import の背景
- Rationale for Absolute Imports

Python 2.4 より前のバージョンでは、パッケージの中にあるモジュールを読んだとき、

import foo

In Python 2.4 and earlier, if you're reading a module located inside a package, it is not clear whether

これが別のパッケージのトップレベルモジュールなのか、 それとも自分と同じパッケージの中にある他のモジュールを指しているのか、 パッと見ただけではすぐには分からなかった。 Python のライブラリが拡張されるにつれ、 より多くの既存のパッケージ内のモジュールが、 突然そして偶然に、標準ライブラリを隠してしまうことがあった。 これはパッケージ内で解決するには非常に難しい問題だった、 なぜなら、import で指定された foo が 実際にどちらのモジュールを指しているかを判別する方法がないからである。 この不明瞭さを解決するために、上記のように import foo と指定された場合は 常に sys.path から到達可能なモジュールまたはパッケージを指すように提案された。 これを絶対 import と呼ぶ。

refers to a top-level module or to another module inside the package. As Python's library expands, more and more existing package internal modules suddenly shadow standard library modules by accident. It's a particularly difficult problem inside packages because there's no way to specify which module is meant. To resolve the ambiguity, it is proposed that foo will always be a module or package reachable from sys.path. This is called an absolute import.

python-dev コミュニティは絶対 import をデフォルトにした、 なぜなら絶対 import は一般的な使用方法だし、 絶対 import は(パッケージ内で)相対 import する全ての機能を提供することができるからである。

The python-dev community chose absolute imports as the default because they're the more common use case and because absolute imports can provide all the functionality of relative (intra-package) imports -- albeit at the cost of difficulty when renaming package pieces higher up in the hierarchy or when moving one package inside another.

この表現はコードの意味を変えてしまうため、 絶対 import は Python 2.5, 2.6 ではオプショナルな機能であり、 次のコードを書くことで有効にすることができる。

from __future__ import absolute_import

Because this represents a change in semantics, absolute imports will be optional in Python 2.5 and 2.6 through the use of

この部分の提案については当初から BDFL の承認を得られていた。

This part of the proposal had BDFL approval from the beginning.

# 相対 import の背景
- Rationale for Relative Imports

絶対 import に目がいくにつれて、 そもそも相対 import は許されるべきかという疑問が起こりる。 いくつかの実例が示されてきた、 このうちもっとも重要なのは サブパッケージを編集することなく大きなパッケージの構造を再構成できるということだ。 加えてパッケージの内側のモジュールは 相対 import 無しには簡単には import できないということである。

With the shift to absolute imports, the question arose whether relative imports should be allowed at all. Several use cases were presented, the most important of which is being able to rearrange the structure of large packages without having to edit sub-packages. In addition, a module inside a package can't easily import itself without relative imports.

Guido は相対 import の考えを承認した、 しかしその書き方(構文)については多くの同意は得られなかった。 相対 import は import するにあたり名前を明示して列挙しなければならない (ここは訳が怪しいです。)。 (即ち、そのまま import foo と書けば、常に絶対 import になる。)

Guido approved of the idea of relative imports, but there has been a lot of disagreement on the spelling (syntax). There does seem to be agreement that relative imports will require listing specific names to import (that is, import foo as a bare term will always be an absolute import).

ここにいくつか候補がある。

(1) まず Guido から:

Here are the contenders:

(1) One from Guido:

これと

from .foo import bar

and

そしてこれ

from ...foo import bar

これらの2つの書式は、2つの異なる提案された意味を持っている。 1つの意味は、それぞれのドットは1つのレベルを表している。 ドットの数を数える煩雑さについては多くの不評があった。

These two forms have a couple of different suggested semantics. One semantic is to make each dot represent one level. There have been many complaints about the difficulty of counting dots.

もう一方の選択肢は1つのレベルの相対 import しか許さないということである。 これについては多くの機能を失っており、 1つドットが書かれているだけでは見逃してしまうことを不満に思っている。

Another option is to only allow one level of relative import. That misses a lot of functionality, and people still complained about missing the dot in the one-dot form.

最後の選択肢は相対モジュールやパッケージを見つけるアルゴリズムを定義することだ、 ここでの目標は「明示的であることは、暗黙的であるより良い」である (提案されたアルゴリズムは、現在のパッケージディレクトリから 最終的なパッケージの親がヒットする上に向けてまでことだ。)。

The final option is to define an algorithm for finding relative modules and packages; the objection here is "Explicit is better than implicit". (The algorithm proposed is "search up from current package directory until the ultimate package parent gets hit".)

ある人はセパレータとして "-" や "^" のような他の表記を提案した。 ある人は "*" を提案した。

from *.foo import bar

Some people have suggested other punctuation as the separator, such as "-" or "^". Some people have suggested using "*":

(2) 次の選択肢はいくつかの提案を混ぜ合わせたものです。

The next set of options is conflated from several posters:

これと

from __pkg__.__pkg__ import

そしてこれ

from .__parent__.__parent__ import

and

(Guido を含めた)多くの人々が、これらが醜いと判断していますが、しかし、これらは明白です。 全体的に見て、より多くの人がより短いオプションとして __pkg__ を好んでいます (訳注: 訳が怪しい)

Many people (Guido included) think these look ugly, but they are clear and explicit. Overall, more people prefer __pkg__ as the shorter option.

(3) 1つの提案は配下にあるパッケージの参照だけを許すことだった。 言い換えれば、パッケージツリーよりも高いモジュールを参照する 相対 import を使えなくするということだ。 そうなると、あなたは次のいずれかを実行することができる。

(3) One suggestion was to allow only sibling references. In other words, you would not be able to use relative imports to refer to modules higher in the package tree. You would then be able to do either

これか

from .spam import eggs

もしくはこれ

import .spam.eggs

or

(4) ある人は数字でどれだけ親を遡るかを示すことを好むものもいた。

(4) Some people favor allowing indexed parents:

from -2.spam import eggs

この例においては、カレントディレクトリから import する場合は、シンプルである (訳注 他の事例と同じ書式で、どこがシンプルなのか分からない)

In this scenario, importing from the current directory would be a simple

from .spam import eggs

(4) 最後に、パッケージを掘り下げるために import から from ... import に変更するのが嫌な人たちがいます。 彼らは完全に import の構文を書き換えることを提案しました:

(4) Finally, some people dislike the way you have to change import to from ... import when you want to dig inside a package. They suggest completely rewriting the import syntax:

これか

from MODULE import NAMES as RENAME searching HOW

あるいはこれ

import NAMES as RENAME from MODULE searching HOW
    [from NAMES] [in WHERE] import ...

or

しかしながら、これは到底 Python 2.5 に実装できそうにない(変更が大きすぎる)、 そして相対 import を許してしまうことは、私たちがいま必要としているものにとって 十分にクリティカルである (特に standard import が絶対 import に変わるのであれば(standard import ってなんだ?))。 それ以上に、この構文の提案はいくつかの明らかな問題がある。

However, this most likely could not be implemented for Python 2.5 (too big a change), and allowing relative imports is sufficiently critical that we need something now (given that the standard import will change to absolute import). More than that, this proposed syntax has several open questions:

(4-1) 正確な提案された構文は?(どの括弧が、どの情況でオプショナルなのか?)

(4-1) What is the precise proposed syntax? (Which clauses are optional under which circumstances?)

(4-2) searching clause は、どれほどの範囲まで影響を及ぼすのか? 言い換えれば、

(4-2) How strongly does the searching clause bind? In other words, do you write:

このように書くのか

import foo as bar searching XXX, spam as ham searching XXX

それともこのように書くのか

import foo as bar, spam as ham searching XXX

or

# Guido の決定 - Guido's Decision

Guido は相対 import は、ドットを前に書く書式にすることを宣告した。 1つだけドットを前に書いた場合、カレントパッケージから始まる相対 import であることを示している。 2つないしそれ以上ドットを前に書いた場合、モジュールに対して親への相対 import を与えます、 1つのドットにつき1つ親ディレクトリへと遡ります (訳注 意訳しました。)。 ここにパッケージの例があります。

Guido has Pronounced [1] that relative imports will use leading dots. A single leading dot indicates a relative import, starting with the current package. Two or more leading dots give a relative import to the parent(s) of the current package, one level per dot after the first. Here's a sample package layout:

package/
    __init__.py
    subpackage1/
        __init__.py
        moduleX.py
        moduleY.py
    subpackage2/
        __init__.py
        moduleZ.py
    moduleA.py

以下のファイルは moduleX.py または subpackage1/__init__.py であり、 新しく提案された構文の正しい使い方を示しています。

from .moduleY import spam
from .moduleY import spam as ham
from . import moduleY
from ..subpackage1 import moduleY
from ..subpackage2.moduleZ import eggs
from ..moduleA import foo
from ...package import bar
from ...sys import path

Assuming that the current file is either moduleX.py or subpackage1/__init__.py, following are correct usages of the new syntax:

末尾の行に書かれたものは文法的には正しいですが、明白に非推奨となっています(Guido の言葉を借りれば "insane" です)。

Note that while that last case is legal, it is certainly discouraged ("insane" was the word Guido used).

相対 import は常に from <> import を使わなければなりません; import <> であれば絶対 import です。 もちろん先頭のドットを除いて絶対 import に from <> import を使うこともできます。 import .foo が禁止されている理由は

Relative imports must always use from <> import; import <> is always absolute. Of course, absolute imports can use from <> import by omitting the leading dots. The reason import .foo is prohibited is because after

import XXX.YYY.ZZZ

と書けば

then

XXX.YYY.ZZZ

式として使うことができます。しかし

is usable in an expression. But

.moduleY

と書いてしまうと式としては使えせん。

is not usable in an expression.

# 相対 import と__name__
- Relative Imports and __name__

相対 import は、パッケージの階層におけるモジュールの位置を調べるために、 モジュールの __name__ 属性を使います。 もしモジュールの名前がパッケージの情報を含んでいない場合 (例えば __name____main__ が代入されていた場合)、 そのモジュールが実際にファイルシステムのどこにあるかに関わらず、 相対 import は、そのモジュールがトップレベルモジュールであるとみなして動作します。

Relative imports use a module's __name__ attribute to determine that module's position in the package hierarchy. If the module's name does not contain any package information (e.g. it is set to '__main__') then relative imports are resolved as if the module were a top level module, regardless of where the module is actually located on the file system.

# 相対 import と sys.modules における indirection entry
- Relative Imports and Indirection Entries in sys.modules

sys.modules
import したパッケージやモジュールを保存したリストです。 それらの具体的な動作については、以下を見るとわかりやすいかもしれません。 ただ indirection entry が何を指しているかは、 まだわかっていません。
from で import したときの対象モジュールの実行の流れ (opens new window)

パッケージが導入されたとき、sys.modules における indirection entry の概念が現れた^2 (opens new window)。 パッケージ内のモジュールの sys.modules の entry が None という値を持っていたとき、 それはモジュールが実際にトップレベルモジュールを参照していることを表していた。 例えば、'Sound.Effects.string' は sys.modules において None と言う値を持っているかもしれない。 それはその名前に解決されたどんな import も 実際にトップレベルの 'string'モジュールを import することであることを意味しました (訳注: 訳が怪しい)

When packages were introduced, the concept of an indirection entry in sys.modules came into existence ^2 (opens new window). When an entry in sys.modules for a module within a package had a value of None, it represented that the module actually referenced the top-level module. For instance, 'Sound.Effects.string' might have a value of None in sys.modules. That meant any import that resolved to that name actually was to import the top-level 'string' module.

これにより 相対 import が絶対 import に解決されることになっていたころは、そのための最適化が導入されました。 しかし、この PEP では絶対インポートと相対インポートの間に非常に明確な記述があるため、 この最適化は不要になりました。 絶対import と相対 import が唯一の利用可能な import の機能になると、 sys.modules の indirection entry はサポートされなくなります。

This introduced an optimization for when a relative import was meant to resolve to an absolute import. But since this PEP makes a very clear delineation between absolute and relative imports, this optimization is no longer needed. When absolute/relative imports become the only import semantics available then indirection entries in sys.modules will no longer be supported.

# 参考文献 - References

さらなる背景は、以下の python-dev のスレッドを参考にしてください。

For more background, see the following python-dev threads:

この文章はパブリックドメインです。
Source: https://github.com/python/peps/blob/master/pep-0328.txt

This document has been placed inthe public domain.
Source: https://github.com/python/peps/blob/master/pep-0328.txt