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.
Perhaps I'm dense; but a few items that might help you.
You have an errant "
in your print("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.