Suppressing nested exception - python-3.x

In the except clause of a try...except block, is there any way to mark the current exception as handled, so if another exception is raised in the except block, it doesn't link the new exception to the old one?
Example:
from time import sleep
def connect(server):
print("Attempting to connecting to", server)
sleep(2)
raise ConnectionRefusedError("Couldn't connect")
print("Connected to", server)
try:
conn = connect('main-server')
except ConnectionRefusedError as connection_refused:
# connection_refused.handled = True
conn = connect('backup-server')
This produces:
Traceback (most recent call last):
File "<pyshell#37>", line 2, in <module>
conn = connect('main-server')
File "<pyshell#26>", line 2, in connect
raise ConnectionRefusedError("Couldn't connect")
ConnectionRefusedError: Couldn't connect
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "<pyshell#37>", line 4, in <module>
conn = connect('backup-server')
File "<pyshell#26>", line 2, in connect
raise ConnectionRefusedError("Couldn't connect")
ConnectionRefusedError: Couldn't connect
I'd like to mark the first exception as handled, so that the second exception doesn't link to the first with the "During handling of the above exception, another exception occurred" ceremony.
I realize in this simple example, I can do this by creating a flag condition, exiting the except clause, testing the flag, and resuming the recovery code.
try:
conn = connect('main-server')
except ConnectionRefusedError:
conn = None
if not conn:
conn = connect('backup-server')
Or using a for...else construct:
for server in ('main-server', 'backup-server'):
try:
conn = connect(server)
break
except ConnectionRefusedError:
continue
else:
raise ConnectionRefusedError("Couldn't connect to any server")
Finally, I know I can wrap my exception handler in a try...except block, and use raise...from None to hide the first exception.
try:
conn = connect('main-server')
except ConnectionRefusedError:
try:
conn = connect('backup-server')
except ConnectionRefusedError as nested:
raise nested from None
But I'm not looking for any "restructure the code" solutions, and I'd rather not use the try ... except ... try ... except ... raise ... from None, catching exception simply to raise it again. I'm curious if there is anything I can place at this point:
except ConnectionRefusedError as connection_refused:
# connection_refused.handled = True
which can flag the exception as being completely handled.

Related

OS Error while doing requests for images with multiple threads in python

I'm making a program that gets info from a website about games, among that info, images, since i'm trying to download info of all games on that website, using a single thread with a 1Mbps connection would be very painful, so i decided to take action against this issue and programmed to spawn a thread for each letter of the alphabet that a game starts with, (games can be filtered by such). So, inside the function that downloads the corresponding image to certain game, while i have more than one thread, at some point in execution (sooner or later) an error is raised, then inside the except block that handles it, another exception is raised, and so on, over and over... this immediately causes threads to come to an end, but the fact is that, when i'm left with only a petty single thread to rely on, that thread goes on very well without giving any trouble.
Question:
How to solve this, and why is it happening?
Deduction:
I think that, when multiple threads get to requests.get line inside the download_image function (the function where the very problem must lie), maybe it fails because of multiple requests... that is as far as i can try to guess.
I really don't have the least idea of how to solve this, that being said, i would appreciate any help, thanks in advance.
I got rid of all the functions not having to do anything with the problem described above.
I spawn the threads at program's end, and each thread target function is named get_all_games_from_letter.
CODE
from bs4 import BeautifulSoup
from string import ascii_lowercase
from datetime import date
from vandal_constants import *
from PIL import Image
from requests.exceptions import ConnectionError
from exceptions import NoTitleException
from validator_collection import url as url_check
from rawgpy import RAWG
from io import BytesIO
import traceback
import requests
import threading
import sqlite3
import concurrent.futures
### GLOBALS #####
FROM_RAWG = False
INSERT_SQL = ''
# CONSTANTS ########
rawg = RAWG('A Collector')
#################
def download_image(tag=None, game=None, rawg_game=None):
if tag:
return sqlite3.Binary(requests.get(url).content) if (url := tag['data-src']) else None
elif game:
global FROM_RAWG
img_tag = game.select_one(IMG_TAG_SELECTOR)
if img_tag and img_tag.get('data-src', None):
try:
if url_check(img_tag['data-src']):
return sqlite3.Binary(requests.get(img_tag['data-src']).content)
print(f"{img_tag['data-src']} is NOT a valid url")
except ConnectionError:
try:
print('Error While downloading from "Vandal.elespannol.com" website:')
traceback.print_exc()
except Exception:
print('Another Exception Ocurred')
traceback.print_exc()
except OSError:
print('Error en el Handshake parece')
traceback.print_exc()
FROM_RAWG = True
if rawg_game and getattr(rawg_game, 'background_image', None):
try:
print('Continue to download from RAWG')
return sqlite3.Binary(requests.get(rawg_game.background_image).content)
except ConnectionError:
print('Error While downloading from RAWG:')
traceback.print_exc()
return None
def prepare_game_record(game, db_games_set):
global INSERT_SQL
title = getattr(game.select_one(TITLE_TAG_SELECTOR), 'text', None)
if not title:
raise NoTitleException()
if title in db_games_set:
print(f'Already Have {title} in database')
return None
description = game.select_one(DESCRIPTION_TAG_SELECTOR)
rawg_game = None
try:
rawg_game = rawg.search(title)[0]
except Exception as err:
print('No rawg')
traceback.print_exc()
game_data = {
'nombre': title,
'descripcion': description.text if description else rawg_game.description if rawg_game else '',
'genero': genres if (genres := translate_genres(game.select_one(GENRES_TAG_SELECTOR).contents[1].strip().split(' / '))) else '',
'fondo': resize_image(img) if (img := download_image(game=game, rawg_game=rawg_game)) and not FROM_RAWG else img,
'year': None,
}
if not INSERT_SQL:
INSERT_SQL = construct_sql_insert(**game_data)
if hasattr(rawg_game, 'released'):
game_data['year'] = date.fromisoformat(rawg_game.released).year
return tuple(game_data.values())
def get_all_games_from_letter(letter):
global FROM_RAWG
counter = 36
hashes_set = set()
with sqlite3.connect('/media/l0new0lf/LocalStorage/data.db') as connection:
cursor = connection.cursor()
cursor.execute(f'SELECT nombre FROM juegos where nombre like "{letter.upper()}%"')
db_games_set = []
for row in cursor:
db_games_set.append(row[0])
db_games_set = set(db_games_set)
while True:
try:
prepared_games = []
rq = requests.get(
f'https://vandal.elespanol.com/juegos/13/pc/letra/{letter}/inicio/{counter}')
if rq:
print('Request GET: from ' +
f'https://vandal.elespanol.com/juegos/13/pc/letra/{letter}/inicio/{counter}' + ' Got Workable HTML !')
else:
print('Request GET: from ' +
f'https://vandal.elespanol.com/juegos/13/pc/letra/{letter}/inicio/{counter}' + ' Not Working !!, getting next page!')
continue
if rq.status_code == 301 or rq.status_code == 302 or rq.status_code == 303 or rq.status_code == 304:
print(f'No more games in letter {letter}\n**REDIRECTING TO **')
break
counter += 1
soup = BeautifulSoup(rq.content, 'lxml')
main_table = soup.select_one(GAME_SEARCH_RESULTS_TABLE_SELECTOR)
if hash(main_table.get_text()) not in hashes_set:
hashes_set.add(hash(main_table.get_text()))
else:
print('Repeated page ! I\'m done with this letter.')
break
game_tables = main_table.find_all(
'table', {'class': GAME_TABLES_CLASS})
print('entering game_tables loop')
for game in game_tables:
FROM_RAWG = False
try:
game_record = prepare_game_record(game, db_games_set)
except NoTitleException:
print('There is no title for this game, DISCARDING!')
continue
except Exception as err:
print('Unknown ERROR in prepare_games_record function')
traceback.print_exc()
continue
if not game_record:
continue
prepared_games.append(game_record)
print('Game successfully prepared !')
if prepared_games:
print(f'Thread, Writing to Database')
try:
cursor.executemany(INSERT_SQL, prepared_games)
connection.commit()
except Exception as err:
print(err)
print('done')
except Exception as err:
print('TRULY UNEXPECTED EXCEPTION')
print(err)
traceback.print_exc()
continue
#get_all_games_from_letter('c') You use a single thread?, no trouble at all!!
with concurrent.futures.ThreadPoolExecutor(len(ascii_lowercase)) as executor:
for letter in ascii_lowercase:
executor.submit(get_all_games_from_letter, letter)
Error Stack Trace:
Note: This is only part of the errors, but the rest is the very same.
Game successfully prepared !
Error While downloading from "Vandal.elespannol.com" website:
Traceback (most recent call last):
File "/usr/lib/python3/dist-packages/urllib3/connectionpool.py", line 665, in urlopen
httplib_response = self._make_request(
File "/usr/lib/python3/dist-packages/urllib3/connectionpool.py", line 376, in _make_request
self._validate_conn(conn)
File "/usr/lib/python3/dist-packages/urllib3/connectionpool.py", line 996, in _validate_conn
conn.connect()
File "/usr/lib/python3/dist-packages/urllib3/connection.py", line 366, in connect
self.sock = ssl_wrap_socket(
File "/usr/lib/python3/dist-packages/urllib3/util/ssl_.py", line 370, in ssl_wrap_socket
return context.wrap_socket(sock, server_hostname=server_hostname)
File "/usr/lib/python3.8/ssl.py", line 500, in wrap_socket
return self.sslsocket_class._create(
File "/usr/lib/python3.8/ssl.py", line 1040, in _create
self.do_handshake()
File "/usr/lib/python3.8/ssl.py", line 1309, in do_handshake
self._sslobj.do_handshake()
OSError: [Errno 0] Error
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/usr/lib/python3/dist-packages/requests/adapters.py", line 439, in send
resp = conn.urlopen(
File "/usr/lib/python3/dist-packages/urllib3/connectionpool.py", line 719, in urlopen
retries = retries.increment(
File "/usr/lib/python3/dist-packages/urllib3/util/retry.py", line 400, in increment
raise six.reraise(type(error), error, _stacktrace)
File "/usr/lib/python3/dist-packages/six.py", line 702, in reraise
raise value.with_traceback(tb)
File "/usr/lib/python3/dist-packages/urllib3/connectionpool.py", line 665, in urlopen
httplib_response = self._make_request(
File "/usr/lib/python3/dist-packages/urllib3/connectionpool.py", line 376, in _make_request
self._validate_conn(conn)
File "/usr/lib/python3/dist-packages/urllib3/connectionpool.py", line 996, in _validate_conn
conn.connect()
File "/usr/lib/python3/dist-packages/urllib3/connection.py", line 366, in connect
self.sock = ssl_wrap_socket(
File "/usr/lib/python3/dist-packages/urllib3/util/ssl_.py", line 370, in ssl_wrap_socket
return context.wrap_socket(sock, server_hostname=server_hostname)
File "/usr/lib/python3.8/ssl.py", line 500, in wrap_socket
return self.sslsocket_class._create(
File "/usr/lib/python3.8/ssl.py", line 1040, in _create
self.do_handshake()
File "/usr/lib/python3.8/ssl.py", line 1309, in do_handshake
self._sslobj.do_handshake()
urllib3.exceptions.ProtocolError: ('Connection aborted.', OSError(0, 'Error'))
To solve the problem what one would need is just add a global lock in order that when each thread tries to request.get an image, it has to ask in the first place if some thread is already using it. That is, downloading an image is restricted to just simultaneously one use for all threads
#######GLOBALS####
lock = threading.Lock() #Add this to globals variables
##################
def download_image(tag=None, game=None, rawg_game=None):
if tag:
return sqlite3.Binary(requests.get(url).content) if (url := tag['data-src']) else None
elif game:
global FROM_RAWG
img_tag = game.select_one(IMG_TAG_SELECTOR)
if img_tag and img_tag.get('data-src', None):
try:
if url_check(img_tag['data-src']):
lock.acquire() #acquire the lock for downloading (it means other threads must wait until the one that acquired finishes)
temp = sqlite3.Binary(requests.get(img_tag['data-src']).content)
lock.release() # release the lock when done with receiving the HttpResponse
return temp
print(f"{img_tag['data-src']} is NOT a valid url")
except ConnectionError:
try:
print('Error While downloading from "Vandal.elespannol.com" website:')
traceback.print_exc()
except Exception:
print('Another Exception Ocurred')
traceback.print_exc()
except OSError:
print('Error en el Handshake parece')
traceback.print_exc()
FROM_RAWG = True
if rawg_game and getattr(rawg_game, 'background_image', None):
try:
print('Continue to download from RAWG')
lock.acquire() #acquire the lock for downloading (it means other threads must wait until the one that acquired finishes)
temp = sqlite3.Binary(requests.get(rawg_game.background_image).content)
lock.release() # release the lock when done with
return temp
except ConnectionError:
print('Error While downloading from RAWG:')
traceback.print_exc()
return None
And done, no more troubles with downloading images in multiple threads.... but still... i don't actually know why i would need to make sure of that one request.get is made for all threads, i thought OS handles this issue by using queues or something.

Gtk.Application.run() versus Gtk.main() Last Chance Exception Handling in Python3

I created a last chance exception handler for my test Gtk.Application but it is never hit. However if I don't use Gtk.Application but use Gtk.main() to start my test app, the last chance exception handler is hit.
The sample below has 2 functions (test_gtk_main() and test_gtk_application()) which show what I mean. Both functions deliberately cause a NameError: name '_on_window_delete' is not defined. Both functions have a last chance exception handler. Only the exception handler for test_gtk_main() is hit.
My question: How can I modify test_gtk_application so the last chance exception handler is hit?
Sample code:
import logging
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, Gio
#set up logging
date_fmt = '%Y-%m-%d,%H:%M:%S'
log_format = '%(levelname)s %(asctime)s.%(msecs)03d %(name)s.%(funcName)s %(message)s'
logging.basicConfig(format=log_format, datefmt=date_fmt, level=logging.INFO)
_logger = logging.getLogger(__name__)
_logger.info('Gtk version is %s.%s.%s', Gtk.MAJOR_VERSION, Gtk.MINOR_VERSION, Gtk.MICRO_VERSION)
def test_gtk_main():
try:
window = Gtk.Window(title="Window")
window.connect("delete-event", _on_window_delete)
window.show_all()
Gtk.main()
except Exception as ex:
_logger.exception("\nLast Chance Exception Gtk.main() Caught '%s'", ex)
def test_gtk_application():
try:
app_id = "org.foo.example"
flags = Gio.ApplicationFlags.FLAGS_NONE
app = Gtk.Application.new(app_id, flags)
app.connect("startup", do_startup, app)
app.connect("activate", do_activate, app)
app.connect("shutdown", do_shutdown, app)
app.run()
except Exception as ex: #never hit
_logger.exception("\nLast Chance Exception Gtk.Application() Caught '%s'", ex)
def do_startup(self, app):
_logger.debug("entered do_startup")
def do_activate(self, app):
win = Gtk.ApplicationWindow(title="Test")
win.connect("delete-event", _on_window_delete)
def do_shutdown(self, app):
_logger.debug("entered do_shutdown")
if __name__ == "__main__":
test_gtk_main() #exception handler hit
test_gtk_application() #exception handler ignored
And here is the output (run from terminal on Ubuntu 18.04)
$ python3 test_gtk_exception_handler_3.py
INFO 2020-07-18,12:47:37.849 __main__.<module> Gtk version is 3.22.30
ERROR 2020-07-18,12:47:37.880 __main__.test_gtk_main
Last Chance Exception Gtk.main() Caught 'name '_on_window_delete' is not defined'
Traceback (most recent call last):
File "test_gtk_exception_handler_3.py", line 17, in test_gtk_main
window.connect("delete-event", _on_window_delete)
NameError: name '_on_window_delete' is not defined
Traceback (most recent call last):
File "test_gtk_exception_handler_3.py", line 40, in do_activate
win.connect("delete-event", _on_window_delete)
NameError: name '_on_window_delete' is not defined
The problem is you are trying to catch the exception in the wrong place.
the exception is function named "_on_window_delete" is not defined.
In test_gtk_main function, you are directly trying to connect to "_on_window_delete" that's why you are catching that error.
But in test_gtk_application you are adding "do_activate" as a callback function so the function "_on_window_delete" is not directly executed in the try statement. That's why you are not catching an error. but if you move the try clause to do_activate function it will work properly.
def do_activate(self, app):
try:
win = Gtk.ApplicationWindow(title="Test")
win.connect("delete-event", _on_window_delete)
except Exception as ex: #never hit
_logger.exception("\nLast Chance Exception Gtk.Application() Caught '%s'", ex)
or if you move that exception code to the try clause in function "test_gtk_application"
that will also catch the exception
def test_gtk_application():
try:
app_id = "org.foo.example"
flags = Gio.ApplicationFlags.FLAGS_NONE
app = Gtk.Application.new(app_id, flags)
win = Gtk.ApplicationWindow(title="Test")
app.connect("startup", do_startup, app)
app.connect("activate", do_activate, app)
app.connect("shutdown", do_shutdown, app)
win.connect("delete-event", _on_window_delete)
app.run()
except Exception as ex: #never hit
_logger.exception("\nLast Chance Exception Gtk.Application() Caught '%s'", ex)
then you would get the exception as below
INFO 2020-07-19,13:49:57.773 __main__.<module> Gtk version is 3.24.20
ERROR 2020-07-19,13:49:58.091 __main__.test_gtk_main
Last Chance Exception Gtk.main() Caught 'name '_on_window_delete' is not defined'
Traceback (most recent call last):
File "exception.py", line 17, in test_gtk_main
window.connect("delete-event", _on_window_delete)
NameError: name '_on_window_delete' is not defined
ERROR 2020-07-19,13:49:58.092 __main__.test_gtk_application
Last Chance Exception Gtk.Application() Caught 'name '_on_window_delete' is not defined'
Traceback (most recent call last):
File "exception.py", line 33, in test_gtk_application
win.connect("delete-event", _on_window_delete)
NameError: name '_on_window_delete' is not defined
basically, to catch an exception it has to run in the try clause, or else you won't be able to catch that error. for more details, I would suggest you look into (https://docs.python.org/3/tutorial/errors.html)

deliberately Raise and throw an exception in python

I have a use case where I need to raise an exception and again throw the exception. For this I'm using raise keyword in both try and catch. The code is as below
try:
username = input ("username:")
If Len(username) != 6:
raise Exception
except Exception:
raise Exception ("username is not valid")
Is this the right way to do like this? Is it compliant to coding standards to raise Exception in both try and except blocks?
I'm guessing this is a simplified version of your actual use case, in which case it is generally correct. A couple of notes:
You can use raise without anything after it to re-raise the same error.
try:
raise ValueError('message')
except ValueError:
run_something()
raise # will raise ValueError ('message')
Don't raise a general Exception and don't catch them either, be specific, otherwise this code will obscure other errors and will be difficult to debug. If nothing else suits you, make an exception of your own:
class MyException(Exception):
pass
Then you can use it:
raise MyException('my message')
In your use case, if I understood it correctly, all of this together would be:
class InvalidUsername(Exception):
pass
try:
username = input('username: ')
if len(username) > 6:
raise InvalidUsername('Username is too long')
if '!' in username:
raise InvalidUsername('Invalid character in username')
except InvalidUsername:
handle_invalid_user()
raise
Example in the console:
>>> try:
... username = input('username: ')
... if len(username) > 6:
... raise InvalidUsername('Username is too long')
... if '!' in username:
... raise InvalidUsername('Invalid character in username')
... except InvalidUsername:
... handle_invalid_user()
... raise
...
username: test1234
Traceback (most recent call last):
File "<stdin>", line 4, in <module>
__main__.InvalidUsername: Username is too long
Or with an invalid character:
username: ofer!
Traceback (most recent call last):
File "<stdin>", line 6, in <module>
__main__.InvalidUsername: Invalid character in username
I was also looking to raise an exception when there is an error within the business logic from an external server and due to database connection.
I came across this arcticle to basically raise the exception especially when you are follwing an Controller-> Service -> Repository pattern.
https://flask.palletsprojects.com/en/2.1.x/errorhandling/
from flask import jsonify, request
class InvalidAPIUsage(Exception):
status_code = 400
def __init__(self, message, status_code=None, payload=None):
super().__init__()
self.message = message
if status_code is not None:
self.status_code = status_code
self.payload = payload
def to_dict(self):
rv = dict(self.payload or ())
rv['message'] = self.message
return rv
#app.errorhandler(InvalidAPIUsage)
def invalid_api_usage(e):
return jsonify(e.to_dict()), e.status_code
# an API app route for getting user information
# a correct request might be /api/user?user_id=420
#app.route("/api/user")
def user_api(user_id):
user_id = request.arg.get("user_id")
if not user_id:
raise InvalidAPIUsage("No user id provided!")
user = get_user(user_id=user_id)
if not user:
raise InvalidAPIUsage("No such user!", status_code=404)
return jsonify(user.to_dict())
[1]: https://flask.palletsprojects.com/en/2.1.x/errorhandling/
I hope this helps to developers who are developing enterprise level apps.

Keyboard Interrupting an asyncio.run() raises CancelledError and keeps running the code

I have inspected this SO question on how to gracefully close out the asyncio process. Although, when I perform it on my code:
async def ob_main(product_id: str, freq: int) -> None:
assert freq >= 1, f'The minimum frequency is 1s. Adjust your value: {freq}.'
save_loc = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'data', 'ob', product_id)
while True:
close = False
try:
full_save_path = create_save_location(save_loc)
file = open(full_save_path, 'a', encoding='utf-8')
await ob_collector(product_id, file)
await asyncio.sleep(freq)
except KeyboardInterrupt:
close = True
task.cancel()
loop.run_forever()
task.exception()
except:
exc_type, exc_value, exc_traceback = sys.exc_info()
error_msg = repr(traceback.format_exception(exc_type, exc_value, exc_traceback))
print(error_msg)
logger.warning(f'[1]-Error encountered collecting ob data: {error_msg}')
finally:
if close:
loop.close()
cwow()
exit(0)
I get the following traceback printed in terminal:
^C['Traceback (most recent call last):\n', ' File "/anaconda3/lib/python3.7/asyncio/runners.py", line 43, in run\n return loop.run_until_complete(main)\n', ' File "/anaconda3/lib/python3.7/asyncio/base_events.py", line 555, in run_until_complete\n self.run_forever()\n', ' File "/anaconda3/lib/python3.7/asyncio/base_events.py", line 523, in run_forever\n self._run_once()\n', ' File "/anaconda3/lib/python3.7/asyncio/base_events.py", line 1722, in _run_once\n event_list = self._selector.select(timeout)\n', ' File "/anaconda3/lib/python3.7/selectors.py", line 558, in select\n kev_list = self._selector.control(None, max_ev, timeout)\n', 'KeyboardInterrupt\n', '\nDuring handling of the above exception, another exception occurred:\n\n', 'Traceback (most recent call last):\n', ' File "coinbase-collector.py", line 98, in ob_main\n await asyncio.sleep(freq)\n', ' File "/anaconda3/lib/python3.7/asyncio/tasks.py", line 564, in sleep\n return await future\n', 'concurrent.futures._base.CancelledError\n']
and the code keeps running.
task and loop are the variables from the global scope, defined in the __main__:
loop = asyncio.get_event_loop()
task = asyncio.run(ob_main(args.p, 10))
Applying this question's method solves the issue. So in the above case:
try:
loop.run_until_complete(ob_main(args.p, 10))
except KeyboardInterrupt:
cwow()
exit(0)
However, I do not uderstand why that works.

Python 3.5.2: socket.timeout exception causes typeerror

I'm a bit of a Python newbie and this is my first post to stackoverflow so please bear with me. :)
Before posting i have searched google and stackoverflow but cant seem to find anything similar to my issue.
I have a script that polls a website and retrieves the content.
It works fine for hours however if it encounters a socket timeout the script throws a typeerror even though I have an exception for it.
I'm sure I am missing something obvious, but cant put my finger on it.
Code:
timingout = 10
def get_url(url):
try:
sock = urllib.request.urlopen(url, timeout=timingout)
orig_html = sock.read()
html = orig_html.decode("utf-8", errors="ignore").encode('cp1252', errors='ignore')
sock.close()
except KeyboardInterrupt:
# Kill program if Control-C is pressed
sys.exit(0)
except urllib.error.URLError as e:
print("***Error= Page ", e.reason)
return
except timingout:
print("socket timed out - URL: %s", url)
else:
# See if site is Down or errors eg: 404
if html == None:
print ("page contains no content!?!")
return ''
# See if site is complaining
elif html == site_overload:
if _verbose:
print('ERROR: Too many requests - SLEEPING 600 secs')
time.sleep(600)
return ''
# If not, we are good
elif html:
return html
error:
return self._sock.recv_into(b)
**socket.timeout: timed out**
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "test.py", line 201, in <module>
main()
File "test.py", line 140, in main
http_text = get_text(site_id)
File "test.py", line 110, in get_text
return get_url(url)
File "test.py", line 59, in get_url
except timingout:
**TypeError: catching classes that do not inherit from BaseException is not allowed**
Thanks in advance for any suggestions & help!
It's caused by trying to use timingout to catch an exception. timingout is an integer object whereas the except statement only accepts objects inherited from the BaseException class.
Remove that except because it doesn't do anything. Also consider revising your try statement to only include a single operation. It will make troubleshooting easier and prevent you from having to break up your try statements later on when a bug occurs.

Resources