Reputation: 270
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
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 fordebug()
, except that any passedexc_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 usestraceback.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