自作モジュールのパッケージ化
前回、FastAPIでMatplotlibによるグラフを作成し、JavaScriptでHTML上に表示する方法を紹介しました。
今回は自分でパッケージを作ろうというお話しです。
同じような話題で自作関数のモジュール化の解説を前にしました。
モジュールの場合は一つの.pyファイルに記載した関数を使えるようにしたものでした。
パッケージというのはそのモジュールを何個も集めてフォルダにまとめたものになります。
ちなみにパッケージをいくつもまとめるとライブラリになります。
とあるプログラムを作っているときに、どうしても一つのファイルにまとめると長ーいプログラムとなってしまい、メンテナンスが大変になったので、そろそろパッケージやらライブラリを作ってみるかと思い腰を上げたのが今回のお話の発端です。
それでは始めていきましょう。
自作モジュールのおさらい
まずは簡単に自作モジュールのおさらいをします。
ということでこんな関数を作ってみました。
def plus(a, b):
return a+b
これを実行する.pyファイルに書けば「自作関数」です。
モジュールの場合は実行する.pyファイルではない別のファイルとして保存します。
フォルダ構成としてはこんな感じにしてみました。
test
├── libs
│ └── test1lib_dir
│ └── test1lib.py
└──test1
└── test1.py
先ほどのプログラムはtest1lib.pyとしてtest1lib_dirフォルダの中に保存されています。
次に先ほどのモジュールを使うプログラムファイルとしてtest1.pyがtest1フォルダの中に保存されています。
この場合、test1lib.pyのモジュールをインポートして使用するにはこんな感じになります。
import sys
sys.path.append('../libs')
from test1lib_dir import test1lib
a = 2
b = 5
c = test1lib.plus(a, b)
print(c)
実行結果
7
最初の2行「import sys」と「sys.path.append(‘../libs’)」はモジュールがある場所をPythonに教えている部分になります。
通常Pythonのライブラリ(pipでインストールしたものなど)はPythonのプログラム内の「site-package」というフォルダ内に保存されています。
自作の場合でも「site-package」フォルダにおけば、上記のコマンドは必要ないのですが、なかなかアクセスも悪く、他のライブラリを間違って消してしまうと大問題です。
そのため、今回のようにプログラムファイル側で場所を指定してやる方が安全だと思います。
モジュールの場所を指定したら、「from モジュールが入っているフォルダ import .pyファイルのファイル名」としてインポートします。
ちなみに「.pyファイルのファイル名」には最後の「.py」は必要ありません。
このようにインポートした後は「ファイル名.関数名」という形でファイル内の関数を呼び出すことができます。
ここまでが「自作モジュール」のお話です。
パッケージ化:__init__.py
それでは自作モジュールをパッケージ化していきましょう。
パッケージ化するにはモジュールが入っているフォルダに「__init__.py」(アンダーバーはinitの前後に2つずつ)というファイルを作成します。
ということでフォルダ構成的にはこんな感じになります。
test
├── libs
│ └── test2lib_dir
│ ├── __init__.py
│ └── test2lib.py
└──test2
└── test2.py
各ファイルの中身はこんな感じです。
from test2lib_dir.test2lib import plus
def plus(a, b):
return a+b
import sys
sys.path.append('../libs')
import test2lib_dir
a = 2
b = 5
c = test2lib_dir.plus(a, b)
print(c)
プログラム的には先ほどのtest1の時とほとんど変わっていないように見えますが、インポートの仕方が変わっています。
先ほどの自作モジュールの場合は「from モジュールが入っているフォルダ import .pyファイルのファイル名」としてインポートしていました。
今回、test2.pyでは「import モジュールが入っているフォルダ」となっています。
パッケージの場合、「import モジュールが入っているフォルダ」とすると、まずそのフォルダ内にある「__init__.py」を読みにいきます。
そして「__init__.py」でインポートしているライブラリをインポートします。
test2の場合、「from test2lib_dir.test2lib import plus」なので、「test2lib_dirフォルダ内にあるtest2libファイルのplusという関数をインポート」するというわけです。
でこれの何がいいのかですが、複数のモジュールを一度にインポートできるようになります。
例えばこんな感じで複数のモジュールをひとまとめにしたフォルダがあるとします。
test
├── libs
│ └── test3lib_dir
│ ├── __init__.py
│ ├── test31lib.py
│ └── test32lib.py
└──test3
└── test3.py
そしてそれぞれの中身をこんな感じにします。
from test3lib_dir.test31lib import plus
from test3lib_dir.test32lib import times
def plus(a, b):
return a+b
def times(a, b):
return a*b
import sys
sys.path.append('../libs')
import test3lib_dir
a = 2
b = 5
c = test3lib_dir.plus(a, b)
d = test3lib_dir.times(a, b)
print(c)
print(d)
「test3lib_dir」には「test31lib.py」と「test31lib.py」の2つのモジュールが入っていて、それぞれ「plus」関数と「times」関数が入っています。
そして「__init__.py」では両方の関数をインポートしています。
このように設定しておくとインポートする側のファイル「test3.py」では「import test3lib_dir」とするだけで「plus」も「times」も一度にインポートできます。
モジュールが数この場合はあまりありがたみがないですが、モジュールが多くなってくるにつれて、機能別にパッケージしていくと分かりやすくなります。
ちなみに一つのモジュールのファイルに複数の関数がある場合でそれら全てをインポートする場合には「*(アスタリスク)」を使って書くこともできます。
from test4lib_dir.test4lib import *
またここまでの「__init__.py」の例ではインポート文がそのフォルダ名で始まっていましたが、そのフォルダ内にある.pyファイルをインポートする場合、省略することも可能です。
from .test5lib import *
実を言うとパッケージ化やライブラリ化は結構面倒だなと思って避けていたのですが、やってみたら思ったよりもスッキリして早い段階で勉強しておくべきだったなと思っています。
次回はPythonですが話題が変わって、ピーク検出の方法を紹介します。
ではでは今回はこんな感じで。
コメント