0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

起動直後にtasks.loop()内でメッセージを送信しようとするとエラーが出るときの対処法

Last updated at Posted at 2020-10-29

前回の記事で、デバッグ用に現在時刻とか送信予定時刻などをprint()していたのですが、思いつきで「syslogにprint()していたものをDiscordに全部送信してしまえ」と思って変えたら、エラーが発生して2日ほど苦戦しておりました。
そのときの対処法を紹介したいと思います。

本題

エラーを吐いていたときのコード

bot.py
@tasks.loop(seconds=60)
async def loop():
    global time_set
    global tem_set

    w_list = ["", "", "", "", "", "", ""]  # 進化したよ!
    now_t, now_dt = datetime.now().strftime('%H:%M'), w_list[datetime.now().weekday()]

    ch = client.get_channel(771155766056452167)
    await ch.send(f"現在の時刻:`{now_t}`/今日の曜日:`{now_dt}`/送信予定時刻:`{time_set}`/送信予定体温:`{tem_set}`")

    if now_dt != "":  # 日曜日以外だったら送信するようにした
        if now_t == time_set:  # 送信予定時刻になった?
            dt_now = datetime.now().strftime("%Y-%m-%d")  # 現在時刻を2020-01-01の形で取得、dt_nowに格納

            file_name = "cfg.json"
            with open(file_name, "r", encoding="utf-8")as f:
                cfg = json.load(f)
                cfg["output"]["ans_1"] = f"{dt_now}"
                cfg["output"]["ans_4"] = f"{tem_set}"

                params = {"entry.{}".format(cfg["entry"][k]): cfg["output"][k] for k in cfg["entry"].keys()}
                res = requests.get(cfg["form_url"] + "formResponse", params=params)

            if res.status_code == 200:
                await template_embed(message=768274673984208926, title="ログ情報", description=f"[URL]({res.url})",
                                     name_1="完了状態", name_2="送信された体温", value_1="成功しました", color=discord.Color.green())
            else:
                res.raise_for_status()
                await template_embed(message=768274673984208926, title="ログ情報", name_1="完了状態", name_2="送信予定だった体温",
                                     value_1="エラーが発生しました。", color=discord.Color.red())

        else:
            if now_t == "21:00":
                time_set = setting_time_set()
                tem_set = set_tem()
                await template_embed(message=768274673984208926, title="送信時刻更新のお知らせ", name_1="次回の送信予定時刻", name_2="送信予定の体温",
                                     value_1=time_set, color=discord.Color.blue())

このコードを実際に動作させると、以下のようなエラーが出るんです。
最初は、IDのコピペミスかなと思っていたのですが、再度コピペしてもエラーを吐いたので何か別の要因があるのでは?と調べてみたら、ありましたよ

client.get_channel()などの関数は、BOTの準備が完了するまでNoneを返します。
例えば、プログラムの冒頭でいきなりget_channel()をしていませんか?
これを避けるには、readyイベントが発生した「後」に取得を行う必要があります。

「えっ、あ、そういえば...」となりました(泣)
俺の2日はどこいった。

エラー
AttributeError: 'NoType' object has no attribute 'send'

対処法

対処法は意外と簡単でした、はい。
先程の記事のget_channel()をする前に、wait_until_ready()(リファレンス)を入れればいいだけです。

bot.py
@tasks.loop(seconds=60)
async def loop():
    global time_set
    global tem_set

    w_list = ["", "", "", "", "", "", ""]  # 進化したよ!
    now_t, now_dt = datetime.now().strftime('%H:%M'), w_list[datetime.now().weekday()]

    await client.wait_until_ready()
    ch = client.get_channel(771155766056452167)
    await ch.send(f"現在の時刻:`{now_t}`/今日の曜日:`{now_dt}`/送信予定時刻:`{time_set}`/送信予定体温:`{tem_set}`")

    if now_dt != "":  # 日曜日以外だったら送信するようにした
        if now_t == time_set:  # 送信予定時刻になった?
            dt_now = datetime.now().strftime("%Y-%m-%d")  # 現在時刻を2020-01-01の形で取得、dt_nowに格納

            file_name = "cfg.json"
            with open(file_name, "r", encoding="utf-8")as f:
                cfg = json.load(f)
                cfg["output"]["ans_1"] = f"{dt_now}"
                cfg["output"]["ans_4"] = f"{tem_set}"

                params = {"entry.{}".format(cfg["entry"][k]): cfg["output"][k] for k in cfg["entry"].keys()}
                res = requests.get(cfg["form_url"] + "formResponse", params=params)

            if res.status_code == 200:
                await template_embed(message=768274673984208926, title="ログ情報", description=f"[URL]({res.url})",
                                     name_1="完了状態", name_2="送信された体温", value_1="成功しました", color=discord.Color.green())
            else:
                res.raise_for_status()
                await template_embed(message=768274673984208926, title="ログ情報", name_1="完了状態", name_2="送信予定だった体温",
                                     value_1="エラーが発生しました。", color=discord.Color.red())

        else:
            if now_t == "21:00":
                time_set = setting_time_set()
                tem_set = set_tem()
                await template_embed(message=768274673984208926, title="送信時刻更新のお知らせ", name_1="次回の送信予定時刻", name_2="送信予定の体温",
                                     value_1=time_set, color=discord.Color.blue())

あら、一発で解決()

まとめ

  • tasks.loop内でget_channel()などの関数を際にエラーが出るときは、wait_until_ready()を入れれば治る。

すっごいざっくりしたまとめでごめんなさい...
同じような状況に陥っている人の助けになれば、幸いです。

参考

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?