For troubleshooting do not catch the exception. The traceback would be more comprehensible without try-except and your custom exception printing. It would be easier for us to understand what is going on.
For exception handling in production code do not catch whole Exception class. You are effectively making yourself blind for errors. See for example this recent post:
There is also a problem in the urllib code:
The code raising a new exception should be:
except OSError as err: # timeout error
# Here we should probably test if it is really a timeout error?
raise URLError(err) from err
The current code confusingly writes:
During handling of the above exception, another exception occurred:
The fixed code would write the following text which explains what is going on:
The above exception was the direct cause of the following exception: