Python, importの使い方(from, as, PEP8の推奨スタイル, 注意点など)

Pythonではimport文を使って標準ライブラリやpipでインストールしたパッケージ、自作のパッケージなどをインポートできます。 ここでは以下の内容について説明します。

モジュールとパッケージとライブラリ importの基本的な使い方 PEP8で推奨されているimportの書き方 オブジェクト(関数や変数、クラス)を指定してインポート: from ... import ... 別名をつけてインポート: import ... as ... パッケージからモジュールやオブジェクトをインポート 正しくインポートできない場合

importの対象となるディレクトリのパスを確認したり追加したりしたい場合は

また、自作のライブラリをインポートする際に相対パスで上位ディレクトリ・サブディレクトリを指定したい場合は

モジュールとパッケージとライブラリ

Pythonでは関数やクラスなどをまとめて書いたファイルをモジュールという。

  1. モジュール (module) — Python 3.6.5 ドキュメント

また、モジュールと__init__.pyを含むディレクトリをパッケージ(Regular packages)という。init.pyには初期化コードを記述するが、空のファイルでも問題ありません。 Python3.3以降では、init.pyを含まないディレクトリもパッケージとしてインポートできるようになりました。このようなパッケージを名前空間パッケージ(Namespace packages)という。

  1. インポートシステム パッケージ — Python 3.6.5 ドキュメント

なお、Pythonには「ライブラリ」という用語はないが、パッケージやモジュールのことをライブラリと呼ぶ場合もあります。厳格に定義されたものではない。 以降、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文の書き方も記されています。

PEP 8 imports -- Style Guide for Python Code | Python.org

なお、あくまでもスタイルガイドなのでこのように書かないとエラーになるというわけではない。 複数モジュールのインポート 仕様ではimport文のあとに複数のモジュールをカンマで区切って書くことができるが、PEP8では推奨されていません。一行ずつ分けて書きます。

# NG
import os, sys

# OK
import os
import sys

次に説明するようにfromを使ってオブジェクト(関数や変数、クラス)をインポートする場合はカンマで区切っても問題ありません。

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を例として、パッケージからモジュールやオブジェクトをインポートします。

21.5. urllib — URL を扱うモジュール群 — Python 3.6.5 ドキュメント cpython/Lib/urllib at master · python/cpython

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 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 モジュール名でも問題ありません。

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の起動時の処理に起因する挙動。

import urllib.parse fails when Python run from command line - Stack Overflow

collectionsの例 異なる例としてcollectionsを挙げる。

8.3. collections — コンテナデータ型 — Python 3.6.5 ドキュメント

collectionsディレクトリは以下のような構成になっています。 collections/ ├── init.py └── abc.py

collectionsではurllibのように配下にモジュールのファイルが格納されているのではなく、init.pyでクラスなどが定義されています。CounterやOrderedDictなどはモジュールではなくクラス。

cpython/Lib/collections at master · python/cpython

このような場合、パッケージをインポートした上でパッケージ名.クラス名としてクラスを使用できます。

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 collections.Counter
# ModuleNotFoundError: No module named 'collections.Counter'

fromを使ってクラスをインポートするのは問題ありません。

from collections import Counter

print(Counter)
# <class 'collections.Counter'>

NumPyの例 サードパーティライブラリとしてNumPyを例とします。 NumPyではnumpyディレクトリの__init__.pyの中で各サブパッケージをインポートしています。

numpy/numpy: Numpy main repository

このため、それぞれのモジュールをインポートする必要はなく、import numpy as npとするだけで各種の関数などが使えます。 scikit-learnの例 異なる例としてscikit-learnを挙げる。 scikit-learnではsklearnディレクトリの__init__.pyではサブパッケージをインポートしていません。

scikit-learn/scikit-learn: scikit-learn: machine learning in Python

このため、サブパッケージを明示的にインポートする必要があります。

from sklearn import datasets, model_selection, svm, metrics

なお、基本的にはドキュメントにどのようにインポートすればいいか書いてあるので、init.pyを読む必要はない。

正しくインポートできない場合

インポート関係の主なエラーとして以下の2つがあります。 ModuleNotFoundError モジュールが見つからないというエラー。 ModuleNotFoundError: No module named 'xxx'

単純に名前が間違っているか、importの対象となるディレクトリのパスの指定が間違っている可能性があります。

あるいは、上のcollecrionsの例のように、モジュールではなくクラスなどをインポートしようとした場合にもModuleNotFoundErrorとなります。関数やクラスなどのオブジェクトをインポートする場合はfromを使います。 AttributeError インポートしたモジュールに指定した属性がないというエラー。 AttributeError: module 'xxx' has no attribute 'yyy'

単純な名前間違いのほか、想定と異なるファイルがインポートされている可能性があります。 例えば、import モジュール名としたときに最優先でモジュールが探索されるのは実行スクリプトファイルと同一ディレクトリであるため、そこにモジュール名.pyというファイルがあるとそのファイルがモジュールとしてインポートされてしまいます。

print(モジュール名)で想定の場所からインポートされているかを確認して、想定外のファイルがインポートされている場合は該当ファイルをリネームするなどして対処します。

Last Updated: 6/26/2019, 10:53:11 PM