felix001
felix001

Reputation: 16731

Python Exceptions Logging

Im currently logging the exceptions of a program via...

def log_message(text):
    log_file = "/var/log/logfile.txt"

    try:
        if os.path.isfile(log_file):
            mode = "a"
        else:
            mode = "w"

        with open(log_file, mode) as myfile:
            myfile.write("%s\n" % (text))

        return True

    except Exception as e:
        print "error : ",e
        return False

try:
    ... some code

except Exception as e:
        log_message("error : %s" % (e))

However im my log I get "TypeError: argument of type 'NoneType' is not iterable" Is there a way to also log the other info from the exception like below. Such as the line number the module file etc etc ?

>>> post_builder_ghost(abc).generate()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "post_builder.py", line 34, in generate
    if 'youtube' in self.video:
TypeError: argument of type 'NoneType' is not iterable
>>>

Thanks,

Upvotes: 0

Views: 545

Answers (2)

exhuma
exhuma

Reputation: 21747

To answer your question directly: look at traceback.print_exc

BUT...

You should have a look at standard logging (tutorial). Your code would become (in it's simplest form):

import logging
logging.basicConfig(stream=open("/var/log/logfile.txt", "a+"))

LOG = logging.getLogger(__name__)

try:
   ... some code
except Exception as e:
   LOG.exception("human readable explanation of what you did")

As mentioned, this is the simplest form of logging. You can got much further than this! Personally, I would advise against basicConfig. But to get you going quickly it will do just fine.

Diving into the logging config you will be able to do much more useful things, like writing debug info in one file, and error messages into another file (or stream like stderr, stdout).

It also supports what you asked, like logging module name, filename and line number, but this is disabled by default. You can enable it, by specifying your own message format (see LogRecord objects for a reference of the fields):

logging.basicConfig(stream=open("/var/log/logfile.txt", "a+"),
                    format="%(levelname)s:%(name)s:%(pathname)s:%(lineno)s:%(message)s")

The LOG.exception method I used above will include the stack trace (which is what you wanted). You have other methods (.debug, .info, .warning, .error, .critical) which will only emit the message.

As a rule of thumb, you want to configure the logging system as soon as possible in your application, but don't do it at the module level to avoid interfering with other libraries if possible. If it's a console application, "entry points" will help (or protect it with an if __name__ == '__main__' block.

After configured (either manually, or using basicConfig), you can then put this in each of your modules:

import logging
LOG = logging.getLogger(__name__)

Which will give a logger (LOG) dedicated to that module and enables you to configure logging (increase/decrease verbosity for example) per module later on (even at run-time).

Upvotes: 1

Omid Raha
Omid Raha

Reputation: 10690

You can use traceback.format_exc.

import traceback

try:
    some code ...
except Exception:
    exp = traceback.format_exc()
    log_message("error : %s" % (exp))

Upvotes: 0

Related Questions