個人ライブラリのススメ(for Python🐍)

[Pythonその2 Advent Calendar 2020](https://qiita.com/advent-calendar/2020/python2) 18日目の記事です。アドベントカレンダーもあと一週間ですね、頑張っていきましょう。

# はじめに
このモジュールを別のプロジェクトでも使いたいとか、[PyPI](https://pypi.org/) に上げるほどではないけど、みんなに配布したいなーと思ったことはありませんか？特に、プロジェクトごとに毎回同じコードを書いたり、コピペするのはもったいないです。

実は **[GitHub](https://github.com/) に上げたモジュールを `pip` からインストールすることができます(プライベートリポジトリでも行けます)**。今回は、その方法と、自分が実際に作ってみて気を付けた方がいいと感じたところを紹介していきます。

# 自作ライブラリを作る🐍
それでは、さっそく始めていきましょう。今回は簡単な例として、**引数 `your_name` を受け取って、挨拶をする関数 `hello(your_name)`** を作ります。

今回作成したサンプルリポジトリは以下のリンクです：
[<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/398510/5e88676d-3f97-1313-96b4-f2fbd1974f6e.png" alt="advent-calendar2020_python2" width="400px" >](https://github.com/syakoo/advent-calendar2020_python2)

## 実行環境
今回使用した環境を以下に示します：

- Python 3.8.5

## ディレクトリ構成
このような感じで、ファイルとディレクトリを作成しましょう：

```bash
├── setup.py
└── src
    └── hello_world
        ├── __init__.py
        └── say_hello.py
```

## コードを書く
まずは、作りたい関数を実装します：

```python:src/hello_world/say_hello.py
def hello(your_name: str) -> str:
    """挨拶を返す関数

    Args:
        your_name (str): あなたの名前

    Returns:
        str: 挨拶
    """
    return f'Hello, {your_name}.'

```

次に、モジュールのインターフェース部分です。`hello` という関数を読み込んでおきます。書かなかったらどうなるかについては実行確認で説明します。

```python:src/hello_world/__init__.py
from .say_hello import hello
```

## setup.py
このファイルには、パッケージ化して配布する際の設定を書いていきます。細かい内容は「[2. setup スクリプトを書く | Python Documentation](https://docs.python.org/ja/3.8/distutils/setupscript.html)」にありますので、そちらを参照してください。ちなみに今回は、リンク先の公式ドキュメントで使用している `distutils` を拡張した `setuptools` を使用しています。

```python:setup.py
import setuptools


setuptools.setup(
    name="hello-world",
    version="0.0",
    author="syakoo",
    author_email="hogehoge@hoge.hoge",
    description="Say Hello.",
    url="https://github.com/syakoo/advent-calender2020_python2",
    packages=["hello_world"],
    package_dir={"hello_world": "src/hello_world"},
    python_requires=">=3.8"
)

```

## 実行確認
これで必要なファイルは全て揃いました。`GitHub` にプッシュしましょう。ここで、**プライベートリポジトリに上げても大丈夫**です。自分専用のライブラリが作れますね。

このライブラリを使う場合は、使用したいプロジェクトで

```console
$ pip install git+https://github.com/<YOUR_NAME>/<REPO_NAME>
```
とすれば取得できます。つまり、GitHub の URL の先頭に `git+` を追加するだけです。

### 例: 上で作った hello-world を実行する
上の通りにインストールします：

```bash
$ pip install git+https://github.com/syakoo/advent-calendar2020_python2
```
そして、適当なファイルを作って、下のように書きます：

```python
from hello_world import hello


print(hello("syakoo"))
# Hello, syakoo.
```
実行が確認できました！ちなみに、`src/hello_world/__init__.py` に何も書かなかった場合は、

```python
from hello_world.say_hello import hello
```

と書く必要があります。使い分けが大事ですね。

# 気を付けた方がいいと思ったこと
上では個人ライブラリの作成の仕方を紹介しました。ここからは、自分が実際にライブラリを作ってみて、こうした方がいいと思ったことを重要度高い順で紹介していきます。**私的な意見が多くなるので、あくまで一意見として考えてくださると幸いです。**

## 1. ファイルを更新したらバージョンを上げること
一度ライブラリを上げてファイルを更新したときは、`setup.py` に記載しているライブラリのバージョンを更新しましょう。なぜなら、ファイルを更新する前にライブラリをインストールしていたら、ファイルを更新してからもう一度インストールしても、**同じバージョンと判断されて更新されませんでした。**

といったことから、バグ修正やアップデートによりファイルを更新したらバージョンも上げるようにしましょう。

## 2. 関数や変数は型ヒントやドキュメントを書くこと
これはライブラリに限らず勧めたい事なのですが、自作ライブラリの関数を使おうとしたときに型情報やドキュメントが書いてあるかないかでは大きな差があると思います。書くようにしましょう。

**型・ドキュメントなし**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/398510/f464880a-dce1-9604-745d-dcbaf6ca3346.png)
**型・ドキュメントあり**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/398510/434ea7a5-c92b-f1a1-2403-057e37d0a8bd.png)

## 3. バージョンは 3.8 がオススメ
現在の Python のバージョンは `3.9` で、`3.10` も控えている状況ですが、AWS Lambda や Azure Functions でサポートされているバージョンは**現在は** 3.8 です。Docker 使えば何とかなるとは思いますが、個人的には 3.8 をオススメしています。

## 4. 開発時に用いるライブラリはインストールさせないこと
ライブラリの開発時は、`pytest` や `autopep8`、`flake8` などのライブラリを使うと思います。しかし、ライブラリ使用時には使わないため `setup.py` の `install_requires` には書かないようにしましょう。

# おわりに
Python のコードを再利用したい場合はジャンジャン個人ライブラリ化していきましょう🐍