Python exception not caught
Question: 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.


Answer: 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](https://docs.python.org/2/library/logging.html#logging.exception):

> 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](https://docs.python.org/2/library/logging.html#logging.Formatter.formatException);
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()`](https://docs.python.org/2/library/traceback.html#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](https://docs.python.org/2/library/logging.html#logging.Formatter)
that formats the exception information without the traceback.

