🐍

ryeでDiscord Botの開発体験を向上させる

2024/05/15に公開

こんにちは、@sushi-chanです。電気通信大学で学生をしています。

私はPythonでDiscordのBotを作っているのですが、パッケージマネージャーとしてはpoetryを使ってきました。

しかし、

  • ビルド済みDockerイメージを自動デプロイしているので、ビルド前にpoetry.lockrequirements.txtを同期させないといけない
  • タスクランナーやLinter・Formatterなどインストールしないといけないツールが多い

などの理由で開発・ビルド環境のセットアップが非常に面倒だというつらさがありました。

そこで最近話題のryeに移行してみたところ、これらの点が大きく改善され、開発体験が良くなったのでその話をします。

この記事で書かないこと

  • PythonでDiscord Botを書く方法
  • ryeとはなにか
  • ryeのインストール方法
  • ryeの基本的な使い方

ryeに移行して改善されたもの

lockファイルとrequirements.txtを同期しなくてよくなった

冒頭でも触れた通り、poetryのlockファイルは独自のものなのでそのままではpipで使えません。しかし、Dockerイメージをビルドする際にpoetryを入れるとその分ビルド時間が伸びるので、ビルド時にはpipを使いたいという課題がありました。

今までは、python-poetry/poetry-plugin-export をGit HookやGitHub Actions上で実行してDockerイメージをビルドする前にlockファイルからrequirements.txtを自動生成することで対応していました。

ryeを使うと、この課題は大きく改善することができます。

ryeではrye syncでパッケージを同期するとrequirements.lockrequirements-dev.lockという2つのlockファイルが生成されます。後者は開発環境用のものです。
さて、このrequirements.lockの中身を見てみましょう。

requirements.lock
# generated by rye
# use `rye lock` or `rye sync` to update this lockfile
#
# last locked with the following flags:
#   pre: false
#   features: []
#   all-features: false
#   with-sources: false

aiodns==3.2.0
    # via discord-py
aiohttp==3.9.5
    # via discord-py

...

typing-extensions==4.11.0
yarl==1.9.4
    # via aiohttp

requirements.txtに随分似ていますね。実際にこのファイルをpipで使ってみましょう。

$ pip install -r requirements.lock
Collecting discord-py@ git+https://github.com/Rapptz/discord.py.git@d853a3f0a7e19d290021434e85f9c4c14089a874 (from -r requirements.lock (line 23))
  Using cached discord.py-2.4.0a5005+gd853a3f0-py3-none-any.whl

...

Successfully installed aiodns-3.2.0 aiohttp-3.9.5 attrs-23.2.0 discord-py-2.4.0a5005+gd853a3f0 frozenlist-1.4.1 idna-3.7 multidict-6.0.5 orjson-3.10.3 pycparser-2.22 typing-extensions-4.11.0

正しく実行されましたね。

ryeが生成するlockファイルはrequirements.txtと互換性があるので、Dockerイメージをビルドするときもそのままpip install -rでlockファイルを見るだけでよくなります。これによって何も意識しなくてもデプロイ時に正しい依存関係がインストールされるようになりました。

タスクランナー・Linter・Formatterが内蔵されている

DiscordのBotは通常エントリーポイントとなるPythonファイルを実行することで起動します。

main.py
import os

from src.app.bot import Bot

if __name__ == "__main__":
    bot = Bot()
    bot.runner(token=os.environ["DISCORD_BOT_TOKEN"])

このコードを見ればお分かりいただけるように、Discord Botの起動にはDiscord APIのアクセストークンが必要です。このトークンは環境変数として渡すのが一般的であり、本番環境ではコンテナ起動時の引数から渡しています。
開発環境のためだけにコードを増やしたくなかったので、今まではpoethepoetというpoetry向けのタスクランナーを追加でインストールして、タスクランナー経由で環境変数を読み込むようにしていました。

一方ryeには、ほぼ同等のことができるタスクランナーが最初から内蔵されています。環境変数の読み込みもサポートされており、現在は下のようなスクリプトで開発環境を起動しています。

pyproject.toml
[tool.rye.scripts]
dev = { cmd = ["python", "main.py"], env-file = ".env" }
rye run dev

また、ryeにはLinterとFormatterも内蔵されています。 最近のPython界隈では有名になってきたruffを使っており、それぞれrye lintrye fmtで実行できます。
rye移行前からruffを使っていたので単純にインストールしなくて良くなっただけですが、自分でインストールしないといけないものが減るのはいいことです。

まとめ

上で書いたこと以外にもPython本体のバージョン管理ができたりと、ryeは非常にかゆいところに手が届くツールだと思います。今まではたくさんのツールを組み合わせて実現していた環境がrye単体で組めるようになり、煩わしさが大きく減りました。

Discord Botのようなビルドを考えなくていい開発をする場合は、ryeを使うことを検討してもいいかもしれません。

GitHubで編集を提案

Discussion