Python, importの使い方(from, as, PEP8の推奨スタイル, 注意点など)
Pythonではimport
文を使って標準ライブラリやpipでインストールしたパッケージ、自作のパッケージなどをインポートできる。
import
の対象となるディレクトリのパスの確認・追加については以下の記事を参照。
また、自作のライブラリをインポートする際に相対パスで上位ディレクトリ・サブディレクトリを指定したい場合は以下の記事を参照。
モジュールとパッケージとライブラリ
モジュール
Pythonでは関数やクラスなどを定義したファイルをモジュールという。
パッケージ
モジュールと__init__.py
を含むディレクトリをパッケージ(Regular packages)という。__init__.py
には初期化コードを記述する。空のファイルでもよい。
Python3.3以降では、__init__.py
を含まないディレクトリもパッケージとしてインポートできるようになった。このようなパッケージを名前空間パッケージ(Namespace packages)という。
ライブラリ
厳密に定義されたものではないが、パッケージやモジュールのことをライブラリと呼ぶ場合もある。
以降、import
の基本的な使い方としてモジュールをインポートする方法を説明したあと、パッケージを扱う場合の注意点を述べる。
importの基本的な使い方
例として標準ライブラリのmathモジュールをインポートする。
以下のようにimport <モジュール名>
とするとモジュールがmodule
型のオブジェクトとしてインポートされる。print(<モジュール名>)
で出力するとどのファイルを読み込んでいるかが確認できる。
import math
print(type(math))
# <class 'module'>
print(math)
# <module 'math' from '/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/lib-dynload/math.cpython-37m-darwin.so'>
<モジュール名>.<関数名>
、<モジュール名>.<定数名>
のようにモジュール内で定義された関数や定数などを使用できる。
print(math.radians(180))
# 3.141592653589793
print(type(math.radians))
# <class 'builtin_function_or_method'>
print(math.pi)
# 3.141592653589793
print(type(math.pi))
# <class 'float'>
なお、radians()
は度をラジアンに変換する関数でpi
は円周率が格納された定数。
モジュールの関数や変数を直接使えるようにインポートしたい場合は後述のfrom
を使う。import <モジュール名>.<関数名>
などとするとエラーとなるので注意。
PEP8で推奨されているimportの書き方
Pythonのスタイルガイド(コーディング規約)であるPEP8ではimport文の書き方も記されている。
なお、あくまでもスタイルガイドなのでこのように書かないとエラーになるというわけではない。
複数モジュールのインポート
仕様ではimport文のあとに複数のモジュールをカンマで区切って書くことができるが、PEP8では推奨されていない。一行ずつ分けて書く。
# Wrong:
import os, sys
# Correct:
import os
import sys
次に説明するようにfrom
を使って関数や変数、クラスなどをインポートする場合はカンマで区切ってもOK。
from math import pi, radians
モジュールをインポートする順番
モジュールの種類によって以下の順番でグループ分けしてインポートするのが推奨されている。グループ間は空白行で区切る。
- 標準ライブラリ
- サードパーティライブラリ
- ローカルライブラリ(自作のライブラリ)
PEP8には書かれていないが、グループ内はアルファベット順に並べられることが多い。
import math
import os
import sys
import Requests
import my_package1
import my_package2
関数や変数、クラスを指定してインポート: from ... import ...
from
を使って、モジュールで定義された関数や変数、クラスなどを指定してインポートできる。
単独でインポート
from <モジュール名> import <識別子名>
で関数などをインポートできる。
インポートした関数などは<識別子名>
で直接使用できる。インポートされるのは指定したもののみでモジュール自体はインポートされない。他の関数などを使用しようとするとエラーNameError
になる。
from math import pi
print(pi)
# 3.141592653589793
# print(math.radians(180))
# NameError: name 'math' is not defined
複数まとめてインポート
同じモジュールから複数の関数や変数などをまとめてインポートする場合はカンマで区切る。
from math import pi, radians
print(pi)
# 3.141592653589793
print(radians(180))
# 3.141592653589793
一行が長くなってしまう場合は、括弧()
を使えば改行して書ける。
from math import (
e,
exp
)
print(e)
# 2.718281828459045
print(exp(1))
# 2.718281828459045
ここでe
は自然対数の底(ネイピア数)で、exp()
は指数関数。以下の記事を参照。
すべてインポート(非推奨)
ワイルドカード*
を使うとモジュールで公開されているすべての関数や変数などがインポートされて使えるようになる。
from math import *
print(pi)
# 3.141592653589793
print(cos(0))
# 1.0
print(sin(0))
cos()
, sin()
は三角関数。以下の記事を参照。
モジュール内で__all__
が定義されていると、__all__
に含まれている名前のみがインポートされる。
なお、*
を使ったインポートはどの名前がどの名前空間に存在しているか不明瞭であるためPEP8では推奨されていない。
別名をつけてインポート: import ... as ...
as
を使うとモジュールや関数などに別名をつけてインポートできる。別名をつけた場合、元の名前は使えない。
モジュールに別名をつける例。
import math as m
print(m.pi)
# 3.141592653589793
# print(math.pi)
# NameError: name 'math' is not defined
変数に別名をつける例。
from math import pi as PI
print(PI)
# 3.141592653589793
# print(pi)
# NameError: name 'pi' is not defined
NumPyやpandasなど、省略名でインポートするのが慣例となっているライブラリもある。
import numpy as np
import pandas as pd
パッケージからモジュールなどをインポート
パッケージからモジュールなどをインポートする場合、その構成や__init__.py
の記述によってインポートの方法に注意が必要。
なお、基本的にはドキュメントにどのようにインポートすればいいか書いてあるのでその通りにすればよい。ここでは、色々なパターンがあるという説明のためいくつか紹介する。
urllibの例
標準ライブラリのurllibを例として、パッケージからモジュールやクラスをインポートする。
- urllib --- URL を扱うモジュール群 — Python 3.11.3 ドキュメント
- cpython/Lib/urllib at main · python/cpython · GitHub
urllib
ディレクトリに以下のようにファイル(モジュール)が格納されている。__init__.py
は空。
urllib/
├── __init__.py
├── error.py
├── parse.py
├── request.py
├── response.py
└── robotparser.py
import urllib
とした場合、配下のモジュールを使うことはできない。例えばurllib.error
とするとエラーAttributeError
となる。
import urllib
print(type(urllib))
# <class 'module'>
print(urllib)
# <module 'urllib' from '/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/urllib/__init__.py'>
# print(urllib.error)
# AttributeError: module 'urllib' has no attribute 'error'
import <パッケージ名>.<モジュール名>
でモジュールをインポートする必要がある。
import urllib.error
print(urllib.error)
# <module 'urllib.error' from '/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/urllib/error.py'>
print(urllib.error.HTTPError)
# <class 'urllib.error.HTTPError'>
from <パッケージ名> import <モジュール名>
でもOK。
from urllib import error
print(error)
# <module 'urllib.error' from '/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/urllib/error.py'>
print(error.HTTPError)
# <class 'urllib.error.HTTPError'>
クラスを指定してインポートすることも可能。
from urllib.error import HTTPError
print(HTTPError)
# <class 'urllib.error.HTTPError'>
このように、__init__.py
で特に初期化コードが記述されていない場合は、パッケージをインポートするのではなく配下のモジュールをインポートする必要があるので注意。
なお、IPython, Jupyter Notebookを使っている場合、urllib
をインポートしただけでurllib.parse
も使えるようになるが、これはIPythonの起動時の処理に起因する挙動。
collectionsの例
異なる例としてcollectionsを挙げる。
collections
ディレクトリは以下のような構成になっている。
collections/
├── __init__.py
└── abc.py
collectionsではurllibのように配下にモジュールのファイルが格納されているのではなく、__init__.py
でクラスなどが定義されている。Counter
やOrderedDict
などはモジュールではなくクラス。
このような場合、パッケージをインポートすると<パッケージ名>.<クラス名>
としてクラスを使用できる。
import collections
print(collections)
# <module 'collections' from '/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/collections/__init__.py'>
print(collections.Counter)
# <class 'collections.Counter'>
import <パッケージ名>.<クラス名>
としてクラスをインポートすることはできない。
# import collections.Counter
# ModuleNotFoundError: No module named 'collections.Counter'
from
を使ってクラスをインポートするのはOK。
from collections import Counter
print(Counter)
# <class 'collections.Counter'>
NumPyの例
サードパーティライブラリとしてNumPyを例とする。
NumPyではnumpy
ディレクトリの__init__.py
の中で各サブパッケージをインポートしている。
このため、それぞれのモジュールをインポートする必要はなく、import numpy as np
とするだけで各種の関数などが使える。
scikit-learnの例
異なる例としてscikit-learnを挙げる。
scikit-learnではsklearn
ディレクトリの__init__.py
ではサブパッケージをインポートしていない。
このため、サブパッケージを明示的にインポートする必要がある。
from sklearn import datasets, model_selection, svm, metrics
正しくインポートできない(エラーが発生する)場合
インポート関係の主なエラーとして以下の2つがある。
ModuleNotFoundError
モジュールが見つからないというエラー。
ModuleNotFoundError: No module named 'xxx'
単純に名前が間違っているか、importの対象となるディレクトリのパスの指定が間違っている可能性がある。
特に自作のモジュールやパッケージを別のディレクトリ(違う階層)からインポートする際はややこしいので注意。
上のcollectionsの例のように、モジュールではなくクラスなどをインポートしようとした場合にもModuleNotFoundError
となる。関数やクラスなどをインポートする場合はfrom
を使う。
AttributeError
インポートしたモジュールに指定した属性がないというエラー。
AttributeError: module 'xxx' has no attribute 'yyy'
単純な名前間違いのほか、想定と異なるファイルがインポートされている可能性がある。
例えば、import <モジュール名>
としたときに最優先でモジュールが探索されるのは実行スクリプトファイルと同一ディレクトリであるため、そこに<モジュール名>.py
というファイルがあるとそのファイルがモジュールとしてインポートされてしまう。
print(<モジュール名>)
で想定の場所からインポートされているかを確認して、想定外のファイルがインポートされている場合は該当ファイルをリネームするなどして対処する。