Простой способ найти «недостаточно аргументов ...» в библиотеке журналов python - PullRequest
7 голосов
/ 19 марта 2010

Знаете ли вы какой-либо простой способ найти вызов журнала, который выдает «недостаточно аргументов для строки формата». На моей рабочей станции я изменил logging/__init__.py для вывода сообщения, чтобы я мог легко найти строку в источнике.

Но знаете ли вы, что делать в среде тестирования, где вы не можете ни изменить стандартную библиотеку Python, ни запустить pdb легко?

Примечание: Трассировка не имеет смысла, и она осторожна библиотекой журналов. Вот обратная связь:

  File "/usr/lib/python2.6/logging/handlers.py", line 71, in emit
    if self.shouldRollover(record):
  File "/usr/lib/python2.6/logging/handlers.py", line 144, in shouldRollover
    msg = "%s\n" % self.format(record)
  File "/usr/lib/python2.6/logging/__init__.py", line 648, in format
    return fmt.format(record)
  File "/usr/lib/python2.6/logging/__init__.py", line 436, in format
    record.message = record.getMessage()
  File "/usr/lib/python2.6/logging/__init__.py", line 306, in getMessage
    msg = msg % self.args
TypeError: not enough arguments for format string

А вот код в стандартной библиотеке, который ловит ошибку

    try:
        if self.shouldRollover(record):
            self.doRollover()
        logging.FileHandler.emit(self, record)
    except (KeyboardInterrupt, SystemExit):
        raise
    except:
        self.handleError(record)

Решение, предложенное Алексом: Я обернул getMessage для печати сообщения и аргументов. Вот код:

def print_log_record_on_error(func):
    def wrap(self, *args, **kwargs):
        try:
            return func(self, *args, **kwargs)
        except:
            import sys
            print >>sys.stderr, "Unable to create log message msg=%r, args=%r " % (
                                getattr(self, 'msg', '?'), getattr(self, 'args', '?'))
            raise
    return wrap
import logging
logging.LogRecord.getMessage = print_log_record_on_error(logging.LogRecord.getMessage)

Ответы [ 2 ]

2 голосов
/ 19 марта 2010

Как правило, лучший способ отловить исключение (включая упомянутое вами) - поместить подозрительный код в предложение try оператора try / except; в предложении except вы можете использовать модуль traceback или другие способы точного определения ошибочного оператора.

В противном случае неперехваченные исключения заканчиваются на sys.excepthook , что является другим способом, который можно использовать для получения трассировки при необходимости.

Однако я не думаю, что у модуля logging есть спроектированный способ сказать ему: «пусть распространяются исключения» - в этом случае ваша лучшая ставка, какой бы грязной она ни была, вероятно, является мартышкой. Другими словами, вы, как правило, можете «изменить стандартную библиотеку Python» во время выполнения - установив идентификаторы в них для своих собственных функций / классов / и т. Д., Оборачивая стандартные идентификаторы. Например, если вы знаете, что проблема связана с вызовом logging.warning, то может быть получен обезьяна «подтверждение концепции»:

import logging, traceback

orgwarn = logging.warning
def mywarn(msg, *a):
  try: res = msg % a
  except TypeError:
    traceback.print_exc()
  return orgwarn(msg, *a)
logging.warning = mywarn

Существуют более чистые способы, но они могут быть несколько громоздкими (например, создайте свой собственный класс logger и установите его в качестве корневого logger). Обезьяны-исправления не являются хорошим способом работы в производственной среде (они хрупки по отношению к обновлениям системы, их трудно понять и поддерживать и т. Д.), Но они могут быть приемлемы для целей отладки и тестирования.

0 голосов
/ 19 марта 2010

Чтобы найти вызов журналирования, который выдает «недостаточно аргументов для строки формата».

Я извлекаю источник для всех вызовов журналирования.Их не так много: .info(, .warn(, .debug(, .error(, .critical(, .exception(, .log(.

Один из этих методов имеет формат без достаточного количествааргументы.Как правило, это легко обнаружить, поскольку в сообщении будут использоваться операторы форматирования "%".

Если ваше приложение последовательно в вызове всех регистраторов, logger делает это еще проще, поскольку вы можете просто использовать grep для * 1015.*.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...