はじめに
制作しているDiscord Botの改修作業を行っている途中で、loop周りのエラーにぶち当たりました。解決に少々時間を要したので、メモを残しておきます。
開発環境
- discord.py 2.1.0
- python3 3.8.10
起きたこと
Discord Botを実行すると以下のエラー文が出るようになった。
Traceback (most recent call last):
File "main.py", line 50, in <module>
loop.start()
File "/home/oimo/.local/lib/python3.8/site-packages/discord/ext/tasks/__init__.py", line 398, in start
self._task = asyncio.create_task(self._loop(*args, **kwargs))
File "/usr/lib/python3.8/asyncio/tasks.py", line 381, in create_task
loop = events.get_running_loop()
RuntimeError: no running event loop
sys:1: RuntimeWarning: coroutine 'Loop._loop' was never awaited
解決策
import discord
from discord.ext import tasks
@client.event
async def on_ready():
loop.start()
@tasks.loop(seconds=60)
async def loop():
now = datetime.now(timezone('Asia/Tokyo')).strftime('%H:%M')
if now.hour == 19 and now.minute == 30:
channel = client.get_channel(CHANNEL_ID)
await channel.send('ゴミ出しに行こうね!')
一体なんだったのか
Discord.py 2.0.0/python 3.1以上の環境で、「discord.ext.tasks」を使用しているときに起きるようです。
もともと「discord.ext.tasks」を使うと、asyncio
という並行処理のコードを書くためのライブラリを使用せずとも、ループを実行させられるらしい。しかし、Discord.py側のアップデートか何なのかbotの起動前に、ただ単にループ処理実行を書くだけでは上手く起動しないようになっています。
そこで、上記のようにon_readyにループ実行を入れてあげれば動くらしい。
@client.event
async def on_ready():
@tasks.loop(seconds=60)
async def loop():
now = datetime.now(timezone('Asia/Tokyo')).strftime('%H:%M')
if now.hour == 19 and now.minute == 30:
channel = client.get_channel(CHANNEL_ID)
await channel.send('ゴミ出しに行こうね!')
loop.start()
まとめ
timezone周りを修正したかっただけなのに、これが出てきてえらい大変困りました。
参考文献
teratail.com