本当に誰でも読める!! Pythonソースコードの読み方講座(第7回)キーワード編 3:Pythonの生命線?import文について

  • HOME
  • 本当に誰でも読める!! Pythonソースコードの読み方講座(第7回)キーワード編 3:Pythonの生命線?import文について

本記事は当社が発行しているシミュレーションメールマガジンVol.7の記事です。 シミュレーションメールマガジンの詳細・購読申込はこちら のサポートページから

プログラマにもノン・プログラマにも読んでいただきたい「Pythonコードの読み方」講座の第7回、今回はキーワード編の3回目として、import 文を扱います。 数値計算や最適化・機械学習からWebアプリケーション開発まで幅広く用いられる Python ですが、自分で一からすべての開発を行うことはまずありません。実装が複雑なコアの部分は必要な機能をまとめたプログラム(ライブラリと呼ばれます)をあらかじめ外部から取得したものを用意しておき、それを自分のプログラムから呼び出して使う、ということが一般的に行われます。

また、自分でプログラムを作っていく上でも、ある程度規模が大きくなってくるとプログラムを適当な単位でファイルやフォルダに分割して管理することが必要になります。このとき、あるファイルのプログラムから別ファイルのプログラムを呼び出す必要が生じます。

このような「外部のプログラムと連携したい」場合に使われるのが import 文です。import は第3回, 第4回で扱った Python のキーワード(予約語)のひとつで、外部プログラムを取り込む文を書くことができます。 今回は import にまつわるコードの読み方を紹介していきます。

 基本の読み方

import itertools # itertools モジュールをインポート
import my_module # my_module モジュールをインポート
import concurrent.futures # concurrent というモジュールの下にある futures モジュールをインポート
import pandas as pd # pandas というモジュールに pd という名前をつけてインポート

import の直後に書かれているものがモジュール名になります。最後の例のように as キーワードを添えて使うことで、モジュールに別名をつけることが可能になります。as を使わなかった場合はモジュール名がそのまま名前になります(my_module にアクセスしたければ my_moduleconcurrent.futures にアクセスしたければ concurrent.futures とそのまま記述すれば良いです)。

ファイルの先頭にこのように記述しておくことで、例えば以下のようにインポートしたモジュールを使うことができます:

for item in itertools.product([1,2,3], [10,20,30]):
    pass # itertools モジュールの持っている product 関数を利用
my_module.my_function(1) # my_module モジュールの持っている my_function 関数を利用
"""
↓ concurrent.futures モジュール, pandas モジュールの利用
モジュール名の記述方法はインポートの仕方に依存するので注意
"""
print(concurrent.futures.ProcessPoolExecutor())
df = pd.DataFrame()

また、from キーワードと組み合わせる以下のような書き方も存在します:

from . import my_module2 # ソースコードと同じ階層の my_module2 をインポート
from .. import my_module3 # ソースコードのひとつ上の階層の my_module3 をインポート
from .my_module4 import something # 同じ階層の my_module4 の something をインポート

これらはソースコードをパッケージ化している場合に利用できる書き方で、使う場合は多少の注意が必要ですが、読むぶんには「近くの階層に存在しているソースコードを呼び出せるようにしている」と思えば良いです。実際に、同じディレクトリやひとつ上のディレクトリに my_module2.py や my_modele3.py といったスクリプトが存在しているはずです。

もう少し実際的な使い方が知りたい方は手前味噌ですがこちらの記事も参考にしてみてください。

 モジュールの正体を知るには?

基本を抑えたところでコードの意味は理解できるようになりましたが、インポートしているものが実際に何なのかはどのように知ることができるのでしょうか?
例えば上記の例で import my_module が行われているとき、何を読み込んでいるのでしょうか?
実はいくつかの可能性があります:

  • my_module という標準モジュール(Python が公式に提供しており、最初から組み込まれていて使えるモジュール)が存在し、それを読み込んでいる
  • my_module というサードパーティモジュール(個人が各々開発しており、別途インストールすることで使えるモジュール)が存在し、それを読み込んでいる
  • カレントディレクトリ(プログラムを実行しているディレクトリ) に my_module.py という自作のソースコードがあり、これを読み込んでいる

これらのいずれに該当するかはカレントディレクトリを見たり、そのようなライブラリが存在するのか検索したりして調べる必要があります。 また、プログラムを実行できる場合、print してみるのが手っ取り早いかもしれません:

print(concurrent.futures)
"""出力例:
<module 'concurrent.futures' from 'C:\\Users\\hogehoge\\Python\\lib\\concurrent\\futures\\__init__.py'>"""

このような形で、ソースコードが存在するパスを表示してくれます。Python の標準モジュールであれば Python のインストールディレクトリに、サードパーティモジュールであればパッケージマネージャのインストール先に、自作のソースコードであればカレントディレクトリが表示されるでしょう。

 import はどこを探しに行く?

モジュールの正体がどれであっても原則として、import XXX と記述したとき、XXX というディレクトリ、もしくは XXX.py というファイルがどこかに存在していて、これを読み込んでいることになります。 import はどこにモジュールを探しに行くのでしょうか?また、複数の場所に XXX モジュールが存在した場合、どれが読み込まれるのでしょうか? その答えを知るには、ふたたびプログラムに聞いてみるのがよいでしょう:

import sys
print(sys.path)

上記を実行することでモジュールを探しに行く先の一覧リストを表示することができます。import を行ったときはこのリストの先頭から探して、最初に見つかったものを返すことになります(最後まで見つからなかった場合は ModuleNotFoundError になります)。 この中には大まかには

  • カレントディレクトリ
  • 環境変数 PYTHONPATH が指定しているディレクトリ群
  • Python 実行環境が要請しているディレクトリ群

などが並んでいる形になります。

 まとめ

今回は import 文の読み方と、半歩踏み込んで何を読み込んでいるのか、どこを読み込むのか、について紹介しました。 import 文はPythonの持つ多様なライブラリ資源にアクセスしたり、自前で大きなプログラムを使う際には必須の機能になります。 また、前回で紹介したように、出所の分からない変数が元をたどると import したモジュールだった、ということもあります。 プログラムを書かれる方も、読むだけの方もこの機会に詳しくなっていただけると幸いです。

豊岡 祥 株式会社 NTTデータ数理システム シミュレーション&マイニング部所属。
S4 Simulation System の開発のほか、機械学習・シミュレーション・数理最適化を幅広く扱い、分野を横断した問題解決に取り組んでいる。
入社後に競技プログラミングをはじめ、PGBATTLE2023にて企業の部団体3位入賞。

著書: 「XAI(説明可能なAI)──そのとき人工知能はどう考えたのか?」リックテレコム
趣味: 合唱
「数理科学の基礎知識」e-book無料ダウンロードはこちら