【図で解説】Pythonで自作モジュール(or パッケージ)をimportするために知っておきたいこと

当ページのリンクには広告が含まれています。

Pythonには様々なモジュール(or パッケージ)が提供されており、 import することで簡単に使えるようになりまが、もちろん自分で作ったモジュールをライブラリとしてimport することも可能です。

但し注意点があって、フォルダのどこに置くかによって import の指定方法が変わってきます。

今回は、フォルダ階層に応じた import の方法について解説したいと思います。

目次

表記や実行環境に関する前提について

この記事を読み進める上で、表記や実行環境に関するいくつかの前提条件があります。

ここでは、その前提条件について簡単に解説しておきます。

プログラムの実行フォルダについて

掲載しているプログラムを実行して試したい場合は、次のことを満たしておいてください。

  • プログラムが格納されているフォルダがカレントフォルダになっている
  • python プログラム名、又は python -m プログラム名 で実行する

というのは、Python Prompt (又は Anaconda Prompt)から実行する場合と、python.exe の引数に渡して実行する場合とでは、若干挙動が異なるからです。

モジュール、パッケージ、ライブラリの表記の違いについて

一般的には、モジュールが集まったものがパッケージ、パッケージが集まったものがライブラリという考え方になります。

Python の場合は、モジュールが1つ以上格納されているフォルダのことをパッケージと呼んでおり、ライブラリは複数フォルダが集まったものなので、それほど大きな違いはありません。

そこで、本記事では任意の階層にあるモジュールをimportするという視点で解説をしています。

記事の中ではパッケージとライブラリを同じ意味として表記している場合がありますが、いずれの場合も、「モジュールが格納されているフォルダ」という意味と解釈して下さい。

自分と同じフォルダに存在するモジュールをimportするには

プログラムと同じ階層のモジュールをimportするのは非常に簡単で、import でモジュール名を指定するだけです。

下記は calc というモジュール名をimport する場合の例です。モジュール名に拡張子は含みませんので、calc.py ではなく calc であることにご注意ください。

自分より下の階層にあるモジュール(or パッケージ)をimportするには

Pythonの場合、「プログラムから import 出来るのは、自分と同じ階層にいるモジュールのみ」という制約があります。

ちなみに、パッケージ同士であればこの制限はありません。今回の場合はパッケージではなくプログラム(アプリケーション)からモジュール、もしくはパッケージを呼び出したいので、この制約に引っかかってしまいます。

明示的に検索パスを指定

解決方法としては、PYTHONPATHにモジュール(又はパッケージ)が含まれるフォルダを指定するか、Pythonがパッケージを検索するためのリストに追加してあげる必要があります。

プログラムで対応する場合は、先頭に下記の3行を追加してから、自作モジュール(or パッケージ)を import する必要があります。

__file__ には実行中のプログラムのパスが格納されていて、'.' という文字列と結合してパスを作っています。

ちなみに、Python Prompt (又は anaconda Prompt)からプログラムを実行するときは、この記述が無くても import 出来ますが、最終的に Python.exe を経由して実行したい場合は、この記述を入れておく方が安心です。

参照の記述

話は元に戻りますが、参照の仕方は次の様になります。

  from パッケージ名 import モジュール名

Python の場合、パッケージはフォルダ名を指しますから、実質は下記と同じです。

 from フォルダ名 import モジュール名

ちなみに、モジュール名はPythonファイルから拡張子'.py' を抜いたもの です。

下記は mylibと、その下のsublib というフォルダから、それぞれ calc1.py 、calc2.pyに格納されている関数をimportする例です。

__init__.py で 複数モジュールをimportする

1つ下の階層から import したい場合、あらかじめモジュールを格納したフォルダの中に __init_.py を作成しておくと、少しだけ記述を簡略できます。

__init_.py は、フォルダをパッケージとして扱うためのマーカー且つコンストラクタの役目を持っています。パッケージとして認識させたい場合は、たとえ空ファイルであっても __init__.py を入れておきましょう。

__init__.py はコンストラクタと同じなので、初期化処理を記述することが出来ます。
プログラムから import mylib を行うと、mylib 直下の__init__.pyが最初に実行されます。

下記の例では、 from mylib.calc1 import * が記述されていますが、これは 「mylibフォルダのcalc1.py に記述されている全ての関数やクラスを importする」という動作になります。

複数のモジュールがあれば同様に記載していくことで、import mylib という1行のみで複数のモジュールを一括して import 出来ます。

この例では2つ下の階層(sublib)からの参照例も記載していますが、基本的には mytlb を起点に、各フォルダをピリオド '.' で繋いでいくだけOKです。

もちろん、それぞれのフォルダには、 __init__.py を記述することは忘れないでください。

更に下の階層もまとめてimportする

自分より下の階層にフォルダを作成した場合、下図の様に __init__.py に import sublib を記述しておくと、import mylib の1行だけで配下のモジュールも含めて import 出来ます。

ただ、使わないモジュールも import されてしまうので、やりすぎには注意が必要です。

異なる階層(1つ上や同一階層など)にあるモジュールをimport する

プログラムが置かれているフォルダとは異なる階層にあるフォルダ(1つ上や同じ階層にある別フォルダなど)からモジュールをimportする場合、環境変数又は sys.path.appendを使います。

自分の配下にあるフォルダから import する場合との違いは、相対パスの指定部分だけです。

実行するプログラムより1つ上の階層なので、 '..' という相対バスを設定します。

1つ上ではなく、全く異なる階層のフォルダを参照する時は、そのフォルダが置かれている相対パスを指定します。

もちろん、絶対パスで指定しても構いません。

今回は sys.path.append で末尾に追加しましたが、もし同じパッケージが既に存在しており、そちらより自作のパッケージを優先したい場合は、sys.path.insert を使う方法もあります。

全く別のドライブにあるモジュールをimport する

同一ドライブに存在するモジュールであれば、環境変数や sys.path に相対パスを指定することでモジュールが参照できますが、異なるドライブに置かれたモジュールの場合は、ドライブ名も含めて指定しなければなりません。

必然的に、ドライブを指定する=絶対パスの指定となります。

例えば、Fドライブの直下に mylib が存在する場合、次の様に指定します。

まとめ

python.exe の引数にプログラムを渡して実行する場合、実行するプログラムと同じ階層のモジュールしかimport 出来ません。

自分より下の階層、あるいは全く別の階層にあるモジュールをimportするには、環境変数にそのパスを設定するか、sys.path.append でパッケージ検索リストに登録する必要があります。

但し、Python Prompt (又は Anaconda Prompt)でPythonのコンソールを立ち上げ、そこに張り付けて実行する場合のみ、カレントフォルダ直下にパッケージがある場合は import 可能です。

以上、Pythonのモジュールやパッケージを import する際のフォルダ階層別参照方法のまとめでした。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

コメント

コメントする

目次