前提・実現したいこと
私はいま、指定時刻(23時)に、辞書のすべての値を-1しようと思っています
しかし、whileなどで、書くとそのあとにある、コードが実行されなくて困っています(ずっとループしてしまうため)。これを両立させることはできないのでしょうか?調べても、期待していたものとは違うものばかりだったので、教えてください。(つい最近pythonを始めました。)
該当のソースコード
python
1dt_now = datetime.datetime.now() 2if dt_now.hour == 23: 3 point_check()
こんな感じに書いてみたのですがうまく行きません
point_checkは自作関数です。
試したこと
whileでループさせてみた。ifで現在時刻と比較させてみた。
補足情報(FW/ツールのバージョンなど)
python3.8.2 windows
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答2件
0
discord.py のwindowsでのエラー(SSL証明の更新)にはまって
なかなか動作確認が出来なかったけど、サンプルコードです。
あまりデバッグはしてないので、このまま実用できるコードかどうかは怪しいです。
必要な情報のみ参考にして下さい。(指定時間の計算等は実際には確認出来てません)
動作確認したPythonのバージョンは3.8.3 / win10 64bit
- (1) discord.py: tasks.loop で一定時間毎に実行
- (2) asyncio: 任意のループを組み込む方法 (asyncio での作法で書く必要があります)
- (3) asyncio: call_later, call_at で指定日時に関数を実行
- (4) 1 と 3 を組み合わせたお勧めの方法
1.2 は、自分のループを両立させる方法のデモで、毎分チャンネルに何か発言します5回
3.4 は、本題の指定時間に毎日実行です。4番がお勧めの方法。
何れの方法を取るとしても、ループで毎分時間をチェックするよりも、
指定時間に関数を実行のcall_laterを起点にするとよいです。
python
1import asyncio 2import datetime 3import discord 4from discord.ext import tasks 5 6 7# ※ 必須設定 8BOT_TOKEN = "XXXXXXXX" 9CHANNEL_ID = 99999999 10 11 12 13def get_next_time(now, hour=23): 14 # 既に23時過ぎの場合、翌日の23時迄の秒数を返す 15 next_time = datetime.datetime(now.year, now.month, now.day, hour, 0, 0) 16 delta = next_time.timestamp() - now.timestamp() # 23時から現在時刻を引く 17 return delta if delta > 0 else (delta + 1*24*60*60) # マイナスであれば一日加算 18 19 20def main(): 21 client = discord.Client() 22 23 @client.event 24 async def on_ready(): 25 loop = asyncio.get_running_loop() 26 channel = client.get_channel(CHANNEL_ID) 27 28 # テスト用フラグ 29 USE_TEST1 = True 30 USE_TEST2 = False 31 USE_TEST3 = False 32 USE_TEST4 = True 33 34 # (1) discordの提供する、一定時間に起動する関数 (60秒毎に5回) 35 # 前後の処理(before_loop,after_loop)が不要であれば、一番手軽な方法です。 36 # https://discordpy.readthedocs.io/ja/latest/ext/tasks/ 37 if USE_TEST1: 38 @tasks.loop(seconds=60.0, count=5) 39 async def task_loop_func(): 40 await channel.send("TEST1") 41 pass 42 43 @task_loop_func.before_loop 44 async def on_task_loop_before(): 45 print("START TEST1") 46 47 @task_loop_func.after_loop # <-- このタスクはキャンセルされたときも呼び出される 48 async def on_task_loop_after(): 49 print("DONE TEST1") 50 51 # タスクを起動 52 task_loop_func.start() 53 54 # (2) 非同期のループを起動する方法 (asyncio) 55 if USE_TEST2: 56 # asyncio でのループの記述の仕方 57 # time.sleepやループは、イベントループ(discord通信等)を止めてしまうので 58 # 必ず asynci.sleep を使います。 59 async def my_loop_func(channel, seconds=60.0, count=5): 60 print("START TEST2") 61 for _ in range(count): 62 await channel.send("TEST2") 63 await asyncio.sleep(seconds) 64 print("DONE TEST2") # <-- キャンセルされた場合中断されます 65 66 asyncio.ensure_future(my_loop_func(channel)) 67 68 # (3) call_at, call_later で指定時間に処理 69 # 注意点: 70 # call_at は loop.time() を基準とした秒数, 71 # call_later は loop.time() を抜いた秒数なので、 (例: call_later(5, func) 5秒後に実行) 72 # この場合、call_later の方が使いやすいのですが、サンプルの為 解り辛い call_at の使い方を解説。 73 if USE_TEST3: 74 async def test3_func(channel): 75 await channel.send("TEST3") 76 loop.call_later(1*24*60*60, lambda:asyncio.ensure_future(test3_func(channel))) 77 78 next_time = get_next_time(datetime.datetime.now()) 79 when = loop.time() + next_time 80 handle = loop.call_at(when, lambda:asyncio.ensure_future(test3_func(channel))) 81 82 83 # (4) 上記を組み合わせた方法 84 # 85 # 1. tasks.loop で24時間毎に実行するタスクを作る 86 # 2. call_later で指定時にタスクを開始 87 if USE_TEST4: 88 @tasks.loop(hours=24) 89 async def test4_func(): 90 await channel.send("TEST4") 91 92 next_time = get_next_time(datetime.datetime.now()) 93 loop.call_later(next_time, test4_func.start) 94 95 client.run(BOT_TOKEN) 96 97 98if __name__ == '__main__': 99 try: 100 main() 101 except KeyboardInterrupt: 102 pass 103
投稿2020/05/31 07:42
編集2020/05/31 08:57総合スコア8760
0
ベストアンサー
念の為確認しますが、discord.py のバージョンは何でしょう?
古いものでなければ、discord.py は asyncio というライブラリ上で動いているので、
このライブラリの作法で書く必要があります。(async/await等の理解が必須です)
両立させることはできないのでしょうか?
可能ですが、一度の実行で良いならcall_later, call_at で指定日時に関数を実行できます。
投稿2020/05/29 15:02
総合スコア8760
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/05/30 12:55 編集
2020/05/31 08:54
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。