Print lines after raising exception - python

Is there a way to print out the contents of a dictionary after raising an exception?
Assuming that the dictionary is this,
d = {"orange":[1,2], "yellow":[5], "red":[2,6,7]}
I would like it to look something like this:
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-63-719ba08e2a6c> in <module>
----> 1 raise TypeError("This is a TypeError. Printing out contents of dictionary...")
TypeError: This is a TypeError.
orange
1
2
yellow
5
red
2
6
7
Is this possible?

Append the dictionary to the exception message.
raise TypeError("This is a TypeError. Printing out contents of dictionary...\n" + str(d))

The format is not right, but this does the trick.
d = {"orange":[1,2], "yellow":[5], "red":[2,6,7]}
try:
d["melon"]
except:
raise Exception(f"{str(d)}")
or you can do:
try:
d["melon"]
except:
for k in d.keys():
print(k, d[k])

try:
# code here
except Exception as e:
# Try and replace `Exception` with the error you're getting
print(f"Error = {e}")
for name, val in zip(d.keys(), d.values()):
print(name)
for i in val:
print(i)
Just be mindful that with except Exception:, the try loop will except any error

Related

Handle KeyError exception and get dictionary name which caused the trouble

KeyError exception object contains args attribute. This is a list and it contains a key name which user tries to access within a dictionary.
Is it possible to figure out dictionary name which does not contain that key and which caused an exception while trying to access the key within it?
Example
data = {"my_key": "my_value"}
try:
data["unknown_key"] except KeyError as e:
print("key name: ", e.args[0])
print("dictionary name: ", e.???) # Here I would need to know the the name of a variable which stores the dictionary is "data"
You can kinda hack this with Python 3.11+, since the traceback contains fine-grained information about where the error happened.
import ast
import linecache
import traceback
data = {"my_key": "my_value"}
flurk = data
try:
data["flep"] = data["my_key"] + flurk["unknown_key"]
except KeyError as e:
# Find the last frame where the exception occurred, formatted as a FrameSummary
err_frame = traceback.TracebackException.from_exception(e).stack[-1]
if err_frame.lineno == getattr(err_frame, "end_lineno", -1): # If we can reliably find the line,
# ... read the line,
line = linecache.getline(err_frame.filename, err_frame.lineno)
# find the "marked segment" in it,
fragment = line[err_frame.colno:err_frame.end_colno]
# ... and parse it as an expression.
expr: ast.Expression = ast.parse(fragment, mode='eval')
# Check we're dealing with a subscript (index) node...
assert isinstance(expr.body, ast.Subscript)
# ... and extract the main parts of the expression.
subscriptee = ast.unparse(expr.body.value)
subscript = ast.unparse(expr.body.slice)
else:
subscriptee = None # No idea
subscript = e.args[0] # Just use the exception message
raise RuntimeError(f"KeyError with {subscriptee=!r}, {subscript=!r}") from e
prints out
Traceback (most recent call last):
File "scratch_679.py", line 8, in <module>
data["flep"] = data["my_key"] + flurk["unknown_key"]
~~~~~^^^^^^^^^^^^^^^
KeyError: 'unknown_key'
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "scratch_679.py", line 27, in <module>
raise RuntimeError(f"KeyError with {subscriptee=!r}, {subscript=!r}") from e
RuntimeError: KeyError with subscriptee='flurk', subscript="'unknown_key'"
so you can see the subscriptee name is flurk.

How to properly handle multiple Runtime errors?

Program description:
Program accepts a file name and a segment, consisting of two numbers (each divided by one space). Then it outputs all lines from existing file where their indicies lie within the given segment.
My solution:
import sys
try:
par = input("Input (<file> <low border of the segment> <high border of the segment>): ").split(' ')
print(17 * '-')
f = par[0]
f_lines = [line.strip("\n") for line in f if line != "\n"]
length = len(f_lines)
if (par == ''):
raise RuntimeError('Error: undefined')
if (par[2] == None) or (par[2] == ''):
raise RuntimeError('Error: segment is limited')
if ((par[1] and par[2]) == None) or ((par[1] and par[2]) == ''):
raise RuntimeError('Error: segment undefined')
if (int(par[2]) >= length):
raise RuntimeError('Error: segment can not be greater than length the amount of lines')
if (par[1] == ''):
a = 0
if (par[2] == ''):
b = 0
segment = [int(par[1]), (int(par[2]) + 1)]
with open(par[0]) as f:
data = f.read().splitlines()
for k in range(segment[0], segment[1]):
print(data[k])
except (FileNotFoundError, IOError, NameError):
print('[!] Error: your input is incorrect. The file may be missing or something else. \n[?] For further information see full error logs: \n',sys.exc_info())
except RuntimeError as e:
print(e)
Problem:
When I try running my program in different ways to test each of my Runtime errors I always get this message:
Traceback (most recent call last):
File "C:\Users\1\Desktop\IT\pycharm\sem_2.py", line 10, in <module>
if (par[2] == None) or (par[2] == ''):
IndexError: list index out of range
I cannot wrap my head around how can I properly handle multiple Runtime errors so they would display as a text message. I haven't found any solution to my question anywhere online, so I'm trying to ask here.
I will appreciate any help, thanks in advance.
Your code would catch FileNotFoundError, IOError, NameError and RuntimeError but what is actually thrown is IndexError and that is not handled.
You may want to add IndexError it to the first except block:
except (FileNotFoundError, IOError, NameError, IndexError):
print('[!] Error: input incorrect!') # ^^^^^^^^^^^^
or perhaps add another except block if you want a custom message for IndexError:
except (FileNotFoundError, IOError, NameError):
print('[!] Error: input incorrect!')
except IndexError:
print('[!] Error: IndexError just happened!')
By the way, the following will always be False because the code in parentheses will resolve to a bool first, which can either be True or False and these are obviously never equal to '' or None:
((par[1] and par[2]) == None) or ((par[1] and par[2]) == '')
You may way want to rewrite it to:
(par[1] is None and par[2] is None) or (par[1] == '' and par[2] == '')

Try function not running correctly

try:
left_break = signs_pos[dave - 1]
except IndexError:
left_error = True
try:
right_break = signs_pos[dave + 1]
except IndexError:
right_error = True
if left_error == True:
current_cal = user_input[:right_break]
elif right_error == True:
current_cal = user_input[left_break:]
else:
current_cal = user_input[left_break:right_break]
I've only started looking at try functions and I need some help with this. What I would like to happen is that if when it tries to find left_break and it gives an error it will set left_error to be true. But if it does not give an error left_break will be set properly.
When the code runs and either right or left does not give an error it does not set left_break or right_break properly.
Traceback (most recent call last):
File "C:\Users\Max\Desktop\MaxsCal.py", line 170, in <module>
current_cal = user_input[:right_break]
NameError: name 'right_break' is not defined
This is the error I get without the try function.
Traceback (most recent call last):
File "C:\Users\Max\Desktop\MaxsCal.py", line 157, in <module>
right_break = signs_pos[dave + 1]
IndexError: list index out of range
Both right_error and left_error will not be true.
The reason why this is happening, is that because you are trying to assign something to a variable inside a try/except, it will not actually exist if you raised an exception.
Here is a simple example to clarify this:
try:
x = 6 / 0
except ZeroDivisionError:
print('this failed')
print(x)
>>> print(x)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'x' is not defined
Now, to remedy this and you are looking to actually use the variable even if it fails in the try/except, you want to declare it before you are calling the thing that might fail.
x = 0
try:
x = 6 / 0
except ZeroDivisionError:
print('this failed')
print(x)
>>> print(x)
>>> 0
Or even inside your try works, but before what you are calling:
try:
x = 0
x = 6 / 0
except ZeroDivisionError:
print('this failed')
print(x)
>>> print(x)
>>> 0
As mentioned to me in the comments, you could also set a default in your except:
try:
x = 6 / 0
except ZeroDivisionError:
print('this failed')
x = 0
print(x)
>>> print(x)
>>> 0
left_break and right_break are only available within the scope of the try block. You can either define them before the try/except block or add an else block to the exception, as discussed in this thread.
Your error is coming from the fact that the variable is out of scope. Right break is only in scope within the try block, change it to
right_break = None
try:
right_break = signs_pos[dave + 1]
except IndexError:
right_error = True

Save KeyErrors and IndexErrors to a list/dict

I'm trying to extract data from an API, and I expect to receive KeyError and IndexError, so I use the try/except function to catch them. I first create a list of items that I'll loop through to extract information from the API responses. Then I create a dataframe that stores information about items that had no errors.
l= ["a","b","c","d"]
def extract_info_from_one_response(response, idx):
try:
response = response.json()
d = {
### some codes ##
}
## ERROR MANAGEMENT
except KeyError,e:
print idx, l[idx], str(e)
return {}
except IndexError,e:
print idx, l[idx], str(e)
return {}
dat = pd.DataFrame([extract_info_from_one_response(response, idx) for idx, response in enumerate(responses)], index=l)
When errors occur, Python prints out [1]the index of the problematic item, [2] the name of the item and [3]the details on the error that took place. How do I save/capture these three outputs, save them into objects or create a dataframe with these 3 pieces of information?
Are you asking how to trace the error?
If so,the traceback module would help like this:
In [1]: import traceback
In [2]: try:
...: a = []
...: a[2] = 1
...: except Exception:
...: y = traceback.format_exc()
...:
In [4]: print y
Traceback (most recent call last):
File "<ipython-input-2-ac34fe2721d3>", line 3, in <module>
a[2] = 1
IndexError: list assignment index out of range
I am not sure what you are asking, but if you want to save what is printed:
key_err = []
idx_err = []
def extract_info_from_one_response(response, idx):
try:
# your code here
except KeyError, e:
key_err.append((idx, l[idx], '{}'.format(e),))
return {}
except IndexError, e:
idx_err.append((idx, l[idx], '{}'.format(e),))
return {}
# your normal code here
# you need to return something here
dat = pd.DataFrame([extract_info_from_one_response(response, idx) for idx, response in enumerate(responses)], index=l)
print(key_err)
print(idx_err)

Python not catching exception

For some reason my code is not catching an exception when I throw it. I have
def trim_rad(rad):
...
if not modrad.shape[0]:
raise IndexError("Couldn't find main chunk")
return modrad, thetas
Then later I call that function:
try:
modrad, thetas = trim_rad(rad)
except IndexError("Couldn't find main chunk"):
return 0
Yet I still get a traceback with that exception. What am I doing wrong?
Catch just the IndexError.
try:
raise IndexError('abc')
except IndexError('abc'):
print 'a'
Traceback (most recent call last):
File "<pyshell#22>", line 2, in <module>
raise IndexError('abc')
IndexError: abc
try:
raise IndexError('abc')
except IndexError:
print 'a'
a # Output
So, reduce your code to
try:
modrad, thetas = trim_rad(rad)
except IndexError:
return 0
If you want to catch the error message too, use the following syntax:
try:
raise IndexError('abc')
except IndexError as err:
print err
abc
You gave except an instance of an IndexError. Do this instead:
try:
modrad, thetas = trim_rad(rad)
except IndexError:
print "Couldn't find main chunk"
return 0
Here is an example:
>>> try:
... [1][1]
... except IndexError('no'):
... pass
...
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
IndexError: list index out of range
>>> try:
... [1][1]
... except IndexError:
... pass
...
>>>
change
except IndexError("Couldn't find main chunk"):
to
except IndexError:
You seem to be catching the exception wrong. You catch exceptions of type, the notation below will assign the exception to e so you can read the description in your except handler.
try:
modrad, thetas = trim_rad(rad)
except IndexError as e:
print e.message
return 0

Categories

Resources