After seeing this error with my urlopen() function:
Traceback (most recent call last): File "test_urlopen.py", line 47, in <module> response = request.urlopen(req, data, context=ctx) File "/lib64/python/lib/urllib/request.py", line 227, in urlopen return opener.open(url, data, timeout) File "/lib64/python/lib/urllib/request.py", line 541, in open response = meth(req, response) File "/lib64/python/lib/urllib/request.py", line 653, in http_response response = self.parent.error( File "/lib64/python/lib/urllib/request.py", line 580, in error return self._call_chain(*args) File "/lib64/python/lib/urllib/request.py", line 508, in _call_chain result = func(*args) File "/lib64/python/lib/urllib/request.py", line 663, in http_error_default raise HTTPError(req.full_url, code, msg, hdrs, fp) urllib.error.HTTPError: HTTP Error 400:
I wrote a catch exception, but fp is empty when I printed it out. Any ideas?
try: response = request.urlopen(req, data, context=ctx) except urllib.error.HTTPError as e: print ("the exception is %s " % str(e.fp()) print ("the exception is %s " % str(e.fp.readlines())) exit(0)
Output:
the exception is <http.client.HTTPResponse object at 0xd1b9615640> the exception is []
fp isn’t empty in the HTTPError class
class HTTPDefaultErrorHandler(BaseHandler): def http_error_default(self, req, fp, code, msg, hdrs): print (str(fp))) print (fp.readlines()) raise HTTPError(req.full_url, code, msg, hdrs, fp)
Output:
"fp <http.client.HTTPResponse object at 0xd1b9615640> [b'{"code":"6006","reason":"Failed to update".....}']
Thanks.
Advertisement
Answer
Perhaps I’m dense; but a few items that might help you.
You have an errant
"
in yourprint("str(fp))
. (Thanks to @CrazyChucky for pointing that out. Was particularly stupid of me to miss that. Made more sense without the"
)In your code:
class HTTPDefaultErrorHandler(BaseHandler): def http_error_default(self, req, fp, code, msg, hdrs): print (str(fp)) print (fp.readlines()) raise HTTPError(req.full_url, code, msg, hdrs, fp)
I noticed you do a print (fp.readlines())
and then raise the error.
After that print (fp.readlines())
, the filepointer will be at the
end of the file. So any further fp.readlines()
will return []
I’d suggest the following:
class HTTPDefaultErrorHandler(BaseHandler): def http_error_default(self, req, fp, code, msg, hdrs): print (str(fp)) print (fp.readlines()) fp.seek(0) raise HTTPError(req.full_url, code, msg, hdrs, fp)
After noticing that the OP got an error with the fp.seek(0)
,
and noticing that fp is a HTTPResponse
object,
I’m not sure it’s even possible to do an analogous seek()
action as the internal fp
of HTTPResponse is a socket file
which (iiuc), doesn’t allow seeking.
With that said, and if someone smarter than me can correct me, the options are:
Remove the
fp.readlines()
altogether as that will set the fp pointer to the end and you can’t reset it.Copy the fp.readlines() items to a new file object (BytesIO()) and pass that to HTTPError.
i.e.
class HTTPDefaultErrorHandler(BaseHandler): def http_error_default(self, req, fp, code, msg, hdrs): print (str(fp)) olddata = fp.readlines() new_fp = io.BytesIO(olddata) new_fp.seek(0) raise HTTPError(req.full_url, code, msg, hdrs, new_fp)
A possible problem that I see is if HTTPError requires new_fp to be a HTTPResponse object. But since this is a RAISE line, the script/program would stop (assuming here..).
This is what I believe will give you what you want, though I’m doubtful it is 100% what you want. I apologize.