Pythonで自作パッケージをつくる

この記事ではPythonのライブラリを自作する手順について説明していきます。
自作ライブラリというとハードルが高く感じられますが、ローカルにPython環境をイチから構築できている方であれば難くないレベル感だと思います。

# そもそもパッケージって？
## パッケージとは
プログラムを書く上で、様々な機能を提供してれる便利なプログラム群です。過去に誰かが作った機能を使い回せるため、すべてを新しく自分でプログラムする必要はなく、効率的にプログラムを書くことができます。広くライブラリとも呼ばれます。

> 現在ではプログラムを書く時でも、わざわざゼロから書く必要は無いわけであり、先人が残したライブラリを利用すればかなり少ない時間や労力でうまく動作するプログラムを完成させることができる。
[Wikipediaより](https://ja.wikipedia.org/wiki/%E8%BB%8A%E8%BC%AA%E3%81%AE%E5%86%8D%E7%99%BA%E6%98%8E)

そして、パッケージにはPythonをインストールしただけで使える**標準ライブラリ**と別途インストールの必要な**外部ライブラリ**があります。

- **標準ライブラリ**
    - Pythonに標準で付いている
    - 機能としては、OSへのアクセス・日付・ファイル圧縮等々
- **外部ライブラリ**
    - 別途インストールが必要
    - 基本的にpipでインストールする

インストールしているライブラリをみるにはターミナルで以下を叩きます。

```terminal
pip list
```

## 構成している要素
Pythonのライブラリとしては「モジュール」と「パッケージ」の2つの概念があります。ひとことで「ライブラリ」というと、この2つを同時に指します。
![パッケージ概念.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547099/9e7bf1ce-663d-dd80-2fb6-6e3c9d0bde7b.jpeg)

- **モジュール**
  - .pyファイルのこと
  - つまり関数やクラスの集まり
  - ファイル名がモジュール名となる
- **パッケージ**
  - 複数のモジュールを1つのディレクトリにまとめたもの
  - 基本的に関連する機能（モジュール）をまとめておく

パッケージをつくるには、適切なディレクトリ構成でモジュールや必要なファイルを配置する必要があります。

# パッケージをつくる
今回、作成パッケージが提供する機能としては**動物の鳴き声を返す機能**とします。
`animalsパッケージ > catモジュール > greet関数`を指定すると`meow`と出力してくれる感じです。

## モジュールをつくる
実際にここから手を動かして、モジュールから作っていきましょう。
動物は猫、犬、ニワトリを作りを用意しました。以下の各Pythonのファイルを用意したら、それらはモジュールとなります。

```python:cat.py
def greet():
    print("meow")
```

```python:dog.py
def greet():
    print("bowwow")
```

```python:chicken.py
def greet():
    print("cock a doodle doo")
```

モジュールはフォルダ内に以下のように配置します。
最終的に、`animals`をパッケージ化したいということを想定したディレクトリ構成となっています。

```terminal
animal_greets
└── animals
    ├── chicken.py
    ├── cat.py
    └── dog.py
```


ここまではPythonを普通に書いただけですね。次でパッケージ化を行いましょう。

# パッケージ化
先ほど作成した`birds`フォルダと`mammalians`フォルダをパッケージ化します。
まず、ディレクトリ内に`__init__.py`ファイルと`setup.py`を配置しましょう。

```terminal
animal_greets
├── animalians
|   ├── __init__.py ←追加
|   ├── cat.py
|   ├── chicken.py
|   └── dog.py
└── setup.py ←追加
```

`__init__.py`は、モジュール検索用のマーカで、パッケージ内のモジュールを正しく認識させるものらしいです。←
中身は以下のように書くことで、外部から呼び出す際にモジュール名を省略できます。

```python:__init__.py
from animals.cat import greet as cat_greet
from animals.chicken import greet as chicken_greet
from animals.dog import greet as dog_greet
```

`setup.py`はpipによるインストールのために必要なファイルです。
中身は以下のように書きます。他に色々な項目があるようですが、最小限に書く場合は以下で問題ないです。

```python:setup.py
from setuptools import setup, find_packages

setup(
    name='animal_greet',
    version='1.0',
    packages=find_packages()
)
```
これでパッケージのコードは完成です。

# パッケージをインストールする
ローカルに先ほど作成したパッケージをインストールして動かしてみましょう。
まず、パッケージと同じディレクトリ階層で以下のコマンドを実行します。

```terminal
$ pip install .
```
するとビルドが行われてpipにインストールされます。
以下のコマンドでインストール済みのライブラリを確認して、`animal-greet`があれば成功です。

```terminal
$ pip list
Package             Version
------------------- ---------
animal-greet        1.0
```

実際に使えるか試してみます。以下はPythonインタプリタから`animal-greet`の`animals`モジュールを利用した例です。

```
$ Python3
>>> import animals
>>> animals.cat_greet()
meow
>>> animals.dog_greet()
bowwow
>>> animals.chicken_greet()
cock a doodle doo
```
ちゃんとパッケージから関数を呼び出せました！


# 参考
- [Pythonチュートリアル](https://docs.python.org/ja/3/tutorial/index.html)
- [Pythonで自分だけのクソライブラリを作る方法](https://zenn.dev/karaage0703/articles/db8c663640c68b)
- [Python の __init__.py とは何なのか](https://qiita.com/msi/items/d91ea3900373ff8b09d7)