質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Discord

Discordは、ゲーマー向けのボイスチャットアプリです。チャット・通話がブラウザ上で利用可能で、個人専用サーバーも開設できます。通話中でも音楽を流したり、PC画面を共有できるなど多機能な点が特徴です。

非同期処理

非同期処理とは一部のコードを別々のスレッドで実行させる手法です。アプリケーションのパフォーマンスを向上させる目的でこの手法を用います。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

1回答

1915閲覧

Discord BOTを制御する非同期処理を 同期関数から実行したい

Unico417

総合スコア6

Discord

Discordは、ゲーマー向けのボイスチャットアプリです。チャット・通話がブラウザ上で利用可能で、個人専用サーバーも開設できます。通話中でも音楽を流したり、PC画面を共有できるなど多機能な点が特徴です。

非同期処理

非同期処理とは一部のコードを別々のスレッドで実行させる手法です。アプリケーションのパフォーマンスを向上させる目的でこの手法を用います。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2022/05/22 18:04

編集2022/05/23 23:50

自作でPythonのアプリケーションを作成しています。
その中にDiscord BOTがありますが、その機能をメインのソースコードから分離したくなりました。

Discord BOTを制御する部分を"DiscordModule"として分離・クラス化した時、次のようなエラーが発生しました。
(エラー全文は下に記載してあります。)

cmd

1RuntimeError: Timeout context manager should be used inside a task

これを実行する術があればご教示ください。

ソースコード

ソースコードは、したいことを表現するために簡略化させて頂きました。

main.py (制御する側)

python

1# main.py 2import asyncio 3from discordmodule import DiscordModule # 自作 discordmodule.py 4 5class HostModule: 6 def __init__(self): 7 self.bot = DiscordModule(command_prefix='/') 8 self.task() 9 10 # DiscordModule.send_message() (非同期関数)を使って特定チャンネルにメッセージを送りたい 11 def task(self): 12 asyncio.run(self.bot.send_message(message='メッセージ', channel=123456789)) 13 14instance = HostModule() 15instance.bot.run('トークン')

discordmodule.py (制御される側)

python

1# discordmodule.py 2import traceback 3from discord.ext import commands 4 5class DiscordModule(commands.Bot): 6 def __init__(self, command_prefix): 7 pass 8 9 async def send_message(self, message:str, channel:int): 10 ch = self.get_channel(channel) # discord.TextChannelオブジェクトは取得確認済み 11 try: 12 await ch.send(message) # ここでエラー 13 except: 14 print(traceback.format_exc()) 15

エラー

cmd

1Traceback (most recent call last): 2 File "C:\Works\Python\schedule\main.py", line 11, in task 3 asyncio.run(self.bot.send_message(message=sc['message'], channel=int(sc['channel']), mention=sc['mention'])) 4 File "C:\Users\User\AppData\Local\Programs\Python\Python310\lib\asyncio\runners.py", line 44, in run 5 return loop.run_until_complete(main) 6 File "C:\Users\User\AppData\Local\Programs\Python\Python310\lib\asyncio\base_events.py", line 641, in run_until_complete 7 return future.result() 8 File "C:\Works\Python\schedule\discordmodule.py", line 10, in send_message 9 await ch.send(message) 10 File "C:\Users\User\AppData\Local\Programs\Python\Python310\lib\site-packages\discord\abc.py", line 1065, in send 11 data = await state.http.send_message(channel.id, content, tts=tts, embed=embed, 12 File "C:\Users\User\AppData\Local\Programs\Python\Python310\lib\site-packages\discord\http.py", line 192, in request 13 async with self.__session.request(method, url, **kwargs) as r: 14 File "C:\Users\User\AppData\Local\Programs\Python\Python310\lib\site-packages\aiohttp\client.py", line 1117, in __aenter__ 15 self._resp = await self._coro 16 File "C:\Users\User\AppData\Local\Programs\Python\Python310\lib\site-packages\aiohttp\client.py", line 448, in _request 17 with timer: 18 File "C:\Users\User\AppData\Local\Programs\Python\Python310\lib\site-packages\aiohttp\helpers.py", line 635, in __enter__ 19 raise RuntimeError( 20RuntimeError: Timeout context manager should be used inside a task

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

おそらくこのエラーはbot.run()asyncio.run()を併用していることによるものだと思われます。
asyncio.runの代わりとして、bot.loop.create_task()を利用するといいでしょう。

python

1 def task(self): 2 self.bot.loop.create_task(self.bot.send_message(...))

そしてもう一つ治すべき問題点は、Botクラスを継承したDiscordModule__init__関数が何もしていないことです。passをしてしまうと、commands.Botの機能のために必要な変数や定数の初期化が行われません。そこで、継承元を指し示すsuper()を使用し、以下のように書くといいでしょう。

python

1 def __init__(self, *args, **kwargs): 2 super().__init__(*args, **kwargs)

投稿2022/05/23 13:25

yaakiyu

総合スコア124

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Unico417

2022/05/23 14:50

ご指摘いただいたところを修正した結果、しっかり実行してくれました。 ありがとうございます。 また、継承元の初期化についても学習になりました。 細かいところまで見ていただき、指摘頂き感謝致します。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問