how to use the post_mortem method of pdb? - python

I am trying to understand how to use the pdb.post_mortem() method.
for this given file
# expdb.py
import pdb
import trace
def hello():
a = 6 * 9
b = 7 ** 2
c = a * b
d = 4 / 0
print(c)
tracer = trace.Trace()
Command prompt
'''
# first Try
λ python -i expdb.py
>>> pdb.post_mortem()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "C:\Program Files\Anaconda3\lib\pdb.py", line 1590, in post_mortem
raise ValueError("A valid traceback must be passed if no "
ValueError: A valid traceback must be passed if no exception is being handled
'''
'''
# Second Try
λ python -i expdb.py
>>> pdb.post_mortem(traceback=tracer.run('hello()') )
--- modulename: trace, funcname: _unsettrace
trace.py(77): sys.settrace(None)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "C:\Program Files\Anaconda3\lib\trace.py", line 500, in run
self.runctx(cmd, dict, dict)
File "C:\Program Files\Anaconda3\lib\trace.py", line 508, in runctx
exec(cmd, globals, locals)
File "<string>", line 1, in <module>
File "expdb.py", line 8, in hello
d = 4 / 0
ZeroDivisionError: division by zero
>>>

The post_mortem method wants a traceback object, not a Trace object. Traceback objects can be acquired from sys.exc_info()[2] inside of an except block, or you can simply call pdb.post_mortem() with no arguments directly (in the except block).
But either way, you must catch the exception before you can debug it.

Related

Python 3/Doctest: Exception is not evaluated as expected result

I have a python module containing (amongst other functions) this piece of code:
def check_color_range(*argv):
"""
Abbreviated documentation and other tests.
>>> check_color_range(23, -1, 99, 10000)
Traceback (most recent call last):
...
TypeError: Falscher Farbwert -1!
"""
for c in argv:
if c < 0 or c > 255:
raise TypeError('Falscher Farbwert ' + str(c) + '!')
When I run this using doctest like so: python -m doctest -v demo.py, I get the following output:
Trying:
check_color_range(23, -1, 99, 10000)
Expecting:
Traceback (most recent call last):
...
TypeError: Falscher Farbwert -1!
**********************************************************************
File "C:\az\code_camp_python\src\EigeneProgramme\Tag3\arcade_base\demo.py", line 5, in demo.check_color_range
Failed example:
check_color_range(23, -1, 99, 10000)
Expected:
Traceback (most recent call last):
...
TypeError: Falscher Farbwert -1!
Got:
Traceback (most recent call last):
File "C:\az\miniconda3\envs\py37\lib\doctest.py", line 1329, in __run
compileflags, 1), test.globs)
File "<doctest demo.check_color_range[0]>", line 1, in <module>
check_color_range(23, -1, 99, 10000)
File "C:\az\code_camp_python\src\EigeneProgramme\Tag3\arcade_base\demo.py", line 12, in check_color_range
raise TypeError('Falscher Farbwert ' + str(c) + '!')
TypeError: Falscher Farbwert -1!
1 items had no tests:
demo
**********************************************************************
1 items had failures:
1 of 1 in demo.check_color_range
1 tests in 2 items.
0 passed and 1 failed.
***Test Failed*** 1 failures.
For me the expected and the actual Errors look the same, but I may be missing something. I already compared whitespace etc., which seems to be the same.
I then tried to paste the complete Traceback from the "Got:" section into the testcase - and I'm still get the failed test, so I guess I must be doing something wrong.
I'd be very happy, if you could give me a heads-up.
On line 8 you have: TypeError: Falscher Farbwert -1!____ (4 blank spaces at the end)
You should replace it with: TypeError: Falscher Farbwert -1!

Python 2.7: Error not caught by exception due to "raise"

Here's my code:
import pandas as pd
df2 = pd.DataFrame()
try:
df_task = df_task.append(df2, ignore_index = True)
except NameError:
df_task = df2
raise
It produces this error:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python2.7/dist-packages/spyderlib/widgets/externalshell/sitecustomize.py", line 540, in runfile
execfile(filename, namespace)
File "/home/cld_intern/.spyder2/.temp.py", line 12, in <module>
df_task = df_task.append(df2, ignore_index = True)
NameError: name 'df_task' is not defined
The except block is supposed to catch the NameError, but somehow the inclusion of "raise" without specifying the exception to raise produces a NameError. Why is it so?
This runs perfectly:
import pandas as pd
df2 = pd.DataFrame()
try:
df_task = df_task.append(df2, ignore_index = True)
except NameError:
df_task = df2
This runs as expected too:
import pandas as pd
df2 = pd.DataFrame()
try:
df_task = df_task.append(df2, ignore_index = True)
except NameError:
df_task = df2
raise Exception("error message")
With the following traceback:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python2.7/dist-packages/spyderlib/widgets/externalshell/sitecustomize.py", line 540, in runfile
execfile(filename, namespace)
File "/home/cld_intern/.spyder2/.temp.py", line 15, in <module>
raise Exception("error message")
Exception: error message
in python 3:
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
NameError: name 'df_task' is not defined
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "<stdin>", line 4, in <module>
NameError: name 'df2' is not defined
in python2.7
Traceback (most recent call last):
File "<stdin>", line 4, in <module>
NameError: name 'df2' is not defined
Are you sure you are using python 2.7?
Like mentioned in the comment, df2 is not defined i guess.

error in function: 'str' object is not an iterator

I have a problem with the following function in python (where swap is a function that I have previously created and that works fine):
def swap (cards):
"""
>>> swap('FBFFFBFFBF')
'BFBBBFBBFB'
>>> swap('BFFBFBFFFBFBBBFBBBBFF')
'FBBFBFBBBFBFFFBFFFFBB'
>>> swap('FFBFBFBFBFBFBFBBFBFBFBFBBFBFBBFBF')
'BBFBFBFBFBFBFBFFBFBFBFBFFBFBFFBFB'
"""
invert=""
for i in cards:
if i is "B":
invert+="F"
else:
invert+="B"
return (invert)
def swap2 (cards):
"""
>>> next('FBFFFBFFBF')
'FFBBBFBBFF'
>>> next('BFFBFBFFFBFBBBFBBBBFF')
'FBBFBFBBBFBFFFBFFFFFF'
>>> next('FFBFBFBFBFBFBFBBFBFBFBFBBFBFBBFBF')
'FFFBFBFBFBFBFBFFBFBFBFBFFBFBFFBFF'
"""
indices=""
for pos, i in enumerate(cards):
if i =="B":
indices+=str(pos)
first= int(indices[0])
last= int(indices[-1])
prefix= cards [:first]
middle= cards [first:last+1]
suffix= cards [last+1:]
middle2=swap(middle)
return (prefix+middle2+suffix)
def turns (cards):
"""
>>> turns('FBFFFBFFBF')
3
>>> turns('BFFBFBFFFBFBBBFBBBBFF')
6
>>> turns('FFBFBFBFBFBFBFBBFBFBFBFBBFBFBBFBF')
14
"""
turn=0
while cards != 'F'*len(cards):
cards=swap2(cards)
turn+=1
return (turn)
if __name__ == '__main__':
import doctest
doctest.testmod()
when I run this function it works fine but if I use doctest to see if there are mistakes it tells me:
TypeError: 'str' object is not an iterator
I don't know where this error comes from.
Can anyone help me?
complete output of the doctest:
File "C:\Users\manuel\Documents\Gent MaStat\programming and algorithms\workspace_python\homeworks\Week 5\looking_up.py", line 25, in __main__.swap2
Failed example:
next('FBFFFBFFBF')
Exception raised:
Traceback (most recent call last):
File "C:\Users\manuel\Anaconda3\lib\doctest.py", line 1321, in __run
compileflags, 1), test.globs)
File "<doctest __main__.swap2[0]>", line 1, in <module>
next('FBFFFBFFBF')
TypeError: 'str' object is not an iterator
**********************************************************************
File "C:\Users\manuel\Documents\Gent MaStat\programming and algorithms\workspace_python\homeworks\Week 5\looking_up.py", line 27, in __main__.swap2
Failed example:
next('BFFBFBFFFBFBBBFBBBBFF')
Exception raised:
Traceback (most recent call last):
File "C:\Users\manuel\Anaconda3\lib\doctest.py", line 1321, in __run
compileflags, 1), test.globs)
File "<doctest __main__.swap2[1]>", line 1, in <module>
next('BFFBFBFFFBFBBBFBBBBFF')
TypeError: 'str' object is not an iterator
**********************************************************************
File "C:\Users\manuel\Documents\Gent MaStat\programming and algorithms\workspace_python\homeworks\Week 5\looking_up.py", line 29, in __main__.swap2
Failed example:
next('FFBFBFBFBFBFBFBBFBFBFBFBBFBFBBFBF')
Exception raised:
Traceback (most recent call last):
File "C:\Users\manuel\Anaconda3\lib\doctest.py", line 1321, in __run
compileflags, 1), test.globs)
File "<doctest __main__.swap2[2]>", line 1, in <module>
next('FFBFBFBFBFBFBFBBFBFBFBFBBFBFBBFBF')
TypeError: 'str' object is not an iterator
def swap2 (cards):
"""
>>> next('FBFFFBFFBF')
'FFBBBFBBFF'
>>> next('BFFBFBFFFBFBBBFBBBBFF')
'FBBFBFBBBFBFFFBFFFFFF'
>>> next('FFBFBFBFBFBFBFBBFBFBFBFBBFBFBBFBF')
'FFFBFBFBFBFBFBFFBFBFBFBFFBFBFFBFF'
"""
# …
The function is called swap2 but within the doctests, you are using next which happens to be a built-in function that does something completely different. That’s why you are seeing that error.
At times like this, it’s really important to actually look at the error messages. It clearly told you what was called:
File "<doctest __main__.swap2[0]>", line 1, in <module>
next('FBFFFBFFBF')
So if you don’t know where that was supposed to come from, then check out the error message. Doctest will tell you what it is executing: swap2[0], swap2[1], etc. tells you the function name the docstring that is being executed is by doctest and which test case it is (0 is the first, 1 the second etc.). It even gives you the line number (within the doctest case) where the error appeared, and of course the line that was causing the error. So use that information to go to the problematic code, and figure out what the problem is.

How to print the first line from a traceback stack

Suppose I am given the following traceback:
Traceback (most recent call last):
File "<wingdb_compile>", line 3, in <module>
File "C:\Python34\lib\ftplib.py", line 419, in login
resp = self.sendcmd('PASS ' + passwd)
File "C:\Python34\lib\ftplib.py", line 272, in sendcmd
return self.getresp()
File "C:\Python34\lib\ftplib.py", line 245, in getresp
raise error_perm(resp)
ftplib.error_perm: 530 Login incorrect.
I have managed to extract the Error details but what has stumped me is how would I extract the line:
File "<wingdb_compile>", line 3, in <module>
I was looking at methods in the trace back package but wondered if any one had experience with that here
The function traceback.format_exc is built primarily for this
This is like print_exc(limit) but returns a string instead of printing to a file.
>>> import traceback
>>> try:
... x = 2/0
... except:
... error = traceback.format_exc()
...
>>> error
'Traceback (most recent call last):\n File "<stdin>", line 2, in <module>\nZeroDivisionError: division by zero\n'
>>> linesoferror = error.split('\n')
>>> linesoferror
['Traceback (most recent call last):', ' File "<stdin>", line 2, in <module>', 'ZeroDivisionError: division by zero', '']
So now you wanted the first line then you can simply use
>>> linesoferror[1]
' File "<stdin>", line 2, in <module>'
Voila! You have what you want
ALERT - Valid for Python 2.4.1 and above

How to get a complete exception stack trace in Python

The following snippet:
import traceback
def a():
b()
def b():
try:
c()
except:
traceback.print_exc()
def c():
assert False
a()
Produces this output:
Traceback (most recent call last):
File "test.py", line 8, in b
c()
File "test.py", line 13, in c
assert False
AssertionError
What should I use if I want the complete stack trace including the call to a?
If it matters I have Python 2.6.6
edit: What I'd like to get is the same information I'd get if I left the try except out and let the exception propagate to the top level. This snippet for example:
def a():
b()
def b():
c()
def c():
assert False
a()
Produces this output:
Traceback (most recent call last):
File "test.py", line 10, in <module>
a()
File "test.py", line 2, in a
b()
File "test.py", line 5, in b
c()
File "test.py", line 8, in c
assert False
AssertionError
Here's a function based on this answer. It will also work when no exception is present:
def full_stack():
import traceback, sys
exc = sys.exc_info()[0]
stack = traceback.extract_stack()[:-1] # last one would be full_stack()
if exc is not None: # i.e. an exception is present
del stack[-1] # remove call of full_stack, the printed exception
# will contain the caught exception caller instead
trc = 'Traceback (most recent call last):\n'
stackstr = trc + ''.join(traceback.format_list(stack))
if exc is not None:
stackstr += ' ' + traceback.format_exc().lstrip(trc)
return stackstr
print full_stack() will print the full stack trace up to the top, including e.g. IPython's interactiveshell.py calls, since there is (to my knowledge) no way of knowing who would catch exceptions. It's probably not worth figuring out anyway...
If print full_stack() is called from within an except block, full_stack will include the stack trace down to the raise. In the standard Python interpreter, this will be identical to the message you receive when not catching the exception (Which is why that del stack[-1] is there, you don't care about the except block but about the try block).
I don't know if there is a better way, but here's what I did:
import traceback
import sys
def format_exception(e):
exception_list = traceback.format_stack()
exception_list = exception_list[:-2]
exception_list.extend(traceback.format_tb(sys.exc_info()[2]))
exception_list.extend(traceback.format_exception_only(sys.exc_info()[0], sys.exc_info()[1]))
exception_str = "Traceback (most recent call last):\n"
exception_str += "".join(exception_list)
# Removing the last \n
exception_str = exception_str[:-1]
return exception_str
def main1():
main2()
def main2():
try:
main3()
except Exception as e:
print "Printing only the traceback above the current stack frame"
print "".join(traceback.format_exception(sys.exc_info()[0], sys.exc_info()[1], sys.exc_info()[2]))
print
print "Printing the full traceback as if we had not caught it here..."
print format_exception(e)
def main3():
raise Exception()
if __name__ == '__main__':
main1()
And here's the output I get:
Printing only the traceback above the current stack frame
Traceback (most recent call last):
File "exc.py", line 22, in main2
main3()
File "exc.py", line 31, in main3
raise Exception()
Exception
Printing the full traceback as if we had not caught it here...
Traceback (most recent call last):
File "exc.py", line 34, in <module>
main1()
File "exc.py", line 18, in main1
main2()
File "exc.py", line 22, in main2
main3()
File "exc.py", line 31, in main3
raise Exception()
Exception
Use
traceback.print_stack()
http://docs.python.org/library/traceback.html#traceback.print_stack
suxmac2 $ python out.py
File "out.py", line 16, in <module>
a()
File "out.py", line 5, in a
b()
File "out.py", line 11, in b
traceback.print_stack()
Here is a bit better variant of Tobias Kienzler answer. It works same, but can be called not right in except block, but somewhere deeper.
In other words, this variant will print same stacks, when called like
try:
...
except Exception:
print full_stack()
or
def print_full_stack():
print full_stack()
try:
...
except Exception:
print_full_stack()
Here is code:
def full_stack():
import traceback, sys
exc = sys.exc_info()[0]
if exc is not None:
f = sys.exc_info()[-1].tb_frame.f_back
stack = traceback.extract_stack(f)
else:
stack = traceback.extract_stack()[:-1] # last one would be full_stack()
trc = 'Traceback (most recent call last):\n'
stackstr = trc + ''.join(traceback.format_list(stack))
if exc is not None:
stackstr += ' ' + traceback.format_exc().lstrip(trc)
return stackstr

Categories

Resources