Pythonのimport文はfromで始まったりimportで始まったりする。ややこしい。そのパターンや記述する位置など、基本的な使い方を整理してみたい。

import文とは

import文とは、あるソースファイルの中に、他のソースファイルの中身を持ってくるための宣言文である。

このソースファイルは、自前のものでも良いし、既存のライブラリのものでも良い。また、モジュール全体をそのまま持ってくることもできるし、特定の変数や関数、クラスだけをインポートすることもできる。

モジュールという言葉が何を指すか、慣れないうちは混乱するかもしれない。import文と関連の深い、いくつかの用語を最初に整理しておく。

用語 意味
モジュール .py拡張子を持つ1つのファイル。
パッケージ 複数のモジュールを含むディレクトリ。少なくとも1つの__init__.pyを持つ。
ライブラリ 特定の目的のために用意された、1つ以上のモジュールやパッケージの集合。
名前空間 変数名、関数名、クラス名などの衝突を避けるために、インポート先で使われる識別子。

基本的な使い方

Pythonのimport文は、技術的にはファイルのどこにでも書ける。ただし、可読性や一貫性の観点から先頭に書くことが慣習となっている。

python
import モジュール名

このモジュール名は、インポートしたいファイル名(xxx.pyxxxの部分)である。これがそのまま名前空間となる。

つまりxxx.変数名xxx.関数名()のような形で、そのモジュール内で定義されたアレコレを使える。

また、名前空間を任意に指定したいときは、asキーワードを使って以下のように書く。

python
import モジュール名 as お好きな名前

もし存在しないモジュールをインポートしようとすると、実行時にModuleNotFoundError: No module named 'モジュール'のようなエラーが出て処理が止まる。

書き方のパターン

Pythonのimport文の書き方には、いくつかパターンがある。

例えば複数のモジュールをインポートする場合は、モジュール名をカンマ区切りで追加することもできる。

python
// 複数のモジュールをインポートする場合
import モジュール名1, モジュール名2

asキーワードをつける場合は、そのままモジュール名の後ろに追加すれば良い。

python
// 複数のモジュールを別名でインポートする場合
import モジュール名1 as 任意の名前1,モジュール名2 as 任意の名前2

この、複数のモジュールをカンマ区切りで書くインポートは、見ての通り長くなる。そのため1つ1つ改行してインポートする方法が推奨される。Pythonのコードフォーマッターも、カンマ区切りで書かれたインポートは強制的に分割する。

また、モジュール内の特定の変数、関数、クラス名のみをインポートしたい時は、以下のように書く。

python
from モジュール名 import 識別名

識別名は、変数名や関数名、クラス名である。この書き方の場合、複数の識別名をカンマ区切りでつなげても良い。

なお、JavaScriptのexportのように、元ファイル側で特別なキーワードを指定する必要はない。Pythonのモジュールは、デフォルトですべての変数、関数、クラスをエクスポート(別のファイルからインポート)できる。

モジュールの検索方法

なんの断りもなくimport モジュール名 as 任意の名前とサンプルを書いてきたが、正確にはモジュール名の箇所はモジュールのパスである。

単にモジュール名を指定した場合、Pythonのインポートシステムはまずスクリプトが実行されているディレクトリから該当するモジュールを探す。そこで見つからなければ標準ライブラリを探し、それでも見つからなければサードパーティのライブラリを探す。

最終的に見つからなければModuleNotFoundErrorとなる。

ちなみにこの読み込み順は、sys.pathという変数で確認できる。

python
import sys
print(sys.path)

絶対インポートと相対インポート

無印でモジュール名を指定した場合、現在のディレクトリ、標準ライブラリ、サードパーティのライブラリと順に検索される。これはsys.pathに記載されたパスの代替、つまり変則的な絶対パス指定である。

現在のディレクトリより深い位置にあるモジュールをインポートしたい場合は、以下のように.を使って書く。

python
import パッケージ名.モジュール名

パッケージ名はディレクトリ名、モジュール名はファイル名と同義である。

また、パッケージの中にサブパッケージがあり、この中でインポート文を使いたい場合、頭に’.’をつけるとその位置からの相対パスを指定できる。この場合、fromを使った形でインポートしたい変数、関数、クラスを指定する必要がある。

python
# 現在の階層のモジュールをインポート
from .モジュール名 import 識別名

# 1つ下の階層のモジュールをインポート
from .パッケージ名.モジュール名 import 識別名

# 1つ上の階層にあるパッケージ内のモジュールをインポート
from ..パッケージ名.モジュール名 import 識別名

相対インポートは、そのファイルがメインプログラムとして実行されないことが前提となっている。相対インポートを使ったファイルを直接実行するとImportErrorが出る。

……などともっともらしく書いたが、Pythonのパッケージ周りをまだあんまり理解していないので、この辺りの情報には間違いがあるかもしれない。

PEP 8が推奨するインポート文の書き方

Pythonには、コミュニティで標準化されているガイドラインがある。このガイドラインは、Python Enhancement Proposals、略してPEPsと呼ばれる。PEPsはナンバリングで管理されており、PythonのスタイルガイドはPEP 8にまとめられている。

PEP 8には、インポート文の項目もある。

PEP 8曰く、

  1. import x,yのようにカンマで繋げるべからず。1つずつ改行してインポートせよ。
  2. ただしfrom x import y, zみたいな形は許すぞよ。
  3. インポート文は常にファイルの最上部へ配置せよ。
  4. インポートは、標準、サードパーティ、自前の順にせよ。そして各グループを空白で区切れ。
  5. パッケージレイアウトが複雑な場合を除き、なるべく絶対インポートを使え。
  6. ワイルドカードインポート(from モジュール名 import *)は避けよ。名前衝突の危険あり。

だそうである。別に守らなくても死なないが、弁えてはおきたいところだ。

参考