Nan Xiao
Nan Xiao

Reputation: 17477

Is there any method of getting detailed object information when using pdb to debug python script?

I am using pdb to debug a simple python script:

#!/usr/bin/python

f = open("./hello.scala")
f.close()

The debug flow like this:

[root@localhost ~]# python -m pdb test.py
> /root/test.py(3)<module>()
-> f = open("./hello.scala")
(Pdb) n
> /root/test.py(4)<module>()
-> f.close()
(Pdb) p f
<open file './hello.scala', mode 'r' at 0x7f4d69aae8a0>
(Pdb) pp f
<open file './hello.scala', mode 'r' at 0x7f4d69aae8a0>

I want to check the detailed information of File object f, but I can only get the address of it. Is there any method of getting detailed object information when using pdb to debug python script?

Upvotes: 2

Views: 3343

Answers (2)

shx2
shx2

Reputation: 64338

The easiest way I know to achieve this is by defining an alias in a .pdbrc file.

Here's Ned's famous .pdbrc file.

In it you can find the pi alias (short for "print instance"), which does pretty much what you're looking for.

There are other useful aliases there as well.

Very useful, highly recommended.

Upvotes: 2

abarnert
abarnert

Reputation: 365975

You can use most arbitrary Python expressions in pdb.

I don't know what "detailed object information" you're looking for, but in general, anything useful will be an attribute.

Since you know what type you've got (a file), and it's a builtin or stdlib type that comes with Python, you can look it up in the docs and see what attributes it's guaranteed to have. For example, file objects have a closed attribute; to see that:

(Pdb) p f.closed
True

If you don't know what attributes you want, you can use the inspect module to help. For example:

(Pdb) import inspect
(Pdb) p inspect.getmembers(f, lambda x: not callable(x))
[('__doc__', "file(name[, mode[, buffering]]) -> file object\n\nOpen a file.  The mode can be 'r', 'w' or 'a' for reading (default),\nwriting or appending.  The file will be created if it doesn't exist\nwhen opened for writing or appending; it will be truncated when\nopened for writing.  Add a 'b' to the mode for binary files.\nAdd a '+' to the mode to allow simultaneous reading and writing.\nIf the buffering argument is given, 0 means unbuffered, 1 means line\nbuffered, and larger numbers specify the buffer size.  The preferred way\nto open a file is with the builtin open() function.\nAdd a 'U' to mode to open the file for input with universal newline\nsupport.  Any line ending in the input file will be seen as a '\\n'\nin Python.  Also, a file so opened gains the attribute 'newlines';\nthe value for this attribute is one of None (no newline read yet),\n'\\r', '\\n', '\\r\\n' or a tuple containing all the newline types seen.\n\n'U' cannot be combined with 'w' or '+' mode.\n"), ('closed', True), ('encoding', None), ('errors', None), ('mode', 'r'), ('name', 'temp.xml'), ('newlines', None), ('softspace', 0)]

If you want it pretty-printed, just use the pp command instead of p:

(Pdb) pp inspect.getmembers(f, lambda x: not callable(x))
[('__doc__',
  "file(name[, mode[, buffering]]) -> file object\n\nOpen a file.  The mode can be 'r', 'w' or 'a' for reading (default),\nwriting or appending.  The file will be created if it doesn't exist\nwhen opened for writing or appending; it will be truncated when\nopened for writing.  Add a 'b' to the mode for binary files.\nAdd a '+' to the mode to allow simultaneous reading and writing.\nIf the buffering argument is given, 0 means unbuffered, 1 means line\nbuffered, and larger numbers specify the buffer size.  The preferred way\nto open a file is with the builtin open() function.\nAdd a 'U' to mode to open the file for input with universal newline\nsupport.  Any line ending in the input file will be seen as a '\\n'\nin Python.  Also, a file so opened gains the attribute 'newlines';\nthe value for this attribute is one of None (no newline read yet),\n'\\r', '\\n', '\\r\\n' or a tuple containing all the newline types seen.\n\n'U' cannot be combined with 'w' or '+' mode.\n"),
 ('closed', True),
 ('encoding', None),
 ('errors', None),
 ('mode', 'r'),
 ('name', 'temp.xml'),
 ('newlines', None),
 ('softspace', 0)]

As the docs explain up near the top:

The getmembers() function retrieves the members of an object such as a class or module. The sixteen functions whose names begin with “is” are mainly provided as convenient choices for the second argument to getmembers().

But you don't have to use those 16 functions, you can pass anything you want. As the getmembers docs say:

Return all the members of an object in a list of (name, value) pairs sorted by name. If the optional predicate argument is supplied, only members for which the predicate returns a true value are included.

So, as an example, I wrote a custom function, lambda x: not callable(x), which is true only for members that aren't callable. That means I won't get things like the close method, just things like the closed attribute.

If you don't understand lambda, it's a way to define simple functions in the middle of an expression. It's the same as if I'd written:

def my_function(x):
    return not callable(x)

… and then called inspect.getmembers(f, my_function).


While we're at it, you may want to take a look at IPython, a replacement for the default Python interactive mode. Among other things, it gives you tab completion within Pdb (and within normal interactive sessions):

ipdb> n
--Return--
None
> /Users/abarnert/src/pt.py(2)<module>()
1     1 f = open('temp.txt')
----> 2 f.close()

ipdb> p f
<_io.TextIOWrapper name='temp.xml' mode='r' encoding='UTF-8'>
ipdb> p f.
f.buffer          f.fileno          f.newlines        f.seekable
f.close           f.flush           f.read            f.tell
f.closed          f.isatty          f.readable        f.truncate
f.detach          f.line_buffering  f.readline        f.writable
f.encoding        f.mode            f.readlines       f.write
f.errors          f.name            f.seek            f.writelines
ipdb> p f.

(Sorry for using Python 3 in that example transcript; my Python 2.7 is right in the middle of upgrading IPython...)

Upvotes: 3

Related Questions