はじめに
いろいろ version up をしたいのですが、ここではpoetry を使ったpython のコード開発の方法をはじめるための調査結果をメモしておきます。
おじさんがやりたかったのは、
- WSL2(Ubuntu20.04), Linux (Ubuntu22.04)で開発。ターミナルとVisual Studio Code で。
- python の仮想環境とパッケージ管理ができるのか
- そのままDockerイメージ作れる
というこれまで virtualenv を用いていた環境をそのまま poetry, pyproject.toml で管理できるようにしたい、というのが目的です。
特に仮想環境が含まれるているのかよく分からない状態だったので、試してみました。できるかな。下記に作業結果を置いてあります。
内容
準備
poetry はインストールしなければなりません。本家の指示に従い、インストールするスクリプトを直接実行します。
$ curl -sSL https://install.python-poetry.org | python3 -
$ poetry --version
Poetry (version 1.3.1)
新規作成してみる
$ poetry new poetry-demo
Created package poetry_demo in poetry-demo
$ tree poetry-demo/
poetry-demo/
├── README.md
├── poetry_demo
│ └── __init__.py
├── pyproject.toml
└── tests
└── __init__.py
2 directories, 4 files
他に、pyproject.toml を生成するのに
$ poetry init -n
として作ることもできるようにです。
仮想環境に入る
poetry shell
と打つだけで、自動的に activate してくれました。
$ poetry shell
Creating virtualenv poetry-demo-2afA8rmG-py3.8 in /home/x77/.cache/pypoetry/virtualenvs
Spawning shell within /home/x77/.cache/pypoetry/virtualenvs/poetry-demo-2afA8rmG-py3.8
. /home/x77/.cache/pypoetry/virtualenvs/poetry-demo-2afA8rmG-py3.8/bin/activate
$ . /home/x77/.cache/pypoetry/virtualenvs/poetry-demo-2afA8rmG-py3.8/bin/activate
(poetry-demo-py3.8) $
$exit
でもとに戻れました。
どうやら仮想環境は、ホームディレクトリ直下に作られているようです。ここのcache_dir に当たります。
(poetry-demo-py3.8) $ poetry config --list
cache-dir = "/home/x77/.cache/pypoetry"
experimental.new-installer = true
experimental.system-git-client = false
installer.max-workers = null
installer.no-binary = null
installer.parallel = true
virtualenvs.create = true
virtualenvs.in-project = null
virtualenvs.options.always-copy = false
virtualenvs.options.no-pip = false
virtualenvs.options.no-setuptools = false
virtualenvs.options.system-site-packages = false
virtualenvs.path = "{cache-dir}/virtualenvs" # /home/x77/.cache/pypoetry/virtualenvs
virtualenvs.prefer-active-python = false
virtualenvs.prompt = "{project_name}-py{python_version}"
project 配下に .venv を作りたい場合
virtualenvs.in-project を true にします。上記のように初期設定では null になっているので。
$ poetry config virtualenvs.in-project true
パッケージ管理(追加)
何もパッケージをインストールしていない状態ですが、poetry install
を実行すると、peotry.lock ファイルが生成されます。パッケージの情報は pyproject.toml に書くこともできるようですが、poetry.lock があれば、そちらが優先されるそうです。レポジトリに置いたりするときは、poetry.lock を置くのが良さそうです。
(poetry-demo-py3.8) $ poetry install
Updating dependencies
Resolving dependencies... (0.1s)
Writing lock file
Installing the current project: poetry-demo (0.1.0)
(poetry-demo-py3.8) $ ls
README.md poetry.lock poetry_demo pyproject.toml tests
この時点ではpoetry.lock の中身は空です。このあといろいろインストールされていくものが追加されていきます。(追記)
$ cat poetry.lock
# This file is automatically @generated by Poetry and should not be changed by hand.
package = []
[metadata]
lock-version = "2.0"
python-versions = "^3.8"
content-hash = "123b456bxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
いざ、使用するパッケージを追加してみます。
(poetry-demo-py3.8) $ poetry add fastapi uvicorn
仮想環境で実行しているせいか、インストールしたversion は poetry.lock に書かれています。pyproject.toml も以下のように更新されていました。
[tool.poetry.dependencies]
python = "^3.8"
fastapi = "^0.89.0"
uvicorn = "^0.20.0"
環境の確認
現在のpython の version とか、仮想環境がどこにあったかな、とか分からなくなった時の確認方法としてメモ。
$ poetry env info
Virtualenv
Python: 3.8.10
Implementation: CPython
Path: /home/x77/Github/xxx/my_try_webapi/.venv
Executable: /home/x77/Github/xxxt/my_try_webapi/.venv/bin/python
Valid: True
System
Platform: linux
OS: posix
Python: 3.8.10
Path: /usr
Executable: /usr/bin/python3.8
サーバ起動
app.py を作ります。
from fastapi import FastAPI
import os
app = FastAPI()
@app.get('/')
def index():
return {'Hello': 'World'}
@app.get('/users/{user_id}')
def read_item(user_id: int):
return {'user_id': user_id}
いつものように起動します。
$ uvicorn app:app
INFO: Started server process [10491]
INFO: Waiting for application startup.
INFO: Application startup complete.
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
ブラウザで http://localhost:8000 や http://localhost:8000/users/1000 で動作確認できます。
パッケージ(wheel)を作る
これはコマンド一発でできました。
(my-try-webapi-py3.8)$ poetry build
(my-try-webapi-py3.8)$ ls dist/
my_try_webapi-0.1.0-py3-none-any.whl my_try_webapi-0.1.0.tar.gz
コンテナを作る
いまどきは、直接serverless 環境にdeploy できるようなのですが、ここでは一応 docker コンテナを作ることにします。
コンテナ内でpoetry がインストール
下記のエラーに遭遇。涙。
=> ERROR [3/8] RUN curl -sSL https://install.python-poetry.org/ | python3 - 5.8s
------
> [3/8] RUN curl -sSL https://install.python-poetry.org/ | python3 -:
#0 5.697 Retrieving Poetry metadata
#0 5.697
#0 5.697 # Welcome to Poetry!
#0 5.697
#0 5.697 This will download and install the latest version of Poetry,
#0 5.697 a dependency and package manager for Python.
#0 5.697
#0 5.697 It will add the `poetry` command to Poetry's bin directory, located at:
#0 5.697
#0 5.697 /opt/poetry/bin
#0 5.697
#0 5.697 You can uninstall at any time by executing this script with the --uninstall option,
#0 5.697 and these changes will be reverted.
#0 5.697
#0 5.697 Installing Poetry (1.3.2)
#0 5.697 Installing Poetry (1.3.2): Creating environment
#0 5.697 Installing Poetry (1.3.2): An error occurred. Removing partial environment.
調べてみると、素直に pip で入れることができるようなので、以下のようにしたら動いた。
ENV POETRY_VERSION=1.3.1
RUN pip install "poetry==$POETRY_VERSION"
そのあと、build とfinal を分けるなどありますが、とりあえず、強引に下記のようにしたら動きました。
FROM python:3.10-slim as base
ENV PYTHONFAULTHANDLER=1 \
PYTHONHASHSEED=random \
PYTHONUNBUFFERED=1
WORKDIR /app
FROM base as builder
ENV PIP_DEFAULT_TIMEOUT=100 \
PIP_DISABLE_PIP_VERSION_CHECK=1 \
PIP_NO_CACHE_DIR=1 \
POETRY_VERSION=1.3.1
RUN pip install "poetry==$POETRY_VERSION"
COPY pyproject.toml poetry.lock README.md ./
COPY my_try_webapi ./my_try_webapi
RUN poetry config virtualenvs.in-project true && \
poetry install --only=main --no-root && \
poetry build
EXPOSE 80
CMD ["/app/.venv/bin/uvicorn", "my_try_webapi.main:app", "--host", "0.0.0.0", "--port", "80"]
build します。
$ docker build . -t hogehoge/mytrywebapi:test
docker images
でできているか確認したのち、実行します。ポートを公開するのを忘れずに。
(my-try-webapi-py3.8) xt77$ docker run --rm -p 80:80 --name testapi1 -d hogehoge/mytrywebapi:test
707b5052567d1dba02172428ec333bb1ece1dxxxxxxxxxxxxxxxxxxxxxxxxx
(my-try-webapi-py3.8) xt77$ docker logs testapi1 -f
INFO: Started server process [1]
INFO: Waiting for application startup.
INFO: Application startup complete.
INFO: Uvicorn running on http://0.0.0.0:80 (Press CTRL+C to quit)
poetry を用いてDocker build をどのように行うのか
下記に長い議論があるがとても参考になります。個人的には、build をスマートにして、最終盤に必要なものだけコピーする、といういつものように使いたいのですが、まだスマートにできていません。poetry そのものをインストールするのに大変だった。スマートにできたらいいなぁ。
Docker-compose
これは以前に書いたのと同じにできると思います。
まとめ
とりあえず、poetry で環境構築してFastAPIを使い、開発をすることはできそうな感じでした。作業途中なのですが、明日からまた普通の会社人になるので、メモを挙げておきます。
参考にしたページ
感謝です。
-
Poetry はじめました - チーム開発における Python の開発環境: Github Actions での使い方などノウハウが満載。
-
https://dev.to/nimishverma/a-guide-to-start-a-fastapi-poetry-serverless-project-142d
AWS serverless にdeploy している。
参考になるかも
こちら、とても勉強できそうなのでメモ
その他後日談
その後、scipy をpoetry add しようとしたら、scipy が対応するpython の version に制限があり、poetry init -n で作った設定だとpython の制限がゆるくてerror になることがありました。そこでは、素直に
$ poetry add scipy
Using version ^1.10.1 for scipy
Updating dependencies
Resolving dependencies... (0.0s)
The current project's Python requirement (>=3.8,<4.0) is not compatible with some of the required packages Python requirement:
- scipy requires Python <3.12,>=3.8, so it will not be satisfied for Python >=3.12,<4.0
Because no versions of scipy match >1.10.1,<2.0.0
and scipy (1.10.1) requires Python <3.12,>=3.8, scipy is forbidden.
So, because depthcompletion depends on scipy (^1.10.1), version solving failed.
? Check your dependencies Python requirement: The Python requirement can be specified via the `python` or `markers` properties
For scipy, a possible solution would be to set the `python` property to ">=3.8,<3.12"
なので、素直に、pyproject.toml でversion 指定を変更しました。それで問題なくpoetry add できました。
[tool.poetry.dependencies]
python = ">=3.8, <3.12"
#python = "^3.8"
追記
- virtualenvs.in-project を追記 (2023/01/15)
- poetry.lock, poetry build, Docker 作る試みを追加(2023/02/23)
- poetry env info を追記(2023/02/25)
- Docker build/run を追記(2023/02/25)
- Github に公開(2023/02/25)
- モジュールに対応したpython のバージョン指定(2023/03/26)