-
-
Notifications
You must be signed in to change notification settings - Fork 30.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
errno and strerror attributes incorrectly set on socket errors wrapped by urllib #50720
Comments
In Python 2.6, socket.error was changed to be a child class of IOError >>> import socket
>>> from urllib import urlopen
>>> socket.setdefaulttimeout(0.01)
>>> try: urlopen('http://www.python.org')
... except Exception, e: err1 = e
...
>>> err1
IOError('socket error', timeout('timed out',))
>>> err1.errno
'socket error'
>>> err1.strerror
timeout('timed out',)
>>> err1.strerror.errno
>>> err1.strerror.strerror
>>>
>>> try: urlopen('http://www.pythonfoobarbaz.org')
... except Exception, e: err2 = e
...
>>> err2
IOError('socket error', gaierror(11001, 'getaddrinfo failed'))
>>> err1.errno
'socket error'
>>> err1.strerror
timeout('timed out',)
>>> err1.strerror.errno
>>> err2.errno
'socket error'
>>> err2.strerror
gaierror(11001, 'getaddrinfo failed')
>>> err2.strerror.errno
11001
>>> err2.strerror.strerror
'getaddrinfo failed' The 'socket error' strings doesn't provide any useful information The relevant information is not accessible directly on the error but it IMHO the first arg should be the errno (if it's available) and the The doc of socket.error 1 should be also changed because it says: |
No, it seems that 2.5 has the same problem. The 'socket error' message is |
Yes, it looks to me like urllib is intentionally putting the 'socket |
Can this be fixed without breaking compatibility? Copy/pastable snippet to reproduce the error on 2.x: Result on 2.7: Copy/pastable snippet to reproduce the error on 3.x: Result on 3.2: |
It's very hard to tell what ought to be done here, since Lib/urllib/request.py throws URLErrors with a great variety of order and number of arguments, and it's not clear how URLError (in Lib/urllib/error.py) intends to handle them. However, in this case, AbstractHTTPHandler.do_open is instantiating URLError with another exception instance, and that exception contains .errno and .strerror. URLError puts the entire error instance into In the name of keeping this information available rather than hiding it, I'm attaching a patch that adds to URLError.__init__: if hasattr(reason, "errno"):
self.errno = reason.errno
if hasattr(reason, "strerror"):
self.strerror = reason.strerror Again, I'm not sure this is the most logical approach because I can't find a consistent pattern in the ways URLError is instantiated. |
This is an interesting idea and should at least improve matters. I'm wondering, though...I seem to remember writing code that fished the wrapped error out using one of those attributrs...but I'm not at a computer where I can try to check on that. Hopefully I can check on it this weekend. |
That would be err.reason: from urllib.request import urlopen
try:
urlopen('http://www.pythonfoobarbaz.org')
except Exception as exc:
print('err:', err)
print('repr(err):', repr(err))
print('err.reason:', err.reason)
print('repr(err.reason):', repr(err.reason)) prints: err: <urlopen error [Errno -2] Name or service not known> |
Ah, of course. I should have reread the whole issue :) The backward compatibility is the big concern here. Regardless of what we do about that, we should at least fix this in 3.4. |
Reproduced on 3.11: >>> from urllib.request import urlopen
>>> try:
... urlopen('http://www.pythonfoobarbaz.org')
... except Exception as exc:
... err = exc
... print('err:', err)
... print('repr(err):', repr(err))
... print('err.errno:', err.errno)
... print('err.strerror:', err.strerror)
... print('err.reason:', err.reason)
... print('err.reason.errno:', err.reason.errno)
... print('err.reason.strerror:', err.reason.strerror)
...
err: <urlopen error [Errno 8] nodename nor servname provided, or not known>
repr(err): URLError(gaierror(8, 'nodename nor servname provided, or not known'))
err.errno: None
err.strerror: None
err.reason: [Errno 8] nodename nor servname provided, or not known
err.reason.errno: 8
err.reason.strerror: nodename nor servname provided, or not known |
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields:
The text was updated successfully, but these errors were encountered: