Регистрация в Python с помощью ptb: одна и та же строка регистрируется дважды, но добавлен только один обработчик - PullRequest
0 голосов
/ 08 ноября 2018
  • питон: 3.6.6
  • python-telegram-bot: 10.0.2

У меня есть такая проблема: я определил регистратор Python с SMTPHandler, TimedRotatingFileHandler и StreamHandler.

StreamHandler работает нормально, но когда я пытаюсь использовать его из обработчика python-telegram-bot, строка выводится дважды на стандартный вывод в двух разных форматах, и я не могу найти, как избежать одного и получить другой (по времени), чтобы остаться.

Я обнаружил причину. При добавлении ConversationHandler с CallbackQueryHandler это сообщение отображается при запуске.

WARNING:root:If 'per_message=False', 'CallbackQueryHandler' will not be tracked for every message.

И тогда каждый раз появляется нежелательная строка журнала.

Код приведен ниже как log_config.py. Я добавил также пример кода для тестирования my_main_file.py и текущий вывод в виде многострочного комментария.

конфиг / log_config.py

import os

import logging
from logging import Formatter

from datetime import datetime


VERSION_NUM = '1.2.0'
LOG_MSG_FORMAT = '%(asctime)s - ({0}) %(levelname)s - %(name)s - %(message)s'
LOGFILE_PATH = os.path.join(os.path.dirname(os.path.dirname(__file__)),
                            'log',
                            'alfred.log')
logging.getLogger('telegram').setLevel(logging.WARNING)
logging.getLogger('chardet.charsetprober').setLevel(logging.WARNING)


def my_timezone_time(*args):
    # I simplified this line, because it's irrelevant
    return datetime.now().timetuple()


handlers = []


#
# ... different handlers added
#


# last handler to add, this one works just as I want

ch = logging.StreamHandler()
formatter = Formatter(LOG_MSG_FORMAT.format(VERSION_NUM))
formatter.converter = my_timezone_time
ch.setFormatter(formatter)
ch.setLevel(logging.INFO)
handlers.append(ch)


def getLogger(name):
    """
    Returns a logger for the file. Works fine but when used,
       it always outputs the same line with the last handler 
       and also with an unknown handler not added by me 
       (must be some default instance)
    :param name: the file name
    :return: a logger
    """
    logger = logging.getLogger(name)
    logger.setLevel(logging.DEBUG)
    for h in handlers:
        logger.addHandler(h)

    return logger

my_main_file.py :

#!/usr/bin/python3
from telegram.ext import (Updater, CommandHandler, ConversationHandler,
                          run_async, CallbackQueryHandler)
from config.log_config import getLogger

# Enable logging
logger = getLogger(__name__)

updater = Updater('......')  # Replace with your bot token

# ************************** HANDLERS
# Define a few command handlers. These usually take the two arguments bot and
# update. Error handlers also receive the raised TelegramError object in error.


@run_async
def show_help(bot, update):
    logger.info('HELP!')


def error_handler(bot, update, error):
    logger.warning('La actualización "%s" causó el error "%s"', update, error)


def dumb_handler(bot, update, user_data):
    return ConversationHandler.END


def main():
    """Start the bot."""
    # Create the EventHandler and pass it your bot's token.
    global updater

    # Get the dispatcher to register handlers
    dp = updater.dispatcher

    # on different commands - answer in Telegram
    dp.add_handler(CommandHandler('help', show_help))

    # Add conversation handler with the states
    # The telegram conversation handler needs a handler_list with functions
    # so it can execute desired code in each state/step

    conv_handler = ConversationHandler(
        entry_points=[CommandHandler('irrelevant', dumb_handler,
                                     pass_user_data=True)
                      ],
        states={
            0: [CallbackQueryHandler(dumb_handler, pass_user_data=True)],
        },
        fallbacks=[],
    )
    dp.add_handler(conv_handler)

    # log all errors
    dp.add_error_handler(error_handler)

    updater.start_polling()
    updater.idle()


if __name__ == '__main__':
    main()

"""
OUTPUT when used /help from the bot chat
(First is my wished output, second is the line I want to avoid)
------

2018-11-08 16:41:51,115 - (1.2.0) INFO - __main__ - HELP!
INFO:__main__:HELP!
"""

1 Ответ

0 голосов
/ 08 ноября 2018

telegram.ext.ConversationHandler включает в себя несколько вызовов журнала, которые используют logging.warning вместо self.logger регистратора, который они, вероятно, должны использовать, например этот вызов :

for handler in all_handlers:
    if isinstance(handler, CallbackQueryHandler):
        logging.warning("If 'per_message=False', 'CallbackQueryHandler' will not be "
                        "tracked for every message.")

logging.warning и другие удобные функции ведения журнала на уровне модуля вызывают logging.basicConfig, который добавляет обработчик к корневому регистратору, если на корневом регистраторе нет обработчиков. Этот обработчик ответственен за нежелательный

INFO:__main__:HELP!

протоколирование выхода.

Использование logging.warning вместо self.logger.warning, вероятно, следует рассматривать как ошибку python-telegram-bot. Я не вижу открытой проблемы для их системы отслеживания проблем , поэтому вы можете подать отчет об ошибке.

Тем временем, или если разработчики python-telegram-bot решат, что поведение в порядке, вы можете добавить нулевой обработчик к корневому логгеру, чтобы basicConfig не добавил свой собственный обработчик. Это необходимо сделать до создания ConversationHandler, чтобы выгрузить basicConfig:

logging.getLogger().addHandler(logging.NullHandler())
...