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

Modified: | Tags: Python

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

モジュールをインポートする順番

モジュールの種類によって以下の順番でグループ分けしてインポートするのが推奨されている。グループ間は空白行で区切る。

  1. 標準ライブラリ
  2. サードパーティライブラリ
  3. ローカルライブラリ(自作のライブラリ)

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ディレクトリに以下のようにファイル(モジュール)が格納されている。__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でクラスなどが定義されている。CounterOrderedDictなどはモジュールではなくクラス。

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

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

関連カテゴリー

関連記事