Pythonのパッケージを作ってPyPIに登録する

# Pythonのパッケージを作ってPyPIに登録する
2018年12月9日時点でPythonパッケージを配布用に登録する手順をまとめます。

## 作ったもの
顔文字を出力します。
[コード](https://github.com/shibuiwilliam/py-kaomoji)

### 使い方
インストールは`pip`です。

```bash

> pip install py-kaomoji
```

kaomojiを`import`して使うと、顔文字が出力されます。

```python
from kaomoji import kaomoji
kao = kaomoji.Kaomoji()

" ランダムに顔文字を出力
kao()
> '(ヾﾉヾﾉヾﾉヾﾉヾﾉ･ω･`)ヾﾉｼﾞｪｯﾄｽﾄﾘｰﾑﾅｲﾅｲ'

# 'たのしい'顔文字を出力
kao.kaomoji("たのしい")
> "たのしい！✌('ω'✌ )三✌('ω')✌三( ✌'ω')✌"
```

またはコマンドラインで`kao`と入力しても顔文字が出力されます。

```bash
> kao
.･ヾ(｡>д<)ｼ
```

その他の使い方は[コード](https://github.com/shibuiwilliam/py-kaomoji)をご参照ください。

## まずGithubレポジトリを作る
ソースコード管理用にGithubレポジトリを作ります。
[こちら](https://github.com/new)からプロジェクトの設定を入力して`Create repository`します。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/55384/48c2b5f1-9d38-122b-4464-eb2351c8bc2c.png)

.gitignoreはPython、ライセンスはMIT Licenseにします。
このあたりは忘れがちですが、この時点で設定しておくと楽です。

## Pythonプログラムを作る
Githubからレポジトリをcloneしてきて、その中にプログラムを作っていきます。

```bash
> git clone git@github.com:<your acccount name>/<project name>.git
```

Pythonのプログラムを作ります。
ディレクトリ構成はこんな感じです。

```bash
|-- LICENSE
|-- MANIFEST.in
|-- README.md
|-- data
|   |-- __init__.py
|   |-- kaomojis.yml
|   `-- load_kaomojis.py
|-- kaomoji
|   |-- __init__.py
|   |-- __main__.py
|   `-- kaomoji.py
|-- setup.py
`-- test
    |-- __init__.py
    `-- test_kaomoji.py
```

`data/kaomojis.yml`にyaml形式で顔文字の一覧が入っています。

```yaml
あおり:
  - ( ◜◡‾)
  - (*^▽^*)
  - (⌒▽⌒)
  - o(^▽^)o
あげ:
  - ↑↑↑∩(*’ヮ’)∩↑↑↑
あせ:
  - (ﾟ∀ﾟ ；)ﾀﾗｰ
あたふた:
  - ヽ(´･ω･｀ヽ)
あつい:
  - (｡>﹏<)あㄘ”ゅいー
```

これをdictでロードして出力する、というのがプログラムの全容です。

## setup.pyを作る
setup.pyを作ります。
全文は以下のような感じになっています。

```python
#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""The setup script."""

import sys
from setuptools import setup, find_packages

with open('README.md', encoding='utf-8') as readme_file:
    readme = readme_file.read()


info = sys.version_info

setup(
    name='py_kaomoji',
    version='0.1.3.4',
    description='This is a Kaomoji library for Python for Japanese.',
    long_description=readme,
    long_description_content_type='text/markdown',
    author='shibuiwilliam',
    author_email='*******@gmail.com',
    url='https://github.com/shibuiwilliam/py-kaomoji',
    packages=find_packages(),
    include_package_data=True,
    keywords='kaomoji',
    classifiers=[
        'Development Status :: 2 - Pre-Alpha',
        'Natural Language :: English',
        "License :: OSI Approved :: MIT License",
        'Programming Language :: Python :: 3.6',
        "Operating System :: OS Independent",
    ],
    entry_points = {
        'console_scripts': ['kao=kaomoji.kaomoji:main'],
    },   test_suite="test",
)

```

基本的な書き方は[公式ドキュメント](https://docs.python.org/3.6/distutils/setupscript.html)のとおりですが、公式ドキュメントで説明されていない点として以下を追加しています。

- マークダウンでREADMEを書いている。
    - Githubではマークダウンで良いが、PyPIで表示するには `long_description_content_type='text/markdown` が必要。
- entry_pointでコマンド化
    - コマンドに`kao`を追加するには以下を追加する必要があります。
     
```python
    entry_points = {
        'console_scripts': ['kao=kaomoji.kaomoji:main'],
```

上記で`kao`コマンドはkaomojiディレクトリのkaomoji.pyファイル内の`def main()`を実行しています。

これで`python3 setup.py sdist`または`python3 setup.py install`を実効することでパッケージを作ることができますが、その前にMANIFEST.inが必要になります。

## MANIFEST.in
顔文字データはすべてdata/kaomojis.ymlに入っていますが、Pythonはデフォルトでは.py以外のファイルをパッケージに含めません。
data/kaomojis.ymlをパッケージに含めるために、以下をMANIFEST.inに記述します。

```
recursive-include data *
```

## 配布用のパッケージにしてみる
setup.pyを使って配布可能なパッケージにするために、まずは`python setup.py check`してみます

```bash
> python setup.py check
/opt/anaconda3/lib/python3.6/distutils/dist.py:261: UserWarning: Unknown distribution option: 'long_description_content_type'
  warnings.warn(msg)
running check
```

`check`でsetup.pyの内容の不備を確認しています。
ひとつwarningが出ていますが、これは無視します。

続いて配布可能なパッケージを作ります。
コマンドは`python setup.py sdist`です。

```bash
> python setup.py sdist
/opt/anaconda3/lib/python3.6/distutils/dist.py:261: UserWarning: Unknown distribution option: 'long_description_content_type'
  warnings.warn(msg)
running sdist
running egg_info
writing py_kaomoji.egg-info/PKG-INFO
writing dependency_links to py_kaomoji.egg-info/dependency_links.txt
writing entry points to py_kaomoji.egg-info/entry_points.txt
writing top-level names to py_kaomoji.egg-info/top_level.txt
reading manifest file 'py_kaomoji.egg-info/SOURCES.txt'
reading manifest template 'MANIFEST.in'
writing manifest file 'py_kaomoji.egg-info/SOURCES.txt'
running check
creating py_kaomoji-0.1.3.5
creating py_kaomoji-0.1.3.5/data
creating py_kaomoji-0.1.3.5/kaomoji
creating py_kaomoji-0.1.3.5/py_kaomoji.egg-info
creating py_kaomoji-0.1.3.5/test
copying files to py_kaomoji-0.1.3.5...
copying MANIFEST.in -> py_kaomoji-0.1.3.5
copying README.md -> py_kaomoji-0.1.3.5
copying setup.py -> py_kaomoji-0.1.3.5
copying data/__init__.py -> py_kaomoji-0.1.3.5/data
copying data/kaomojis.yml -> py_kaomoji-0.1.3.5/data
copying data/load_kaomojis.py -> py_kaomoji-0.1.3.5/data
copying kaomoji/__init__.py -> py_kaomoji-0.1.3.5/kaomoji
copying kaomoji/__main__.py -> py_kaomoji-0.1.3.5/kaomoji
copying kaomoji/kaomoji.py -> py_kaomoji-0.1.3.5/kaomoji
copying py_kaomoji.egg-info/PKG-INFO -> py_kaomoji-0.1.3.5/py_kaomoji.egg-info
copying py_kaomoji.egg-info/SOURCES.txt -> py_kaomoji-0.1.3.5/py_kaomoji.egg-info
copying py_kaomoji.egg-info/dependency_links.txt -> py_kaomoji-0.1.3.5/py_kaomoji.egg-info
copying py_kaomoji.egg-info/entry_points.txt -> py_kaomoji-0.1.3.5/py_kaomoji.egg-info
copying py_kaomoji.egg-info/top_level.txt -> py_kaomoji-0.1.3.5/py_kaomoji.egg-info
copying test/__init__.py -> py_kaomoji-0.1.3.5/test
copying test/test_kaomoji.py -> py_kaomoji-0.1.3.5/test
Writing py_kaomoji-0.1.3.5/setup.cfg
Creating tar archive
removing 'py_kaomoji-0.1.3.5' (and everything under it)

```

カレントディレクトリに`dist/py_kaomoji-0.1.3.5.tar.gz`が出来上がっていれば成功です。

## インストール
前項で作った配布用パッケージをインストールしてみます。
コマンドは`python setup.py install`です。

```bash
> python setup.py install
/opt/anaconda3/lib/python3.6/distutils/dist.py:261: UserWarning: Unknown distribution option: 'long_description_content_type'
  warnings.warn(msg)
running install
    ...<中略>...
zip_safe flag not set; analyzing archive contents...
data.__pycache__.load_kaomojis.cpython-36: module references __file__
creating 'dist/py_kaomoji-0.1.3.5-py3.6.egg' and adding 'build/bdist.linux-x86_64/egg' to it
removing 'build/bdist.linux-x86_64/egg' (and everything under it)
Processing py_kaomoji-0.1.3.5-py3.6.egg
creating /opt/anaconda3/lib/python3.6/site-packages/py_kaomoji-0.1.3.5-py3.6.egg
Extracting py_kaomoji-0.1.3.5-py3.6.egg to /opt/anaconda3/lib/python3.6/site-packages
Removing py-kaomoji 0.1 from easy-install.pth file
Adding py-kaomoji 0.1.3.5 to easy-install.pth file
Installing kao script to /opt/anaconda3/bin

Installed /opt/anaconda3/lib/python3.6/site-packages/py_kaomoji-0.1.3.5-py3.6.egg
Processing dependencies for py-kaomoji==0.1.3.5
Finished processing dependencies for py-kaomoji==0.1.3.5

> pip list | grep py-kaomoji
py-kaomoji                         0.1.3.5  
```

最後に`pip list | grep py-kaomoji`で表示されていればOKです。

この時点では`pip install py-kaomoji`でインストールすることはできません。
`pip install`できるようにするためにはPyPIに登録する必要があります。

## PyPIに登録する
### PyPIにアカウント登録
PyPIに登録するためには、まずはアカウントを作る必要があります。
[PyPI](https://pypi.org/)からRegisterして自分のアカウントを作ります。

Webフォームで登録後、メールアドレス確認が必要です。
確認メールが届くので、認証しましょう。

### PyPIにパッケージ登録
PyPIにパッケージを登録するにはtwineを使います。
[twine](https://pypi.org/project/twine/)はPyPIにパッケージ登録して配布可能にするためのユティリティツールです。
`pip`でインストール可能です。

```bash
> pip install twine
```

インストール後、パッケージのディレクトリで`twine upload  dist/*`を実行するだけで配布可能（`pip install`可能）にできます。

```bash
> twine upload  dist/* 
Enter your username: <pypi username>
Enter your password: <pypi password>
Uploading distributions to https://upload.pypi.org/legacy/
Uploading py_kaomoji-0.1.3.6.tar.gz
100%|###########################################################################################################################################################| 12.8k/12.8k [00:01<00:00, 7.25kB/s]
```

これで[顔文字](https://pypi.org/project/py-kaomoji/)をPyPIに登録することができました。
`pip install py-kaomoji`できることを確認します。

```bash

> pip install py-kaomoji
Collecting py-kaomoji
  Downloading https://files.pythonhosted.org/packages/7c/8a/822776d1ce2cb9d2b0cb1484cf45d6e06d56b6f1f128d1f6d612145bd820/py_kaomoji-0.1.3.6.tar.gz
Building wheels for collected packages: py-kaomoji
  Running setup.py bdist_wheel for py-kaomoji ... done
  Stored in directory: /root/.cache/pip/wheels/98/6f/ce/bb16c5901e7b4eed76d66a3ae660064d936a277e0d129284a1
Successfully built py-kaomoji
Installing collected packages: py-kaomoji
Successfully installed py-kaomoji-0.1.3.6
```

## 最後に
(≧ω≦(｡･_･｡)ゝｷﾞｭｯ ヾ(*･ω･)ﾉｼ (*ﾟ▽ﾟ*) o(>_< *)(* >_<)oｼﾞﾀﾊﾞﾀ :;(∩＞_＜∩);