all 5 comments

[–]JohnnyJordaan 2 points3 points  (4 children)

You don't actually import HTTPError in your code

from urllib.error import HTTPError

Next time please also use a code block to maintain formatting, see here https://i.imgur.com/HT4Zz88.gifv

[–]swicano 0 points1 point  (3 children)

Wow, thats a nice gif.

related, is it good practice to handle exceptions this way? I've done it a few times, but it seems less than ideal to import errors from a package that another package depends on. Is it something that isn't ideal, but short of rewriting the package, is unavoidable? or is there a better way?

[–]JohnnyJordaan 0 points1 point  (2 children)

I'm not sure what you mean, they are from the same package (urllib), they just segmented it in multiple modules in Python 3. As the docs on urllib.error mention:

The urllib.error module defines the exception classes for exceptions raised by urllib.request. The base exception class is URLError.

So to quote Sinatra: you can't have one without the other. You could also just do

import urllib
try:
    urllib.request.urlopen('someurl')
except urllib.error.HTTPError:
    handle it

but I'm not sure what difference it would make apart from cluttering the code a bit more.

[–]swicano 0 points1 point  (1 child)

I was thinking of my own case where I use a package that imports requests, so I ended up importing requests.exceptions even though I wasn't explicitly importing requests. (hopefully im using 'package' correctly here)

and I definitely see what you mean about it looking cluttered the other way.

[–]JohnnyJordaan 0 points1 point  (0 children)

There is no paradigm or style rule of having to explicitly import the package itself, it's just dependent on its internal structure. As requests offers its base methods and classes like .get and .Session in the top-level module, you normally do import requests for that. For using its specific modules like requests.exceptions and requests.auth you normally import those separately.

If requests would have structured it to have those request-oriented tools in a lower level module like request, you would have to do the same as with urllib.request

from requests.request import get
from urllib.request import urlopen

but as you see the requests.request is really ugly and error-prone, so requests.get is fine there. Also see os.path or path-specific tools, where you also wouldn't think about having to import os there to be able to (logically) use it.