pythontelegrambot http.client.RemoteDisconnected:远程端在执行延迟的作业后关闭连接而无响应\u queue.run\u once作业

2024-09-28 22:20:49 发布

您现在位置:Python中文网/ 问答频道 /正文

我编写了一个python电报机器人,以摆脱没有启动记录的计时器和时钟。 但不幸的是,在测试中,我遇到了一个我无法理解的奇怪问题——每次作业队列中的作业在选定的15分钟延迟后执行时,都会发生HTTPError(http.client.RemoteDisconnected: Remote end closed connection without response) 我尝试用谷歌搜索这个问题,并在代码中添加了一些关键字参数timeout=3600,但这个更改对bot的性能没有影响。 有人能澄清我不明白的事情吗? 事先非常感谢

以下是我的代码,由两个文件组成:

test_bot.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import logging
import pytz
import telegram_bot_config as t

from telegram import Update, InlineKeyboardMarkup, InlineKeyboardButton, ParseMode
from telegram.ext import Updater, CommandHandler, CallbackContext, CallbackQueryHandler, Defaults
import datetime as dt

# Enable logging
logging.basicConfig(
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.INFO
)

logger = logging.getLogger(__name__)

def make_kb():
    keyboard = [
        [InlineKeyboardButton("Send message in 15 minutes", callback_data=t.BUTTON_LABEL1)],
        [InlineKeyboardButton("Send message in 4 hours", callback_data=t.BUTTON_LABEL2)],
    ]

    reply_markup = InlineKeyboardMarkup(keyboard)
    return reply_markup


def start(update: Update, context: CallbackContext) -> None:
    """Sends a message with three inline buttons attached."""
    reply_markup = make_kb()
    update.message.reply_text('Please choose:', reply_markup=reply_markup)


def alarm(context: CallbackContext) -> None:
    """Send the alarm message."""
    job = context.job
    dt_now = dt.datetime.now()
    dt_now_str = dt.datetime.strftime(dt_now, '%Y-%m-%d %H:%M:%S')

    delta_dt = (dt_now - dt.datetime.strptime(job.context["dt_start"], '%Y-%m-%d %H:%M:%S'))
    elapsed = dt.timedelta(delta_dt.total_seconds())
    answer = '{0} were elapsed!*'.format(elapsed)
    text_message = "You had pressed the button at *{0}*.\nAfter waiting I sent it at *{1}*".format(
        job.context["dt_start"],
        dt_now_str)
    context.bot.send_message(job.context["chat_id"], text=answer, parse_mode=ParseMode.MARKDOWN)
    context.bot.send_message(job.context["chat_id"], text=text_message, parse_mode=ParseMode.MARKDOWN)


def button(update: Update, context: CallbackContext) -> None:
    """Parses the CallbackQuery and updates the message text."""
    query = update.callback_query
    query.answer()
    data = query.data
    query.message.reply_text("You selected *" + data + "* option!", parse_mode=ParseMode.MARKDOWN)

    dt_start = dt.datetime.now()
    chat_id = query.message.chat_id
    payload = {"chat_id": chat_id, "dt_start": dt.datetime.strftime(dt_start, '%Y-%m-%d %H:%M:%S')}

    if data == '15m':
        context.job_queue.run_once(alarm, t.DURATION_15M, context=payload, name=str(chat_id))
    if data == '4h':
        context.job_queue.run_once(alarm, t.DURATION_4H, context=payload, name=str(chat_id))


if __name__ == '__main__':
    """Run bot."""
    defaults = Defaults(parse_mode=ParseMode.HTML, tzinfo=pytz.timezone('Europe/Moscow'),)

    updater = Updater(t.TOKEN, request_kwargs={'read_timeout': 4*3600, 'connect_timeout': 4*3600})

    updater.dispatcher.add_handler(CommandHandler("start", start))
    updater.dispatcher.add_handler(CallbackQueryHandler(button))

    # Start the Bot
    updater.start_polling(timeout=4*3600)

    updater.idle()

telegram_bot_config.py

# -*- coding: utf-8 -*-
TOKEN = "YOUR TOKEN HERE!"

DURATION_15M = 60*15
DURATION_4H = 60*60*4

BUTTON_LABEL1 = "15m"
BUTTON_LABEL2 = "4h"

等待消息15分钟后,每次都会发生错误:

C:\Users\test\Dropbox\Development\TelegramTimerBot\venv\Scripts\python.exe C:/Users/test/Dropbox/Development/TelegramTimerBot/test4.py
2021-07-01 22:43:37,315 - apscheduler.scheduler - INFO - Scheduler started
2021-07-01 22:43:43,133 - apscheduler.scheduler - INFO - Added job "1234567" to job store "default"
2021-07-01 22:58:43,098 - apscheduler.executors.default - INFO - Running job "1234567 (trigger: date[2021-07-01 19:58:43 UTC], next run at: 2021-07-01 19:58:43 UTC)" (scheduled at 2021-07-01 19:58:43.092836+00:00)
2021-07-01 22:58:43,099 - apscheduler.scheduler - INFO - Removed job 8ed316fd7340464b948d0f41bce318de
2021-07-01 22:58:43,105 - telegram.ext.dispatcher - ERROR - No error handlers are registered, logging exception.
Traceback (most recent call last):
  File "C:\Users\test\Dropbox\Development\TelegramTimerBot\venv\lib\site-packages\telegram\vendor\ptb_urllib3\urllib3\connectionpool.py", line 617, in urlopen
    chunked=chunked)
  File "C:\Users\test\Dropbox\Development\TelegramTimerBot\venv\lib\site-packages\telegram\vendor\ptb_urllib3\urllib3\connectionpool.py", line 402, in _make_request
    six.raise_from(e, None)
  File "<string>", line 2, in raise_from
  File "C:\Users\test\Dropbox\Development\TelegramTimerBot\venv\lib\site-packages\telegram\vendor\ptb_urllib3\urllib3\connectionpool.py", line 398, in _make_request
    httplib_response = conn.getresponse()
  File "C:\Python37\lib\http\client.py", line 1344, in getresponse
    response.begin()
  File "C:\Python37\lib\http\client.py", line 306, in begin
    version, status, reason = self._read_status()
  File "C:\Python37\lib\http\client.py", line 275, in _read_status
    raise RemoteDisconnected("Remote end closed connection without"
http.client.RemoteDisconnected: Remote end closed connection without response

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\Users\test\Dropbox\Development\TelegramTimerBot\venv\lib\site-packages\telegram\utils\request.py", line 259, in _request_wrapper
    resp = self._con_pool.request(*args, **kwargs)
  File "C:\Users\test\Dropbox\Development\TelegramTimerBot\venv\lib\site-packages\telegram\vendor\ptb_urllib3\urllib3\request.py", line 70, in request
    **urlopen_kw)
  File "C:\Users\test\Dropbox\Development\TelegramTimerBot\venv\lib\site-packages\telegram\vendor\ptb_urllib3\urllib3\request.py", line 148, in request_encode_body
    return self.urlopen(method, url, **extra_kw)
  File "C:\Users\test\Dropbox\Development\TelegramTimerBot\venv\lib\site-packages\telegram\vendor\ptb_urllib3\urllib3\poolmanager.py", line 244, in urlopen
    response = conn.urlopen(method, u.request_uri, **kw)
  File "C:\Users\test\Dropbox\Development\TelegramTimerBot\venv\lib\site-packages\telegram\vendor\ptb_urllib3\urllib3\connectionpool.py", line 666, in urlopen
    _stacktrace=sys.exc_info()[2])
  File "C:\Users\test\Dropbox\Development\TelegramTimerBot\venv\lib\site-packages\telegram\vendor\ptb_urllib3\urllib3\util\retry.py", line 347, in increment
    raise six.reraise(type(error), error, _stacktrace)
  File "C:\Users\test\Dropbox\Development\TelegramTimerBot\venv\lib\site-packages\telegram\vendor\ptb_urllib3\urllib3\packages\six.py", line 685, in reraise
    raise value.with_traceback(tb)
  File "C:\Users\test\Dropbox\Development\TelegramTimerBot\venv\lib\site-packages\telegram\vendor\ptb_urllib3\urllib3\connectionpool.py", line 617, in urlopen
    chunked=chunked)
  File "C:\Users\test\Dropbox\Development\TelegramTimerBot\venv\lib\site-packages\telegram\vendor\ptb_urllib3\urllib3\connectionpool.py", line 402, in _make_request
    six.raise_from(e, None)
  File "<string>", line 2, in raise_from
  File "C:\Users\test\Dropbox\Development\TelegramTimerBot\venv\lib\site-packages\telegram\vendor\ptb_urllib3\urllib3\connectionpool.py", line 398, in _make_request
    httplib_response = conn.getresponse()
  File "C:\Python37\lib\http\client.py", line 1344, in getresponse
    response.begin()
  File "C:\Python37\lib\http\client.py", line 306, in begin
    version, status, reason = self._read_status()
  File "C:\Python37\lib\http\client.py", line 275, in _read_status
    raise RemoteDisconnected("Remote end closed connection without"
telegram.vendor.ptb_urllib3.urllib3.exceptions.ProtocolError: ('Connection aborted.', RemoteDisconnected('Remote end closed connection without response'))

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "C:\Users\test\Dropbox\Development\TelegramTimerBot\venv\lib\site-packages\apscheduler\executors\base.py", line 125, in run_job
    retval = job.func(*job.args, **job.kwargs)
  File "C:/Users/test/Dropbox/Development/TelegramTimerBot/test4.py", line 52, in alarm
    context.bot.send_message(job.context["chat_id"], text=text_message, parse_mode=ParseMode.MARKDOWN)
  File "C:\Users\test\Dropbox\Development\TelegramTimerBot\venv\lib\site-packages\telegram\bot.py", line 129, in decorator
    result = func(*args, **kwargs)
  File "C:\Users\test\Dropbox\Development\TelegramTimerBot\venv\lib\site-packages\telegram\bot.py", line 507, in send_message
    api_kwargs=api_kwargs,
  File "C:\Users\test\Dropbox\Development\TelegramTimerBot\venv\lib\site-packages\telegram\ext\extbot.py", line 206, in _message
    api_kwargs=api_kwargs,
  File "C:\Users\test\Dropbox\Development\TelegramTimerBot\venv\lib\site-packages\telegram\bot.py", line 331, in _message
    result = self._post(endpoint, data, timeout=timeout, api_kwargs=api_kwargs)
  File "C:\Users\test\Dropbox\Development\TelegramTimerBot\venv\lib\site-packages\telegram\bot.py", line 295, in _post
    f'{self.base_url}/{endpoint}', data=data, timeout=effective_timeout
  File "C:\Users\test\Dropbox\Development\TelegramTimerBot\venv\lib\site-packages\telegram\utils\request.py", line 361, in post
    **urlopen_kwargs,
  File "C:\Users\test\Dropbox\Development\TelegramTimerBot\venv\lib\site-packages\telegram\utils\request.py", line 265, in _request_wrapper
    raise NetworkError(f'urllib3 HTTPError {error}') from error
telegram.error.NetworkError: urllib3 HTTPError ('Connection aborted.', RemoteDisconnected('Remote end closed connection without response'))

Tags: inpytestvenvlibpackageslinesite
1条回答
网友
1楼 · 发布于 2024-09-28 22:20:49

IISCRemoteDisconnected('Remote end closed connection without response')表示电报关闭了连接,也就是说,这不是您/ptbs方面的问题。让我有点吃惊的是-如果我理解正确的话-

  • 这种情况经常发生
  • 对API的任何其他请求都不会发生这种情况
  • 它只发生在alarm中的第二个send_message请求中,而不发生在第一个请求中

你能确认以上所有内容吗?当您更改间隔或甚至直接在alarm内运行代码(而不是安排作业)时,是否会出现相同的问题

我建议还可以查看一下network errors上的ptbs wiki页面


免责声明:我目前是python-telegram-bot的维护者


Edit

我试图复制,但没有得到任何例外。我使用的是最新版本的PTB(实际上,在master分支上…),并且在Windows下使用py3.7。此外,我还对您的示例进行了一些压缩,因此为了完整性起见,这里是我使用的mwe:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import logging

from telegram import Update
from telegram.ext import Updater, CommandHandler, CallbackContext
import datetime as dt

# Enable logging
logging.basicConfig(
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.INFO
)

logger = logging.getLogger(__name__)


def alarm(context: CallbackContext) -> None:
    """Send the alarm message."""
    job = context.job
    dt_now = dt.datetime.now()
    dt_now_str = dt.datetime.strftime(dt_now, '%Y-%m-%d %H:%M:%S')

    delta_dt = (dt_now - dt.datetime.strptime(job.context["dt_start"], '%Y-%m-%d %H:%M:%S'))
    elapsed = dt.timedelta(seconds=delta_dt.total_seconds())
    answer = '{0} were elapsed!*'.format(elapsed)
    text_message = f'You had pressed the button at *{job.context["dt_start"]}*.\nAfter waiting I ' \
                   f'sent it at *{dt_now_str}* '
    context.bot.send_message(job.context["chat_id"], text=answer)
    context.bot.send_message(job.context["chat_id"], text=text_message)


def start(update: Update, context: CallbackContext) -> None:
    """Parses the CallbackQuery and updates the message text."""
    offset = 60*15
    update.effective_message.reply_text(f'will run in {offset} seconds')

    dt_start = dt.datetime.now()
    chat_id = update.effective_chat.id
    payload = {"chat_id": chat_id, "dt_start": dt.datetime.strftime(dt_start, '%Y-%m-%d %H:%M:%S')}

    job = context.job_queue.run_once(alarm, offset, context=payload, name=str(chat_id))
    job.run(context.dispatcher)


if __name__ == '__main__':
    """Run bot."""
    updater = Updater(TOKEN)
    updater.dispatcher.add_handler(CommandHandler("start", start))
    updater.start_polling()
    updater.idle()

相关问题 更多 >