How to continue loop after catching exception - python

The below code produces exception while handling non int values but it doesn't continue the loop but rather comes out from the loop raising error. My intention is to provide the value of 0 for exception cases.
Sample Input:
Common Ruby Errors 45min
Rails for Python Developers lightning
Code:
class TimeNotProvidedError(Exception):
pass
def extract_input():
lines = []
__tracks = {}
try:
lines = [line.strip() for line in open('test.txt')]
except FileNotFoundError as e:
print("File Not Found", e)
for line in lines:
title, minutes = line.rsplit(maxsplit=1)
minutes = int(minutes[:-3])
try:
__tracks[title] = minutes
except TimeNotProvidedError:
__tracks[title] = 0
return __tracks
print(extract_input())
Traceback:
ValueError: invalid literal for int() with base 10: 'lightn'

You're getting the error when converting to int with this line: minutes = int(minutes[:-3]). That line isn't in the try block, so the exception isn't caught. Move that line inside the try block, and you'll get the behavior you wanted.
Furthermore, the exception you're catching is TimeNotProvidedError, which isn't what int throws when a conversion fails. Instead, it throws ValueError, so that's the exception type you need to catch.
The mere act of assigning to __tracks[title] is unlikely to cause an exception, and if it does, re-trying with another assignment probably won't work anyway. What you probably want in your loop is this:
title, minutes = line.rsplit(maxsplit=1)
try:
minutes = int(minutes[:-3])
except ValueError:
minutes = 0
__tracks[title] = minutes

Related

retry a function with backoff with different argument and timeout

I am trying to implement a retry ability whenever a function fails with an index error. I started with this:
I know the reason for failure is passing high value to curr_val, but setting high values will generate better output
#these lines are inside another for loop
curr_val=40
while True:
try:
ret1, ret2 = extract(arg1,arg2,val=curr_val)
except IndexError:
curr_val -=5
continue
break
##process ret1
According to this answer, it is possible to use the decorator (like tenacity) to handle such cases, supporting any kind of exception.
my current try with tenacity is as follows:
curr_val = 5
#tenacity.retry(wait=tenacity.wait_fixed(1))
def try_to_extract():
try:
return extract(arg1,arg2,val=curr_val)
except Exception:
curr_val -=1
raise
However, it does not have access to the outside variables and keeps raising exception, without changing curr_val
Can anyone let me know how to handle this? meaning using curr_val inside retry and handle this case. (retrying with another argument(decremented curr_val), in case of failure or timeout)
the iterator can help this.
#tenacity.retry
def try_to_extract(value_iter):
curr_val = next(value_iter)
print(curr_val)
try:
return extract(arg1,arg2,val=curr_val)
except Exception:
raise
curr_val = 40
try_to_extract(itertools.count(curr_val, -1))

Python Exceptions difficulty

I am trying to complete a lab soon but I am having difficulty, the prompt is:
A pedometer treats walking 2,000 steps as walking 1 mile. Write a steps_to_miles() function that takes the number of steps as a parameter and returns the miles walked. The steps_to_miles() function throws a ValueError object with the message "Exception: Negative step count entered." when the number of steps is negative. Complete the main() program that reads the number of steps from a user, calls the steps_to_miles() function, and outputs the returned value from the steps_to_miles() function. Use a try-except block to catch any ValueError object thrown by the steps_to_miles() function and output the exception message.
Output each floating-point value with two digits after the decimal point, which can be achieved as follows:
print('{:.2f}'.format(your_value))
I have been working on it for awhile now, my code is:
def steps_to_miles():
steps = int(input())
if steps < 0:
raise ValueError
return steps
if __name__ == '__main__':
try:
steps = steps_to_miles()
miles_walked = float(steps / 2000)
print('{:.2f}'.format(miles_walked))
except ValueError:
print('Exception: Negative step count entered.')
(Sorry for formatting errors...) The code runs but is only giving me 4 out of the 10 points due to Zybooks stating "test_passed function missing" and "Test stepsToMiles(-3850), should throw an exception". What am I missing or how can fix it? Or alternatively is there another way to write the code?
def steps_to_miles(steps):
if steps < 0:
raise ValueError
return float(steps / 2000)
if __name__ == '__main__':
steps = int(input())
try:
miles_walked = steps_to_miles(steps)
except ValueError:
print('Exception: Negative step count entered.')
print('{:.2f}'.format(miles_walked))
in body of try, need use only 'danger' code
your function was unworked becourse: you dont send any parameter, and it dont return value
input moved into main . It was next error: steps was local variable, which dont used in global namespace, and in function main
We can't do a lot to help you with an automatic homework grader, you should probably ask your teacher or TA. Here are a few pointers:
Your steps_to_miles does not take any arguments, according to the assignment it should take a single integer argument.
The ValueError you throw does not have a message attached to it.
steps_to_miles should divide its argument by 2000 but it doesn't do so. Instead you divide by 2000 outside of the function.
You print a specific string in your except block instead of printing the exception's actual message.
You may need to make your error message a variable, in regards to your zyBooks giving you this error: "Test stepsToMiles(-3850).
I would try this in your function: raise ValueError('Exception: Negative step count entered.')
I would also write in this in your final "except" statement.
except ValueError as err:
print(err)
this should work:
def steps_to_miles(num_steps):
if num_steps < 0:
raise ValueError("Exception: Negative step count entered.")
return num_steps / 2000
if __name__ == '__main__':
num_steps = int(input())
try:
num_miles = steps_to_miles(num_steps)
print('{:.2f}'.format(num_miles))
except ValueError as e:
print(e)

How can I get "EOFEroor" in Python while taking multiple inputs from users?

I'm trying to get multiple inputs from users and break the loop by End of File(EOF) error.
while True:
try:
n, l, c = map(int,input().split())
except EOFError:
break
But when the user gives multiple inputs and then press Enter the ValuEroor warning has come.
ValueError: not enough values to unpack (expected 3, got 0)
In this scenario, Is there any way to get EOFEroor to break the loop and avoid ValueEoor?
You will only get EOFError if the user presses CTRL-D. Just add ValueError to the caught exceptions:
except (EOFError, ValueError):
or, if needed to be handled differently:
except EOFError:
...
except ValueError:
...
You will need it anyway in case the user enters a string that can't be converted to int.

Can't catch ValueError in Python

I am starting to learn Python, and I wrote a very simple code to practice try/except.
Here is the code:
a = float(input('num1: '))
b = float(input('num2: '))
try:
result = a / b
except ValueError as e:
print ('error type: ', type (e))
print(result)
Whenever I enter a letter as a number, the print in except is working, but the code crashes.
ZeroDivisionError & TypeError are working, but ValueError is not.
I even put inputs in separate try/except and it is still not working.
How can I handle this error here, and in the real app?
The crash is occurring before you enter the try block. It does not print the error in the except block if you enter a letter with your current code.
Simply putting the input section in a separate try block wouldn't catch it - you need an except block related to the try within which the error is happening, e.g.
try:
a = float(input('num1: '))
b = float(input('num2: '))
except ValueError as e:
print ('Value Error')
try:
result = a / b
except ZeroDivisionError as e:
print ('Zero DivisionError')
print(result)
Alternatively, you could put the input and division all within the try block and catch with your current reporting:
try:
a = float(input('num1: '))
b = float(input('num2: '))
result = a / b
except ValueError as e:
print ('error type: ', type (e))
print(result)
EDIT: Note that if any error does occur in either of these, it will cause further errors later on. You're better off going with the second option, but moving the print(result) into the try block. That's the only time it will be defined.

Is it possible for too many nested try/except to cause stack overflow?

I have a mixed dataset which I am attempting to handle all cases by using try/except blocks. Essentially I try the first case, if that fails then I try the next case in the except block, and so on.
It was working OK until I got to 10 levels of except. Is this a thing in Python.
I cannot find a definitive answer to this question. I suspect I am writing really bad code.
I give actual code in the first try block only:
try:
logf.write(f'Processing Type 8...\n')
with open(filename, 'r') as las_file:
l = las_file.readlines()
# drop the header lines and start reading the file from the header row (indicated by ~A)
lasdata = [x.replace('\n', '').split() for x in list(
dropwhile(lambda x: '~A' not in x, l))]
# delete ~A from the header row
del lasdata[0][0]
las_df = pd.DataFrame(lasdata)
# now set column names as header
new_header = [
'DEPTH',
'GR',
'CALI',
'BRD',
'LSD',
'SSD',
]
las_df = las_df[1:]
las_df.columns = new_header
# add hole id as column
las_df['BHID'] = hole
las_df['filename'] = filename
# make a copy and drop unwanted columns
las_df = las_df[[
'filename',
'BHID',
'DEPTH',
'LSD',
'SSD',
'GR',
'CALI']].copy()
# append each hole in loop
type8_df = type8_df.append(las_df)
# write success to log file
logf.write(f'Type 8: Hole {hole} Processed OK\n')
# output to CSV file without the pandas index column
type8_df.to_csv(path_or_buf='.\\type_8.csv', index=False)
except KeyError as e:
try:
do_something()
except KeyError as e:
try:
do_something()
except KeyError as e:
try:
do_something()
except KeyError as e:
try:
do_something()
except Exception as e:
logfile.write(e)
and so on - ten levels deep
This is the error message:
Fatal Python error: XXX block stack overflow
Current thread 0x000027a8 (most recent call first):
File "e:/python/geology/las_data/las_converter.py", line 398 in las_converter
File "e:/python/geology/las_data/las_converter.py", line 471 in
I have more than ten KeyError cases to handle. how do I do this?
UPDATE
I have refactored this where now I generate a list of all of the header/column name cases I have to deal with - when processing some directories of files I get up to 50 cases so my try/except approach was never going to work. I then process each file using an if statement to match by type then process.
Thanks all I learned a lot.
The following applies to CPython. This limit may not be present in other implementations.
The error is "Fatal Python error: XXX block stack overflow", not "RuntimeError: maximum recursion depth exceeded". The latter would be a stackoverflow. This error occurs when the block stack already has its limit of blocks and you add one more.
for/while/try/except/finally/with blocks can only be nested to a limited depth in a function. The depth limit is 20.
It should be possible to rewrite the code so that it well below this limit. One way is to break out the inner part of the code into its own function which would have its own limit.
The error message you posted has a stack trace that indicates what line of your code caused the error:
File "e:/python/geology/las_data/las_converter.py", line 398 in las_converter
File "e:/python/geology/las_data/las_converter.py", line 471 in
Have a look at these lines; they are probably assuming a key is present when it sometimes isn't.
Instead of assuming, you can check first and prevent the KeyError entirely:
if key1 in my_dictionary:
do_something()
elif key2 in my_dictionary:
do_something()
elif key3 in my_dictionary:
do_something()
and so on.
You could even use a loop:
for key in [key1, key2, key3, key4, key5]:
if key in my_dictionary:
do_something()

Categories

Resources