Easy way to find "not enough arguments ..." in python protocol library

Do you know any simple way to find a log call that calls "not enough argumenst for format string". On my workstation, I changed logging/__init__.py to print msg so that I can easily find the line in the source.

But do you know what to do in a test environment where you cannot change the standard python library and run pdb easily?

Note. Tracing is pointless, and it is stored in the registration library. Here is the trace:

  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 

And here is the code in the standard library that catches the error

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

Solution suggested by Alex: I wrapped getMessage to print msg and args. Here is the code:

 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) 
+7
python debugging
source share
2 answers

Generally, the best way to catch an exception (including the one you mention) is to put suspicious code in the try clause of the try / except try ; in the except clause, you can use the traceback module or other methods to define an erroneous statement.

Otherwise, uncaught exceptions end in sys.excepthook , which is another way you can use to get traces if necessary.

However, I don’t think that the logging module has an architectural way of telling it: “Let exceptions apply” - in this case, your best choice, however dirty it may be, is probably a monkey fix. In other words, you can usually "change the standard Python library" at runtime by setting identifiers in it for your own functions / classes / etc, wrapping the standard ones. For example, if you know that the problem is with the logging.warning call, it might be: "proof of concept" monkeypatch:

 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 

There are cleaner methods, but they can be somewhat cumbersome (for example, create your own registrar class and set it as the root log). Monkey-patching is not a good way to work in a production environment (it is fragile for system updates, it can be difficult to understand and maintain, etc.), but it may be acceptable for debugging and testing purposes.

+2
source share

To find a log call that produces "not enough argumenst for the format string".

I grep source for all registration calls. There are not many of them: .info( , .warn( , .debug( , .error( , .critical( , .exception( , .log( .

One of these methods has a format without sufficient arguments. This is usually easy to notice, as the message will have the format operators "%".

If your application is consistent when calling all logger logs, this makes it even easier, since you can more easily grep for logger. .

0
source share

All Articles