Noxet
Noxet

Reputation: 270

Python exception not caught

I am currently playing with sockets and JSON in Python where I have the following code:

class RCHandler(SocketServer.BaseRequestHandler):    
    def setup(self):
        pass

    def handle(self):
        raw = self.request.recv(1024)
        recv = raw.strip()

        if not recv:
            return

        # do some logging
        logging.debug("RECV: (%s)" % recv)

        try:
            data = json.loads(recv)
        except:
            logging.exception('JSON parse error: %s' % recv)
            return

        if recv == 'quit':
            return

The problem is that when I send a faulty JSON string, e.g. '{"method": "test"', the exception seems to be caught, but I still get the following traceback:

DEBUG: 20/09/2015 12:33:57 - RECV: ({"method": "test")
ERROR: 20/09/2015 12:33:57 - JSON parse error: {"method": "test"
Traceback (most recent call last):
  File "./remoteControl.py", line 68, in handle
    data = json.loads(recv)
  File "/usr/lib/python2.7/json/__init__.py", line 338, in loads
    return _default_decoder.decode(s)
  File "/usr/lib/python2.7/json/decoder.py", line 366, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
  File "/usr/lib/python2.7/json/decoder.py", line 382, in raw_decode
    obj, end = self.scan_once(s, idx)
ValueError: Expecting object: line 1 column 17 (char 16)

What am I missing here? I am not supposed to get a traceback if I catch the exception right? My server class extends ThreadingTCPServer if that has anything to do with it.

When I ran another python script:

#!/usr/bin/python

import json
import socket

d = '{"method": "test"'

try:
    data = json.loads(d)
except:
    print "fail"

It only prints "fail" and no traceback.

Upvotes: 1

Views: 8037

Answers (1)

Martijn Pieters
Martijn Pieters

Reputation: 1125148

You did catch the exception, but you are telling logging to include the exception information (which includes the traceback), by using the Logger.exception method here:

except:
    logging.exception('JSON parse error: %s' % recv)

From the method documentation:

Logs a message with level ERROR on the root logger. The arguments are interpreted as for debug(), except that any passed exc_info is not inspected. Exception info is always added to the logging message. This function should only be called from an exception handler.

Emphasis mine.

Also see the Formatter.formatException() documentation; it is this method that does the exception formatting here:

Formats the specified exception information (a standard exception tuple as returned by sys.exc_info()) as a string. This default implementation just uses traceback.print_exception(). The resulting string is returned.

and traceback.print_exception() does this:

Print exception information and up to limit stack trace entries from traceback to file.

If you did not want the exception to be included, use logging.error() instead:

except:
    logging.error('JSON parse error: %s' % recv)

or provide a custom Formatter subclass that formats the exception information without the traceback.

Upvotes: 5

Related Questions