i wrote a code which is dumping numbers which is collected from serial port read as follows:
readoff = ser.readline()
and the proper format of readoff is follows:
a=' 213 -456 725'
and then for dumping and making some calculations im splitting it to 3 part and turning them to integer as follows:
splitted=readoff.split()
if len(splitted) == 3 :
temparrayforx.append(int(splitted[0]))
temparrayfory.append(int(splitted[1]))
temparrayforz.append(int(splitted[2]))
but sometimes from the serial port im reading something like: '2-264' which cannot turned into a integer. or sometimes readoff is not divisible to three.
here is my sample error:
temparrayforx.append(int(splitted[0]))
ValueError: invalid literal for int() with base 10: '2-264'
my goal is if the reading is not correct(if its not 3 part)(if its not a proper number), skip that readoff and go on(read another data). how can i do that ?
thanks for help
The standard python try-catch is:
try:
do_something_risky()
except ExceptionName as exc:
do_something_else()
It is very important to specify the exceptions you want to catch, otherwise you might catch unwanted exceptions that should bubble up, resulting in errors difficult to detect.
You can catch different exceptions and react in a different way to them:
try:
do_something_risky()
except SomeException as exc:
do_this()
except AnotherException as exc:
do_that()
Additionally you can add else and finally
try:
do_something_risky()
except ExceptionName, AnotherPossibleException as exc:
do_something_else()
else:
do_something_when_no_exception_raised()
finally:
# Useful for cleaning up
do_something_no_matter_what_happens()
In your case
try:
# Do the problematic thing
except ValueError as exc:
# Manage the exception
You should catch the specific exception that's being raised, ValueError in this case:
try:
temparrayforx.append(int(splitted[0]))
except ValueError as e:
print e
It's important to catch a specific error type so you don't accidentally catch lots of unexpected errors - like if splitted is empty, an IndexError would be raised. A bare 'except:' or 'except Exception:' would hide that from you.
In your case, since you want to catch a couple of different error cases (line doesn't have enough parts, value isn't a number) you can either catch both exception types in the same except clause or have two different except clauses - for example if you need to do different things with each problem.
Related
Is there a functional difference between the exception handling in code blocks 1,2,3? I want to print different messages based on the type error for example including the error code if psycopg2 error. I have read that nested try except blocks are good practice. I'm using psycopg2 as an example.
# code block 1
def my_func(fun_arg):
try:
# ... some stuff
except psycopg2.Error as error:
print(f"Error while inserting data to PostgreSQL {type(error).__name__} {error.pgcode} {error.pgerror}")
except Exception as error:
print(f'error in my_func {type(error).__name__} {error.args}')
# code block 2
def my_func(fun_arg):
try:
# ... some stuff
try:
# ... some stuff
except psycopg2.Error as error:
print(f"Error while inserting data to PostgreSQL {type(error).__name__} {error.pgcode} {error.pgerror}")
except Exception as error:
print(f'error in my_func {type(error).__name__} {error.args}')
# code block 3
def my_func(fun_arg):
try:
# ... some stuff
except (psycopg2.Error, Exception) as error:
if (type(error).__name__ in (
'DatabaseError', 'OperationalError', 'NotSupportedError',
'ProgrammingError', 'DataError','IntegrityError',))
print(f"Error while inserting data to PostgreSQL {type(error).__name__} {error.pgcode} {error.pgerror}")
else:
print(f'error in my_func {type(error).__name__} {error.args}')
In your case, there is no functional difference. In such a case, you may follow the Zen of Python to choose the one that fits best. There are a lot of ways to interpret it but I would choose block number 1 as it is the simplest, the flattest, and the most readable one.
Block number one is the preferred one for the reasons above I'd say.
Block number two is needed when all the branches of the inner try can raise the same exception and the handler of the exception is also the same. E.g.:
try:
try:
store_to_db(value)
except ValueError:
store_to_db(fallback)
except DbError:
log_error()
Block number three is just a more complicated and more difficult-to-read alternative to block number one. I cannot imagine a practical use case for it except that there is a shared code for both exceptions. E.g.:
try:
do_something()
except (DatabaseError, OperationalError, KeyError) as error:
data = collect_some_data()
if type(error).__name__ in ('DatabaseError', 'OperationalError'):
print(f"Error while inserting data to PostgreSQL {data}")
else:
print(f'error in my_func {data}')
Although isinstance is probably preferred over type(error).__name__ ==. And I would still argue that it is better to split it into multiple except clauses and repeat the call to collect_some_data but it is a matter of personal preferences.
Another thing to take into account is that it is generally preferred to "limit the try clause to the absolute minimum amount of code necessary as it avoids masking bugs" [PEP 8]. This is another reason to avoid nested try whenever possible.
I think either of the first two options are fine.
Personally I find I think the first is easier to read for a short simple function although if my_func was larger and more complex with nesting then I would opt for the second option as it makes it clear where exactly where sycopg2.Error may be raised.
The wouldn't use the third option. If you want to catch multiple exceptions use this syntax:
except (RuntimeError, TypeError, NameError):
pass
I have a try block case in my code and I want to ignore one particular exception and all the rest should be raised.
For example:
try:
blah
except <exception> as e:
raise Exception(e)
In this kind of case, I want all the exceptions to be raised except for one case, say if the exception is "query not found" I have to ignore it.
How do I ignore that single exception?
I can use multiple except blocks but how to define a exception?
You can give something like this:
try:
print(x)
except NameError:
print("Variable x is not defined")
except:
print("Something else went wrong")
In this case, you want to catch NameError and specify a message. For all others, you want to specify another message.
Let's say you want to ignore NameError, then you can just give continue or pass.
Alternatively, you can also raise an exception.
Example will be:
x = -1
if x < 0:
raise Exception("Sorry, no numbers below zero")
So you can use a combination of all this to get you what you want.
If you want more details on exception, see the below links:
https://docs.python.org/3/tutorial/errors.html
https://www.w3schools.com/python/python_try_except.asp
https://realpython.com/python-exceptions/
And on stack overflow (as Gino highlighted), see
Handling all but one exception
As an alternative to #Joe Ferndz's answer, in case you don't want the exception to be raised but still want the block to exit, you can use suppress from the contextlib module:
from contextlib import suppress
with suppress(ValueError):
print('hello world')
raise ValueError
print('this will not be printed')
In this case, the block still exits on raise ValueError, but an exception is not raised.
In Python's try, except blocks, why does else need to exist if I can just use an except: without a specifier?
It seems like your understanding of how try, except, else, and finally is off.
Here's a summary of how they all work together, from looking at https://docs.python.org/2/tutorial/errors.html:
try:
#Try something that might raise an exception
except <exception specifier>:
#Code here will only run if the exception that came up was the one specified
except:
#Except clause without specifier will catch all exceptions
else:
#Executed if try clause doesn't raise exception
#You can only have this else here if you also have except blocks
finally:
#Runs no matter what
In what I have written, NoResultException can be raised either in my try block or my except UnexpectedAlertPresentException block. I would like to go to the except NoResultException block in either case, but it only does this if NoResultException is raised in the try block. This is approximately what I have now:
try:
# do things
except UnexpectedAlertPresentException:
# do other things, including possibly raise NoResultException
except NoResultException:
# handle exception
I could change it to something like this:
try:
# do things
except UnexpectedAlertPresentException:
try:
# do other things, including possibly raise NoResultException
except NoResultException:
# handle exception
except NoResultException:
# handle exception
to handle NoResultException, but I'm trying to avoid repeating myself. Is there any better way to do this?
try:
try:
# do things
except UnexpectedAlertPresentException:
# do other things, including possibly raise NoResultException
except NoResultException:
# handle exception
Try not to go overboard with the exception-handling control flow. The logic can get really hard to reason about, and the indentation can get really deep.
I have this kind of code:
try:
return make_success_result()
except FirstException:
handle_first_exception()
return make_error_result()
except SecondException:
handle_second_exception()
return make_error_result()
And I'm wondering is there any way I can achieve this:
try:
# do something
except Error1:
# do Error1 specific handling
except Error2:
# do Error2 specific handling
else:
# do this if there was no exception
????:
# ALSO do this if there was ANY of the listed exceptions (e.g. some common error handling)
So the code is executed in one of following sequences:
try > else > finally
try > except > ???? > finally
EDIT: my point here is that ???? block should execute right after ANY of the except blocks, meaning that it's an addition to error handling, not a substitution.
What I would do in that case is to set a boolean when you get an exception, like so:
got_exception = False
try:
# do something
except Error1:
# do Error1 specific handling
got_exception = True
except Error2:
# do Error2 specific handling
got_exception = True
else:
# If there was no exception
finally:
if got_exception:
# ALSO do this if there was ANY exception (e.g. some common error handling)
This should fit your needs, which is IMO the cleanest way of combining all of the solutions which have been presented into the most readable code structure that's going to be the easiest to debug.
You can actually do this:
try:
print 'try'
# 1/0
# {}[1]
# {}.a
except AttributeError, KeyError: # only handle these exceptions..
try:
raise # re-raise the exception so we can add a finally-clause executing iff there was an exception.
except AttributeError:
print 'attrerr'
# raise ... # any raises here will also execute 'common'
except KeyError:
print 'keyerror'
finally: # update 0: you wanted the common code after the exceptions..
print "common"
else:
print 'no exception'
but it is horrid and I would not suggest that you do without copious amounts of comments describing why..
UPDATE: you don't need to catch anything but the interesting exceptions in the inner try-block. Code updated.
UPDATE2: per OP's clarification, common should just be executed when an interesting exception is thrown. Code updated. #MattTaylor's version is definitely the way to go ;-)
Yes, exception handling in python includes both an else and a finally clause. You can do this:
try:
# do something
except Error1:
# do Error1 specific handling
except Error2:
# do Error2 specific handling
else:
# do this if there was no exception
finally:
# Do this in any case!
The python docs mention these blocks, even though it doesn't show the full example you need.
EDIT:
I see that you do not ask specifically for the clean-up in the general case. Python docs put it this way:
The try statement has another optional clause which is intended to define clean-up actions that must be executed under all circumstances.
Note that the finally will run whether there was an exception or not. Combined with the else block, you should still be able to do what you want.
You could trap all errors and check for its type in the error handling code like this:
try:
# do something
except Exception as e:
if isinstance(e, Error1):
# do Error1 specific handling
elif isinstance(e, Error2):
# do Error2 specific handling
else:
# do non-Error1/Error2 handling
# ALSO do this if there was ANY exception (e.g. some common error handling)
else:
# do this if there was no exception