BETA

discord.py を丁寧に殺すお話、あるいはPythonとコルーチン

投稿日:2019-12-13
最終更新:2019-12-13

まえせつ

こんにちは、KPです。最近お皿をはじめました。
この記事は NITKC Prolab Advent Calendar 2019 Day13 として執筆されました。
前日 は、はとさんのlibcursesをRubyで殴るお話でした。

そうだ、DiscordBotを作ろう

とりあえずググってみる。
discord.pyというのを使えば良さそう。

ドキュメントを参考に最低限のコードを書いてみた

discord.py - basic concepts

import discord  

class MuteClient(discord.Client):  
    async def on_ready(self):  
        print(f'logged in as {self.user}')  

    async def on_message(self, message):  
        if message.content == 'ping':  
            await message.channel.send('pong!')  

client = MuteClient()  
client.run('your_token_here')  

実行してみる


無事に動作しているようだ。
これを元に拡張していけば良さそう。

問題


Ctrl+Cで終了しようとしたが、やけに時間がかかった。
Discord側を確認してみると、Botはオンラインのままだ。
どうやら終了処理が正常に行われなかったらしい。

ドキュメントを読んでみる

終了時にClient.closeを呼んでやるとよさそう。
Client.closeは async function なので、同期的に呼び出すにはちょっと手間がかかる。

コルーチンとは

コルーチンとは、特殊なサブルーチンである。
通常のサブルーチンは処理が完全に終了するまで制御を返さないが、コルーチンは処理を中断しても良いタイミング (たとえばIO待ちでブロックしたとか、明示的にsleepを行ったとか) で処理を中断し、他のコルーチンに制御を渡す。
制御を渡されたコルーチンは前回中断した位置から動作を再開し、同様に中断しても良いタイミングまで動作し、また他のコルーチンに制御を渡す。
このようにして、コルーチンはシングルスレッドで複数のタスクを並列的に実行できる(ようにみせかける)。

コルーチンとasyncioとイベントループ

Pythonにおいては、 async function == coroutines と思ってくれて概ね構わない。
asyncioはイベントループに詰まっているcoroutinesを順次実行する。
今回の場合、もともとdiscord.Clientが内部的に使用しているイベントループがあるため、それを利用することにした。

実装

KeyboardInterruptをトラップしてクライアントのイベントループにClient.closeを入れる。

import discord  

class MuteClient(discord.Client):  
    async def on_ready(self):  
        print(f'logged in as {self.user}')  

    async def on_message(self, message):  
        if message.author == self.user:  
            return  

        if message.content == 'm:ping':  
            await message.channel.send('pong!')  

client = MuteClient()  

try:  
    client.loop.run_until_complete(client.start('your_token_here'))  
except KeyboardInterrupt:  
    client.loop.run_until_complete(client.close())  

動作確認


無事に動作しているようだ。
こんどはCtrl+Cで正常に終了できる。
Client.runにも同じようなことが書いてあるのに、Client.runはうまく行かないのはなんでだろう。

おわりに

マサカリがあれば遠慮なく投げてください。死にます。asyncioの話あたりが狙い目です。
明日はうぃんじーさんです。僕とは違ってまともな文章を書いてくれるでしょう。
おしまい。

技術ブログをはじめよう Qrunch(クランチ)は、プログラマの技術アプトプットに特化したブログサービスです
駆け出しエンジニアからエキスパートまで全ての方々のアウトプットを歓迎しております!
or 外部アカウントで 登録 / ログイン する
クランチについてもっと詳しく

この記事が掲載されているブログ

@WkuJGgWkR5Kv1m0Mの技術ブログ

よく一緒に読まれる記事

0件のコメント

ブログ開設 or ログイン してコメントを送ってみよう