概要
Python用のパッケージ管理ツールPoetryを使って郵便番号から住所を取得するPythonパッケージを作成しコマンドラインから実行できるようにしてみる。
作業ディレクトリ作成
mkdir -p /tmp/$(date +%Y%m%d) && cd $_
pwd # /tmp/$(date +%Y%m%d)
開発環境構築
python3 -m venv venv
source venv/bin/activate
poetry インストール
pipのバージョンが低いとコケるのでpipをアップデートしてからインストールを行う
pip install --upgrade pip
pip install poetry
新しいPythonプロジェクト zip_code_app の作成
poetry new --src zip_code_app
プロジェクト作成後のディレクトリ構造
/tmp/$(date +%Y%m%d)/zip_code_app
├── README.rst
├── pyproject.toml
├── src
│ └── zip_code_app
│ └── __init__.py
└── tests
├── __init__.py
└── test_zip_code_app.py
requests モジュールインストール
住所検索APIに問い合わせを行うために requests をインストール
cd /tmp/$(date +%Y%m%d)/zip_code_app
poetry add requests
requests がインストールされ
pyproject.toml
ファイルにrequests
が追記される。
[tool.poetry.dependencies]
python = "^3.7"
+requests = "^2.25.1"
>
[tool.poetry.dev-dependencies]
pytest = "^5.2"
郵便番号から住所を取得するプログラムを作成
vi /tmp/$(date +%Y%m%d)/zip_code_app/src/zip_code_app/core.py
import json
import requests
import sys
URL = 'http://zipcloud.ibsnet.co.jp/api/search?zipcode={}'
def zip_api(zip_code):
r = requests.get(URL.format(zip_code))
return r.json()
def main():
zip_code = sys.argv[1]
zip_json = zip_api(zip_code)
print(json.dumps(zip_json, ensure_ascii=False))
if __name__ == '__main__':
main()
core.py 作成後のディレクトリ構造
/tmp/20210710/zip_code_app
├── README.rst
├── poetry.lock
├── pyproject.toml
├── src
│ └── zip_code_app
│ ├── __init__.py
│ └── core.py ■ これが作成された
└── tests
├── __init__.py
└── test_zip_code_app.py
実行してみる
poetry run python /tmp/$(date +%Y%m%d)/zip_code_app/src/zip_code_app/core.py 100-0001 | jq .
{
"message": null,
"results": [
{
"address1": "東京都",
"address2": "千代田区",
"address3": "千代田",
"kana1": "トウキョウト",
"kana2": "チヨダク",
"kana3": "チヨダ",
"prefcode": "13",
"zipcode": "1000001"
}
],
"status": 200
}
テストコード作成
vi /tmp/$(date +%Y%m%d)/zip_code_app/tests/test_zip_code_app.py
from zip_code_app import __version__
from zip_code_app import core
def test_version():
assert __version__ == '0.1.0'
def test_zip_api():
expect = {
'message': None,
'results': [{'address1': '東京都',
'address2': '千代田区',
'address3': '千代田',
'kana1': 'トウキョウト',
'kana2': 'チヨダク',
'kana3': 'チヨダ',
'prefcode': '13',
'zipcode': '1000001'}],
'status': 200
}
actual = core.zip_api('100-0001')
assert expect == actual
テスト実行
poetry install
poetry run pytest /tmp/$(date +%Y%m%d)/zip_code_app/tests/test_zip_code_app.py -vv
======================================== test session starts ========================================
platform darwin -- Python 3.7.3, pytest-5.4.3, py-1.10.0, pluggy-0.13.1 -- /private/tmp/$(date +%Y%m%d)/venv/bin/python3
cachedir: .pytest_cache
rootdir: /private/tmp/$(date +%Y%m%d)/zip_code_app
collected 2 items
tests/test_zip_code_app.py::test_version PASSED [ 50%]
tests/test_zip_code_app.py::test_zip_api PASSED [100%]
========================================= 2 passed in 0.37s =========================================
## スクリプトを登録
vi pyproject.toml
```toml:pyproject.toml
[tool.poetry.scripts]
zip-code = "zip_code_app.core:main"
スクリプトを実行してみる
poetry run zip-code 100-0001 | jq .
{
"message": null,
"results": [
{
"address1": "東京都",
"address2": "千代田区",
"address3": "千代田",
"kana1": "トウキョウト",
"kana2": "チヨダク",
"kana3": "チヨダ",
"prefcode": "13",
"zipcode": "1000001"
}
],
"status": 200
}
パッケージをビルドする
poetry build
/tmp/20210710/zip_code_app
├── README.rst
|-- dist
| |-- zip_code_app-0.1.0-py3-none-any.whl ■ これが作成された
| `-- zip_code_app-0.1.0.tar.gz ■ これが作成された
├── poetry.lock
├── pyproject.toml
├── src
│ └── zip_code_app
│ ├── __init__.py
│ └── core.py
└── tests
├── __init__.py
└── test_zip_code_app.py
パッケージをインストール
ビルドしたパッケージからインストールする場合
pip install /tmp/20210710/zip_code_app/dist/zip_code_app-0.1.0-py3-none-any.whl
github で管理している場合のインストール
pip install git+https://github.com/mykysyk/zip-code.git
スクリプトを実行してみる
zip-code 100-0001 | jq .
{
"message": null,
"results": [
{
"address1": "東京都",
"address2": "千代田区",
"address3": "千代田",
"kana1": "トウキョウト",
"kana2": "チヨダク",
"kana3": "チヨダ",
"prefcode": "13",
"zipcode": "1000001"
}
],
"status": 200
}