rocky edited this page Jun 2, 2015 · 1 revision

Until a more detailed guide is written, we'll give an overview of trepan2 here. You can find where we're going by comparing with the manuals for pydb and ruby-debug.

The help system has been reworked from pydb and pdb and it is more extensive now. Play around with it. Starting with a plain help

(trepan2) helpClasses of commands:breakpoints -- Making the program stop at certain pointsdata -- Examining data...(trepan2) help breakpointsList of commands:break -- Set breakpoint at specified line or functioncondition -- Specify breakpoint number N ......(trepan2) help *List of all debugger commands: break enable ipython python source condition examine jump quit step ...

You can set the line width to use in displaying the help output using the command: set width. To see the current line width, initially taken from the COLUMNS environment variable, type: show width.

The list command will show you your source code.

(trepan2) list21#!/usr/bin/python2"""Greatest Common Divisor 3 4 Some characterstics of this program used for testing check_args() does 5 not have a 'return' statement. 6 7 check_args() raises an uncaught exception when given the wrong number 8 of parameters. 9 10 -> """
(trepan2) list# keep going11importsys1213defcheck_args():
14iflen(sys.argv) !=3:
15# Rather than use sys.exit let's just raise an error16raiseException, "Need to give two numbers"17foriinrange(2):
18try:
19sys.argv[i+1] =int(sys.argv[i+1])
20exceptValueError:
(trepan2) importos.path# Assumes set autoeval on
(trepan2) listos.path1111"""Common operations on Posix pathnames. 2 3 Instead of importing this module directly, import os and refer to 4 this module as os.path. The "os.path" name is an alias for this 5 module on Posix systems; on other systems (e.g. Mac, Windows), 6 os.path provides the same operations in a manner specific to that 7 platform, and is an alias to another module (e.g. macpath, ntpath). 8 9 Some of this can actually be useful on non-Posix systems too, e.g. 10 for manipulation of the pathname component of URLs. 11 """
(trepan2) listos.path.join5152# Join pathnames.53# Ignore the previous parts if a part is absolute.54# Insert a '/' unless the first part is empty or already ends in '/'.5556defjoin(a, *p):
57"""Join two or more pathname components, inserting '/' as needed"""58path=a59forbinp:
60ifb.startswith('/'):
(trepan2) remember_this_line=17
(trepan2) listremember_this_line1213defcheck_args():
14iflen(sys.argv) !=3:
15# Rather than use sys.exit let's just raise an error16raiseException, "Need to give two numbers"17foriinrange(2):
18try:
19sys.argv[i+1] =int(sys.argv[i+1])
20exceptValueError:
21print"** Expecting an integer, got: %s"%repr(sys.argv[i])
(trepan2)

There are many more options and possibilities so check out help list for details. If you are not using trepan2 via some sort of front-end program (e.g. I generally use my GNU Emacs front-end. Also see [#Set_Auto_List] below.

Here's a sample session using these commands:

(trepan2) setbasename# Short filenames in display
(trepan2) settrace# Show the events
(trepan2) step4line-gcd.py:13line-gcd.py:26line-gcd.py:40line-gcd.py:41
(gcd.py:41): <module>--41check_args()
(trepan2) s# 's' is an abbreviation for stepcall-gcd.py:13
(gcd.py:13): check_args->13defcheck_args():
(trepan2) step<# Step until the next returnline-gcd.py:14line-gcd.py:17line-gcd.py:18line-gcd.py:19line-gcd.py:17line-gcd.py:18line-gcd.py:19line-gcd.py:17return-gcd.py:17
(gcd.py:17): check_args<-17foriinrange(2):
(trepan2) settraceoff# That's enough tracing
(trepan2) next# like step but skips over function calls
(gcd.py:43): <module>--43 (a, b) =sys.argv[1:3]
(trepan2) # A carriage-return or empty command runs the last step/next
(gcd.py:44): <module>--44print"The GCD of %d and %d is %d"% (a, b, gcd(a, b))
(trepan2) s<# step until the next call
(gcd.py:26): gcd->26defgcd(a,b):
(trepan2) finish# run until return of *this* function; compare with s<
(gcd.py:38): gcd<-38returngcd(b-a, a)
(trepan2) retval# show the return value1
(trepan2)

In this section we describe cool commands not generally found in other Python debuggers that you may want to experiment with.

In addition to the sub-commands that we describe in more detail, also look at:

  • set autopython -- go into python automatically on every stop
  • set trace -- turn on/off event tracing
  • info threads -- show list of threads and where they are

Also check out the set, show, and info commands in general.

aliasalias-namedebugger-command

Add alias alias-name for a debugger command debugger-comand.

Add an alias when you want to use a command abbreviation for a command that would otherwise be ambigous. For example, by default we make s be an alias of step to force it to be used. Without the alias, s might be step, show, or set among others

Example:

alias cat list # "cat myprog.py" is the same as "list myprog.py"
alias s step # "s" is now an alias for "step".
# The above example is done by default.

See also unalias and show alias.

unaliasalias-name

Remove alias alias-name.

See also alias.

macromacro-namelambda-object

Define macro-name as a debugger macro. Debugger macros get a list of arguments which you supply without parenthesis or commas. See below for an example.

The macro (really a Python lambda) should return either a String or an List of Strings. The string in both cases is a debugger command. Each string gets tokenized by a simple split() . Note that macro processing is done right after splitting on ;;. As a result, if the macro returns a string containing ;; this will not be interpreted as separating debugger commands.

If a list of strings is returned, then the first string is shifted from the list and executed. The remaining strings are pushed onto the command queue. In contrast to the first string, subsequent strings can contain other macros. ;; in those strings will be split into separate commands.

Here is an trivial example. The below creates a macro called l= which is the same thing as list .:

macro l= lambda: 'list .'

A simple text to text substitution of one command was all that was needed here. But usually you will want to run several commands. So those have to be wrapped up into a list.

The below creates a macro called fin+ which issues two commands finish followed by step:

macro fin+ lambda: ['finish','step']

If you wanted to parameterize the argument of the finish command you could do that this way:

macro fin+ lambda levels: ['finish %s' % levels ,'step']

Invoking with:

fin+ 3

would expand to: ['finish 3', 'step']

If you were to add another parameter for step, the note that the invocation might be:

fin+ 3 2

rather than fin+(3,2) or fin+ 3, 2.

See also alias, and info macro.

setautoeval [on|off]

Evaluate unrecognized debugger commands.

Often inside the debugger, one would like to be able to run arbitrary Python commands without having to preface Python expressions with print or eval. Setting autoeval on will cause unrecognized debugger commands to be eval'd as a Python expression.

Note that if this is set, on error the message shown on type a bad debugger command changes from:

Undefined command: "fdafds". Try "help".

to something more Python-eval-specific such as:

NameError: name 'fdafds' is not defined

One other thing that trips people up is when setting autoeval is that there are some short debugger commands that sometimes one wants to use as a variable, such as in an assignment statement. For example:

s = 5

which produces when autoeval is on:

Command 'step' can take at most 1 argument(s); got 2.

because by default, s is an alias for the debugger step command. It is possible to remove that alias if this causes constant problem.

setautolist [on|off]

Run the list command every time you stop in the debugger. With this, you will get output like:

-> 1 from subprocess import Popen, PIPE
(trepan2) next
(/users/fbicknel/Projects/disk_setup/sqlplus.py:2): <module>
-- 2 import os
1 from subprocess import Popen, PIPE
2 -> import os
3 import re
4
5 class SqlPlusExecutor(object):
6 def __init__(self, connection_string='/ as sysdba', sid=None):
7 self.__connection_string = connection_string
8 self.session = None
9 self.stdout = None
10 self.stderr = None
(trepan2) next
(/users/fbicknel/Projects/disk_setup/sqlplus.py:3): <module>
-- 3 import re
1 from subprocess import Popen, PIPE
2 import os
3 -> import re
4
5 class SqlPlusExecutor(object):
6 def __init__(self, connection_string='/ as sysdba', sid=None):
7 self.__connection_string = connection_string
8 self.session = None
9 self.stdout = None
10 self.stderr = None
(trepan2)

You may also want to put this this in your debugger startup file. See [#Startup_Profile]

python [-d]

Run Python as a command subshell. The sys.ps1 prompt will be set to trepan2 >>>.

If -d is passed, you can access debugger state via local variable debugger.

To issue a debugger command use function dbgr(). For example:

dbgr('info program')

Set consecutive stops must be on different file/line positions.

By default, the debugger traces all events possible including line, exceptions, call and return events. Just this alone may mean that for any given source line several consecutive stops at a given line may occur. Independent of this, Python allows one to put several commands in a single source line of code. When a programmer does this, it might be because the programmer thinks of the line as one unit.

One of the challenges of debugging is getting the granualarity of stepping comfortable. Because of the above, stepping all events can often be too fine-grained and annoying. By setting different on you can set a more coarse-level of stepping which often still is small enough that you won't miss anything important.

Note that the 'step' and 'next' debugger commands have '+' and '-' suffixes if you wan to override this setting on a per-command basis.

See also set trace to change what events you want to filter.

disassemble [thing] [start-line [end-line]]

With no argument, disassemble the current frame. With an integer start-line, the disassembly is narrowed to show lines starting at that line number or later; with an end-line number, disassembly stops when the next line would be greater than that or the end of the code is hit.

If start-line or end-line is., +, or -, the current line number is used. If instead it starts with a plus or minus prefix to a number, then the line number is relative to the current frame number.

With a class, method, function, pyc-file, code or string argument disassemble that.

Examples:

disassemble # Possibly lots of stuff dissassembled
disassemble . # Disassemble lines starting at current stopping point.
disassemble + # Same as above
disassemble +0 # Same as above
disassemble os.path # Disassemble all of os.path
disassemble os.path.normcase # Disaassemble just method os.path.normcase
disassemble -3 # Disassemble subtracting 3 from the current line number
disassemble +3 # Disassemble adding 3 from the current line number
disassemble 3 # Disassemble starting from line 3
disassemble 3 10 # Disassemble lines 3 to 10
disassemble myprog.pyc # Disassemble file myprog.pyc

Clone this wiki locally

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content
rocky edited this page Jun 2, 2015 · 1 revision

Until a more detailed guide is written, we'll give an overview of trepan2 here. You can find where we're going by comparing with the manuals for pydb and ruby-debug.

The help system has been reworked from pydb and pdb and it is more extensive now. Play around with it. Starting with a plain help

(trepan2) helpClasses of commands:breakpoints -- Making the program stop at certain pointsdata -- Examining data...(trepan2) help breakpointsList of commands:break -- Set breakpoint at specified line or functioncondition -- Specify breakpoint number N ......(trepan2) help *List of all debugger commands: break enable ipython python source condition examine jump quit step ...

You can set the line width to use in displaying the help output using the command: set width. To see the current line width, initially taken from the COLUMNS environment variable, type: show width.

The list command will show you your source code.

(trepan2) list21#!/usr/bin/python2"""Greatest Common Divisor 3 4 Some characterstics of this program used for testing check_args() does 5 not have a 'return' statement. 6 7 check_args() raises an uncaught exception when given the wrong number 8 of parameters. 9 10 -> """
(trepan2) list# keep going11importsys1213defcheck_args():
14iflen(sys.argv) !=3:
15# Rather than use sys.exit let's just raise an error16raiseException, "Need to give two numbers"17foriinrange(2):
18try:
19sys.argv[i+1] =int(sys.argv[i+1])
20exceptValueError:
(trepan2) importos.path# Assumes set autoeval on
(trepan2) listos.path1111"""Common operations on Posix pathnames. 2 3 Instead of importing this module directly, import os and refer to 4 this module as os.path. The "os.path" name is an alias for this 5 module on Posix systems; on other systems (e.g. Mac, Windows), 6 os.path provides the same operations in a manner specific to that 7 platform, and is an alias to another module (e.g. macpath, ntpath). 8 9 Some of this can actually be useful on non-Posix systems too, e.g. 10 for manipulation of the pathname component of URLs. 11 """
(trepan2) listos.path.join5152# Join pathnames.53# Ignore the previous parts if a part is absolute.54# Insert a '/' unless the first part is empty or already ends in '/'.5556defjoin(a, *p):
57"""Join two or more pathname components, inserting '/' as needed"""58path=a59forbinp:
60ifb.startswith('/'):
(trepan2) remember_this_line=17
(trepan2) listremember_this_line1213defcheck_args():
14iflen(sys.argv) !=3:
15# Rather than use sys.exit let's just raise an error16raiseException, "Need to give two numbers"17foriinrange(2):
18try:
19sys.argv[i+1] =int(sys.argv[i+1])
20exceptValueError:
21print"** Expecting an integer, got: %s"%repr(sys.argv[i])
(trepan2)

There are many more options and possibilities so check out help list for details. If you are not using trepan2 via some sort of front-end program (e.g. I generally use my GNU Emacs front-end. Also see [#Set_Auto_List] below.

Here's a sample session using these commands:

(trepan2) setbasename# Short filenames in display
(trepan2) settrace# Show the events
(trepan2) step4line-gcd.py:13line-gcd.py:26line-gcd.py:40line-gcd.py:41
(gcd.py:41): <module>--41check_args()
(trepan2) s# 's' is an abbreviation for stepcall-gcd.py:13
(gcd.py:13): check_args->13defcheck_args():
(trepan2) step<# Step until the next returnline-gcd.py:14line-gcd.py:17line-gcd.py:18line-gcd.py:19line-gcd.py:17line-gcd.py:18line-gcd.py:19line-gcd.py:17return-gcd.py:17
(gcd.py:17): check_args<-17foriinrange(2):
(trepan2) settraceoff# That's enough tracing
(trepan2) next# like step but skips over function calls
(gcd.py:43): <module>--43 (a, b) =sys.argv[1:3]
(trepan2) # A carriage-return or empty command runs the last step/next
(gcd.py:44): <module>--44print"The GCD of %d and %d is %d"% (a, b, gcd(a, b))
(trepan2) s<# step until the next call
(gcd.py:26): gcd->26defgcd(a,b):
(trepan2) finish# run until return of *this* function; compare with s<
(gcd.py:38): gcd<-38returngcd(b-a, a)
(trepan2) retval# show the return value1
(trepan2)

In this section we describe cool commands not generally found in other Python debuggers that you may want to experiment with.

In addition to the sub-commands that we describe in more detail, also look at:

  • set autopython -- go into python automatically on every stop
  • set trace -- turn on/off event tracing
  • info threads -- show list of threads and where they are

Also check out the set, show, and info commands in general.

aliasalias-namedebugger-command

Add alias alias-name for a debugger command debugger-comand.

Add an alias when you want to use a command abbreviation for a command that would otherwise be ambigous. For example, by default we make s be an alias of step to force it to be used. Without the alias, s might be step, show, or set among others

Example:

alias cat list # "cat myprog.py" is the same as "list myprog.py"
alias s step # "s" is now an alias for "step".
# The above example is done by default.

See also unalias and show alias.

unaliasalias-name

Remove alias alias-name.

See also alias.

macromacro-namelambda-object

Define macro-name as a debugger macro. Debugger macros get a list of arguments which you supply without parenthesis or commas. See below for an example.

The macro (really a Python lambda) should return either a String or an List of Strings. The string in both cases is a debugger command. Each string gets tokenized by a simple split() . Note that macro processing is done right after splitting on ;;. As a result, if the macro returns a string containing ;; this will not be interpreted as separating debugger commands.

If a list of strings is returned, then the first string is shifted from the list and executed. The remaining strings are pushed onto the command queue. In contrast to the first string, subsequent strings can contain other macros. ;; in those strings will be split into separate commands.

Here is an trivial example. The below creates a macro called l= which is the same thing as list .:

macro l= lambda: 'list .'

A simple text to text substitution of one command was all that was needed here. But usually you will want to run several commands. So those have to be wrapped up into a list.

The below creates a macro called fin+ which issues two commands finish followed by step:

macro fin+ lambda: ['finish','step']

If you wanted to parameterize the argument of the finish command you could do that this way:

macro fin+ lambda levels: ['finish %s' % levels ,'step']

Invoking with:

fin+ 3

would expand to: ['finish 3', 'step']

If you were to add another parameter for step, the note that the invocation might be:

fin+ 3 2

rather than fin+(3,2) or fin+ 3, 2.

See also alias, and info macro.

setautoeval [on|off]

Evaluate unrecognized debugger commands.

Often inside the debugger, one would like to be able to run arbitrary Python commands without having to preface Python expressions with print or eval. Setting autoeval on will cause unrecognized debugger commands to be eval'd as a Python expression.

Note that if this is set, on error the message shown on type a bad debugger command changes from:

Undefined command: "fdafds". Try "help".

to something more Python-eval-specific such as:

NameError: name 'fdafds' is not defined

One other thing that trips people up is when setting autoeval is that there are some short debugger commands that sometimes one wants to use as a variable, such as in an assignment statement. For example:

s = 5

which produces when autoeval is on:

Command 'step' can take at most 1 argument(s); got 2.

because by default, s is an alias for the debugger step command. It is possible to remove that alias if this causes constant problem.

setautolist [on|off]

Run the list command every time you stop in the debugger. With this, you will get output like:

-> 1 from subprocess import Popen, PIPE
(trepan2) next
(/users/fbicknel/Projects/disk_setup/sqlplus.py:2): <module>
-- 2 import os
1 from subprocess import Popen, PIPE
2 -> import os
3 import re
4
5 class SqlPlusExecutor(object):
6 def __init__(self, connection_string='/ as sysdba', sid=None):
7 self.__connection_string = connection_string
8 self.session = None
9 self.stdout = None
10 self.stderr = None
(trepan2) next
(/users/fbicknel/Projects/disk_setup/sqlplus.py:3): <module>
-- 3 import re
1 from subprocess import Popen, PIPE
2 import os
3 -> import re
4
5 class SqlPlusExecutor(object):
6 def __init__(self, connection_string='/ as sysdba', sid=None):
7 self.__connection_string = connection_string
8 self.session = None
9 self.stdout = None
10 self.stderr = None
(trepan2)

You may also want to put this this in your debugger startup file. See [#Startup_Profile]

python [-d]

Run Python as a command subshell. The sys.ps1 prompt will be set to trepan2 >>>.

If -d is passed, you can access debugger state via local variable debugger.

To issue a debugger command use function dbgr(). For example:

dbgr('info program')

Set consecutive stops must be on different file/line positions.

By default, the debugger traces all events possible including line, exceptions, call and return events. Just this alone may mean that for any given source line several consecutive stops at a given line may occur. Independent of this, Python allows one to put several commands in a single source line of code. When a programmer does this, it might be because the programmer thinks of the line as one unit.

One of the challenges of debugging is getting the granualarity of stepping comfortable. Because of the above, stepping all events can often be too fine-grained and annoying. By setting different on you can set a more coarse-level of stepping which often still is small enough that you won't miss anything important.

Note that the 'step' and 'next' debugger commands have '+' and '-' suffixes if you wan to override this setting on a per-command basis.

See also set trace to change what events you want to filter.

disassemble [thing] [start-line [end-line]]

With no argument, disassemble the current frame. With an integer start-line, the disassembly is narrowed to show lines starting at that line number or later; with an end-line number, disassembly stops when the next line would be greater than that or the end of the code is hit.

If start-line or end-line is., +, or -, the current line number is used. If instead it starts with a plus or minus prefix to a number, then the line number is relative to the current frame number.

With a class, method, function, pyc-file, code or string argument disassemble that.

Examples:

disassemble # Possibly lots of stuff dissassembled
disassemble . # Disassemble lines starting at current stopping point.
disassemble + # Same as above
disassemble +0 # Same as above
disassemble os.path # Disassemble all of os.path
disassemble os.path.normcase # Disaassemble just method os.path.normcase
disassemble -3 # Disassemble subtracting 3 from the current line number
disassemble +3 # Disassemble adding 3 from the current line number
disassemble 3 # Disassemble starting from line 3
disassemble 3 10 # Disassemble lines 3 to 10
disassemble myprog.pyc # Disassemble file myprog.pyc

Clone this wiki locally

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
rocky edited this page Jun 2, 2015 · 1 revision

Until a more detailed guide is written, we'll give an overview of trepan2 here. You can find where we're going by comparing with the manuals for pydb and ruby-debug.

The help system has been reworked from pydb and pdb and it is more extensive now. Play around with it. Starting with a plain help

(trepan2) helpClasses of commands:breakpoints -- Making the program stop at certain pointsdata -- Examining data...(trepan2) help breakpointsList of commands:break -- Set breakpoint at specified line or functioncondition -- Specify breakpoint number N ......(trepan2) help *List of all debugger commands: break enable ipython python source condition examine jump quit step ...

You can set the line width to use in displaying the help output using the command: set width. To see the current line width, initially taken from the COLUMNS environment variable, type: show width.

The list command will show you your source code.

(trepan2) list21#!/usr/bin/python2"""Greatest Common Divisor 3 4 Some characterstics of this program used for testing check_args() does 5 not have a 'return' statement. 6 7 check_args() raises an uncaught exception when given the wrong number 8 of parameters. 9 10 -> """
(trepan2) list# keep going11importsys1213defcheck_args():
14iflen(sys.argv) !=3:
15# Rather than use sys.exit let's just raise an error16raiseException, "Need to give two numbers"17foriinrange(2):
18try:
19sys.argv[i+1] =int(sys.argv[i+1])
20exceptValueError:
(trepan2) importos.path# Assumes set autoeval on
(trepan2) listos.path1111"""Common operations on Posix pathnames. 2 3 Instead of importing this module directly, import os and refer to 4 this module as os.path. The "os.path" name is an alias for this 5 module on Posix systems; on other systems (e.g. Mac, Windows), 6 os.path provides the same operations in a manner specific to that 7 platform, and is an alias to another module (e.g. macpath, ntpath). 8 9 Some of this can actually be useful on non-Posix systems too, e.g. 10 for manipulation of the pathname component of URLs. 11 """
(trepan2) listos.path.join5152# Join pathnames.53# Ignore the previous parts if a part is absolute.54# Insert a '/' unless the first part is empty or already ends in '/'.5556defjoin(a, *p):
57"""Join two or more pathname components, inserting '/' as needed"""58path=a59forbinp:
60ifb.startswith('/'):
(trepan2) remember_this_line=17
(trepan2) listremember_this_line1213defcheck_args():
14iflen(sys.argv) !=3:
15# Rather than use sys.exit let's just raise an error16raiseException, "Need to give two numbers"17foriinrange(2):
18try:
19sys.argv[i+1] =int(sys.argv[i+1])
20exceptValueError:
21print"** Expecting an integer, got: %s"%repr(sys.argv[i])
(trepan2)

There are many more options and possibilities so check out help list for details. If you are not using trepan2 via some sort of front-end program (e.g. I generally use my GNU Emacs front-end. Also see [#Set_Auto_List] below.

Here's a sample session using these commands:

(trepan2) setbasename# Short filenames in display
(trepan2) settrace# Show the events
(trepan2) step4line-gcd.py:13line-gcd.py:26line-gcd.py:40line-gcd.py:41
(gcd.py:41): <module>--41check_args()
(trepan2) s# 's' is an abbreviation for stepcall-gcd.py:13
(gcd.py:13): check_args->13defcheck_args():
(trepan2) step<# Step until the next returnline-gcd.py:14line-gcd.py:17line-gcd.py:18line-gcd.py:19line-gcd.py:17line-gcd.py:18line-gcd.py:19line-gcd.py:17return-gcd.py:17
(gcd.py:17): check_args<-17foriinrange(2):
(trepan2) settraceoff# That's enough tracing
(trepan2) next# like step but skips over function calls
(gcd.py:43): <module>--43 (a, b) =sys.argv[1:3]
(trepan2) # A carriage-return or empty command runs the last step/next
(gcd.py:44): <module>--44print"The GCD of %d and %d is %d"% (a, b, gcd(a, b))
(trepan2) s<# step until the next call
(gcd.py:26): gcd->26defgcd(a,b):
(trepan2) finish# run until return of *this* function; compare with s<
(gcd.py:38): gcd<-38returngcd(b-a, a)
(trepan2) retval# show the return value1
(trepan2)

In this section we describe cool commands not generally found in other Python debuggers that you may want to experiment with.

In addition to the sub-commands that we describe in more detail, also look at:

  • set autopython -- go into python automatically on every stop
  • set trace -- turn on/off event tracing
  • info threads -- show list of threads and where they are

Also check out the set, show, and info commands in general.

aliasalias-namedebugger-command

Add alias alias-name for a debugger command debugger-comand.

Add an alias when you want to use a command abbreviation for a command that would otherwise be ambigous. For example, by default we make s be an alias of step to force it to be used. Without the alias, s might be step, show, or set among others

Example:

alias cat list # "cat myprog.py" is the same as "list myprog.py"
alias s step # "s" is now an alias for "step".
# The above example is done by default.

See also unalias and show alias.

unaliasalias-name

Remove alias alias-name.

See also alias.

macromacro-namelambda-object

Define macro-name as a debugger macro. Debugger macros get a list of arguments which you supply without parenthesis or commas. See below for an example.

The macro (really a Python lambda) should return either a String or an List of Strings. The string in both cases is a debugger command. Each string gets tokenized by a simple split() . Note that macro processing is done right after splitting on ;;. As a result, if the macro returns a string containing ;; this will not be interpreted as separating debugger commands.

If a list of strings is returned, then the first string is shifted from the list and executed. The remaining strings are pushed onto the command queue. In contrast to the first string, subsequent strings can contain other macros. ;; in those strings will be split into separate commands.

Here is an trivial example. The below creates a macro called l= which is the same thing as list .:

macro l= lambda: 'list .'

A simple text to text substitution of one command was all that was needed here. But usually you will want to run several commands. So those have to be wrapped up into a list.

The below creates a macro called fin+ which issues two commands finish followed by step:

macro fin+ lambda: ['finish','step']

If you wanted to parameterize the argument of the finish command you could do that this way:

macro fin+ lambda levels: ['finish %s' % levels ,'step']

Invoking with:

fin+ 3

would expand to: ['finish 3', 'step']

If you were to add another parameter for step, the note that the invocation might be:

fin+ 3 2

rather than fin+(3,2) or fin+ 3, 2.

See also alias, and info macro.

setautoeval [on|off]

Evaluate unrecognized debugger commands.

Often inside the debugger, one would like to be able to run arbitrary Python commands without having to preface Python expressions with print or eval. Setting autoeval on will cause unrecognized debugger commands to be eval'd as a Python expression.

Note that if this is set, on error the message shown on type a bad debugger command changes from:

Undefined command: "fdafds". Try "help".

to something more Python-eval-specific such as:

NameError: name 'fdafds' is not defined

One other thing that trips people up is when setting autoeval is that there are some short debugger commands that sometimes one wants to use as a variable, such as in an assignment statement. For example:

s = 5

which produces when autoeval is on:

Command 'step' can take at most 1 argument(s); got 2.

because by default, s is an alias for the debugger step command. It is possible to remove that alias if this causes constant problem.

setautolist [on|off]

Run the list command every time you stop in the debugger. With this, you will get output like:

-> 1 from subprocess import Popen, PIPE
(trepan2) next
(/users/fbicknel/Projects/disk_setup/sqlplus.py:2): <module>
-- 2 import os
1 from subprocess import Popen, PIPE
2 -> import os
3 import re
4
5 class SqlPlusExecutor(object):
6 def __init__(self, connection_string='/ as sysdba', sid=None):
7 self.__connection_string = connection_string
8 self.session = None
9 self.stdout = None
10 self.stderr = None
(trepan2) next
(/users/fbicknel/Projects/disk_setup/sqlplus.py:3): <module>
-- 3 import re
1 from subprocess import Popen, PIPE
2 import os
3 -> import re
4
5 class SqlPlusExecutor(object):
6 def __init__(self, connection_string='/ as sysdba', sid=None):
7 self.__connection_string = connection_string
8 self.session = None
9 self.stdout = None
10 self.stderr = None
(trepan2)

You may also want to put this this in your debugger startup file. See [#Startup_Profile]

python [-d]

Run Python as a command subshell. The sys.ps1 prompt will be set to trepan2 >>>.

If -d is passed, you can access debugger state via local variable debugger.

To issue a debugger command use function dbgr(). For example:

dbgr('info program')

Set consecutive stops must be on different file/line positions.

By default, the debugger traces all events possible including line, exceptions, call and return events. Just this alone may mean that for any given source line several consecutive stops at a given line may occur. Independent of this, Python allows one to put several commands in a single source line of code. When a programmer does this, it might be because the programmer thinks of the line as one unit.

One of the challenges of debugging is getting the granualarity of stepping comfortable. Because of the above, stepping all events can often be too fine-grained and annoying. By setting different on you can set a more coarse-level of stepping which often still is small enough that you won't miss anything important.

Note that the 'step' and 'next' debugger commands have '+' and '-' suffixes if you wan to override this setting on a per-command basis.

See also set trace to change what events you want to filter.

disassemble [thing] [start-line [end-line]]

With no argument, disassemble the current frame. With an integer start-line, the disassembly is narrowed to show lines starting at that line number or later; with an end-line number, disassembly stops when the next line would be greater than that or the end of the code is hit.

If start-line or end-line is., +, or -, the current line number is used. If instead it starts with a plus or minus prefix to a number, then the line number is relative to the current frame number.

With a class, method, function, pyc-file, code or string argument disassemble that.

Examples:

disassemble # Possibly lots of stuff dissassembled
disassemble . # Disassemble lines starting at current stopping point.
disassemble + # Same as above
disassemble +0 # Same as above
disassemble os.path # Disassemble all of os.path
disassemble os.path.normcase # Disaassemble just method os.path.normcase
disassemble -3 # Disassemble subtracting 3 from the current line number
disassemble +3 # Disassemble adding 3 from the current line number
disassemble 3 # Disassemble starting from line 3
disassemble 3 10 # Disassemble lines 3 to 10
disassemble myprog.pyc # Disassemble file myprog.pyc

Clone this wiki locally

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
rocky edited this page Jun 2, 2015 · 1 revision

Until a more detailed guide is written, we'll give an overview of trepan2 here. You can find where we're going by comparing with the manuals for pydb and ruby-debug.

The help system has been reworked from pydb and pdb and it is more extensive now. Play around with it. Starting with a plain help

(trepan2) helpClasses of commands:breakpoints -- Making the program stop at certain pointsdata -- Examining data...(trepan2) help breakpointsList of commands:break -- Set breakpoint at specified line or functioncondition -- Specify breakpoint number N ......(trepan2) help *List of all debugger commands: break enable ipython python source condition examine jump quit step ...

You can set the line width to use in displaying the help output using the command: set width. To see the current line width, initially taken from the COLUMNS environment variable, type: show width.

The list command will show you your source code.

(trepan2) list21#!/usr/bin/python2"""Greatest Common Divisor 3 4 Some characterstics of this program used for testing check_args() does 5 not have a 'return' statement. 6 7 check_args() raises an uncaught exception when given the wrong number 8 of parameters. 9 10 -> """
(trepan2) list# keep going11importsys1213defcheck_args():
14iflen(sys.argv) !=3:
15# Rather than use sys.exit let's just raise an error16raiseException, "Need to give two numbers"17foriinrange(2):
18try:
19sys.argv[i+1] =int(sys.argv[i+1])
20exceptValueError:
(trepan2) importos.path# Assumes set autoeval on
(trepan2) listos.path1111"""Common operations on Posix pathnames. 2 3 Instead of importing this module directly, import os and refer to 4 this module as os.path. The "os.path" name is an alias for this 5 module on Posix systems; on other systems (e.g. Mac, Windows), 6 os.path provides the same operations in a manner specific to that 7 platform, and is an alias to another module (e.g. macpath, ntpath). 8 9 Some of this can actually be useful on non-Posix systems too, e.g. 10 for manipulation of the pathname component of URLs. 11 """
(trepan2) listos.path.join5152# Join pathnames.53# Ignore the previous parts if a part is absolute.54# Insert a '/' unless the first part is empty or already ends in '/'.5556defjoin(a, *p):
57"""Join two or more pathname components, inserting '/' as needed"""58path=a59forbinp:
60ifb.startswith('/'):
(trepan2) remember_this_line=17
(trepan2) listremember_this_line1213defcheck_args():
14iflen(sys.argv) !=3:
15# Rather than use sys.exit let's just raise an error16raiseException, "Need to give two numbers"17foriinrange(2):
18try:
19sys.argv[i+1] =int(sys.argv[i+1])
20exceptValueError:
21print"** Expecting an integer, got: %s"%repr(sys.argv[i])
(trepan2)

There are many more options and possibilities so check out help list for details. If you are not using trepan2 via some sort of front-end program (e.g. I generally use my GNU Emacs front-end. Also see [#Set_Auto_List] below.

Here's a sample session using these commands:

(trepan2) setbasename# Short filenames in display
(trepan2) settrace# Show the events
(trepan2) step4line-gcd.py:13line-gcd.py:26line-gcd.py:40line-gcd.py:41
(gcd.py:41): <module>--41check_args()
(trepan2) s# 's' is an abbreviation for stepcall-gcd.py:13
(gcd.py:13): check_args->13defcheck_args():
(trepan2) step<# Step until the next returnline-gcd.py:14line-gcd.py:17line-gcd.py:18line-gcd.py:19line-gcd.py:17line-gcd.py:18line-gcd.py:19line-gcd.py:17return-gcd.py:17
(gcd.py:17): check_args<-17foriinrange(2):
(trepan2) settraceoff# That's enough tracing
(trepan2) next# like step but skips over function calls
(gcd.py:43): <module>--43 (a, b) =sys.argv[1:3]
(trepan2) # A carriage-return or empty command runs the last step/next
(gcd.py:44): <module>--44print"The GCD of %d and %d is %d"% (a, b, gcd(a, b))
(trepan2) s<# step until the next call
(gcd.py:26): gcd->26defgcd(a,b):
(trepan2) finish# run until return of *this* function; compare with s<
(gcd.py:38): gcd<-38returngcd(b-a, a)
(trepan2) retval# show the return value1
(trepan2)

In this section we describe cool commands not generally found in other Python debuggers that you may want to experiment with.

In addition to the sub-commands that we describe in more detail, also look at:

  • set autopython -- go into python automatically on every stop
  • set trace -- turn on/off event tracing
  • info threads -- show list of threads and where they are

Also check out the set, show, and info commands in general.

aliasalias-namedebugger-command

Add alias alias-name for a debugger command debugger-comand.

Add an alias when you want to use a command abbreviation for a command that would otherwise be ambigous. For example, by default we make s be an alias of step to force it to be used. Without the alias, s might be step, show, or set among others

Example:

alias cat list # "cat myprog.py" is the same as "list myprog.py"
alias s step # "s" is now an alias for "step".
# The above example is done by default.

See also unalias and show alias.

unaliasalias-name

Remove alias alias-name.

See also alias.

macromacro-namelambda-object

Define macro-name as a debugger macro. Debugger macros get a list of arguments which you supply without parenthesis or commas. See below for an example.

The macro (really a Python lambda) should return either a String or an List of Strings. The string in both cases is a debugger command. Each string gets tokenized by a simple split() . Note that macro processing is done right after splitting on ;;. As a result, if the macro returns a string containing ;; this will not be interpreted as separating debugger commands.

If a list of strings is returned, then the first string is shifted from the list and executed. The remaining strings are pushed onto the command queue. In contrast to the first string, subsequent strings can contain other macros. ;; in those strings will be split into separate commands.

Here is an trivial example. The below creates a macro called l= which is the same thing as list .:

macro l= lambda: 'list .'

A simple text to text substitution of one command was all that was needed here. But usually you will want to run several commands. So those have to be wrapped up into a list.

The below creates a macro called fin+ which issues two commands finish followed by step:

macro fin+ lambda: ['finish','step']

If you wanted to parameterize the argument of the finish command you could do that this way:

macro fin+ lambda levels: ['finish %s' % levels ,'step']

Invoking with:

fin+ 3

would expand to: ['finish 3', 'step']

If you were to add another parameter for step, the note that the invocation might be:

fin+ 3 2

rather than fin+(3,2) or fin+ 3, 2.

See also alias, and info macro.

setautoeval [on|off]

Evaluate unrecognized debugger commands.

Often inside the debugger, one would like to be able to run arbitrary Python commands without having to preface Python expressions with print or eval. Setting autoeval on will cause unrecognized debugger commands to be eval'd as a Python expression.

Note that if this is set, on error the message shown on type a bad debugger command changes from:

Undefined command: "fdafds". Try "help".

to something more Python-eval-specific such as:

NameError: name 'fdafds' is not defined

One other thing that trips people up is when setting autoeval is that there are some short debugger commands that sometimes one wants to use as a variable, such as in an assignment statement. For example:

s = 5

which produces when autoeval is on:

Command 'step' can take at most 1 argument(s); got 2.

because by default, s is an alias for the debugger step command. It is possible to remove that alias if this causes constant problem.

setautolist [on|off]

Run the list command every time you stop in the debugger. With this, you will get output like:

-> 1 from subprocess import Popen, PIPE
(trepan2) next
(/users/fbicknel/Projects/disk_setup/sqlplus.py:2): <module>
-- 2 import os
1 from subprocess import Popen, PIPE
2 -> import os
3 import re
4
5 class SqlPlusExecutor(object):
6 def __init__(self, connection_string='/ as sysdba', sid=None):
7 self.__connection_string = connection_string
8 self.session = None
9 self.stdout = None
10 self.stderr = None
(trepan2) next
(/users/fbicknel/Projects/disk_setup/sqlplus.py:3): <module>
-- 3 import re
1 from subprocess import Popen, PIPE
2 import os
3 -> import re
4
5 class SqlPlusExecutor(object):
6 def __init__(self, connection_string='/ as sysdba', sid=None):
7 self.__connection_string = connection_string
8 self.session = None
9 self.stdout = None
10 self.stderr = None
(trepan2)

You may also want to put this this in your debugger startup file. See [#Startup_Profile]

python [-d]

Run Python as a command subshell. The sys.ps1 prompt will be set to trepan2 >>>.

If -d is passed, you can access debugger state via local variable debugger.

To issue a debugger command use function dbgr(). For example:

dbgr('info program')

Set consecutive stops must be on different file/line positions.

By default, the debugger traces all events possible including line, exceptions, call and return events. Just this alone may mean that for any given source line several consecutive stops at a given line may occur. Independent of this, Python allows one to put several commands in a single source line of code. When a programmer does this, it might be because the programmer thinks of the line as one unit.

One of the challenges of debugging is getting the granualarity of stepping comfortable. Because of the above, stepping all events can often be too fine-grained and annoying. By setting different on you can set a more coarse-level of stepping which often still is small enough that you won't miss anything important.

Note that the 'step' and 'next' debugger commands have '+' and '-' suffixes if you wan to override this setting on a per-command basis.

See also set trace to change what events you want to filter.

disassemble [thing] [start-line [end-line]]

With no argument, disassemble the current frame. With an integer start-line, the disassembly is narrowed to show lines starting at that line number or later; with an end-line number, disassembly stops when the next line would be greater than that or the end of the code is hit.

If start-line or end-line is., +, or -, the current line number is used. If instead it starts with a plus or minus prefix to a number, then the line number is relative to the current frame number.

With a class, method, function, pyc-file, code or string argument disassemble that.

Examples:

disassemble # Possibly lots of stuff dissassembled
disassemble . # Disassemble lines starting at current stopping point.
disassemble + # Same as above
disassemble +0 # Same as above
disassemble os.path # Disassemble all of os.path
disassemble os.path.normcase # Disaassemble just method os.path.normcase
disassemble -3 # Disassemble subtracting 3 from the current line number
disassemble +3 # Disassemble adding 3 from the current line number
disassemble 3 # Disassemble starting from line 3
disassemble 3 10 # Disassemble lines 3 to 10
disassemble myprog.pyc # Disassemble file myprog.pyc

Clone this wiki locally

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content
rocky edited this page Jun 2, 2015 · 1 revision

Until a more detailed guide is written, we'll give an overview of trepan2 here. You can find where we're going by comparing with the manuals for pydb and ruby-debug.

The help system has been reworked from pydb and pdb and it is more extensive now. Play around with it. Starting with a plain help

(trepan2) helpClasses of commands:breakpoints -- Making the program stop at certain pointsdata -- Examining data...(trepan2) help breakpointsList of commands:break -- Set breakpoint at specified line or functioncondition -- Specify breakpoint number N ......(trepan2) help *List of all debugger commands: break enable ipython python source condition examine jump quit step ...

You can set the line width to use in displaying the help output using the command: set width. To see the current line width, initially taken from the COLUMNS environment variable, type: show width.

The list command will show you your source code.

(trepan2) list21#!/usr/bin/python2"""Greatest Common Divisor 3 4 Some characterstics of this program used for testing check_args() does 5 not have a 'return' statement. 6 7 check_args() raises an uncaught exception when given the wrong number 8 of parameters. 9 10 -> """
(trepan2) list# keep going11importsys1213defcheck_args():
14iflen(sys.argv) !=3:
15# Rather than use sys.exit let's just raise an error16raiseException, "Need to give two numbers"17foriinrange(2):
18try:
19sys.argv[i+1] =int(sys.argv[i+1])
20exceptValueError:
(trepan2) importos.path# Assumes set autoeval on
(trepan2) listos.path1111"""Common operations on Posix pathnames. 2 3 Instead of importing this module directly, import os and refer to 4 this module as os.path. The "os.path" name is an alias for this 5 module on Posix systems; on other systems (e.g. Mac, Windows), 6 os.path provides the same operations in a manner specific to that 7 platform, and is an alias to another module (e.g. macpath, ntpath). 8 9 Some of this can actually be useful on non-Posix systems too, e.g. 10 for manipulation of the pathname component of URLs. 11 """
(trepan2) listos.path.join5152# Join pathnames.53# Ignore the previous parts if a part is absolute.54# Insert a '/' unless the first part is empty or already ends in '/'.5556defjoin(a, *p):
57"""Join two or more pathname components, inserting '/' as needed"""58path=a59forbinp:
60ifb.startswith('/'):
(trepan2) remember_this_line=17
(trepan2) listremember_this_line1213defcheck_args():
14iflen(sys.argv) !=3:
15# Rather than use sys.exit let's just raise an error16raiseException, "Need to give two numbers"17foriinrange(2):
18try:
19sys.argv[i+1] =int(sys.argv[i+1])
20exceptValueError:
21print"** Expecting an integer, got: %s"%repr(sys.argv[i])
(trepan2)

There are many more options and possibilities so check out help list for details. If you are not using trepan2 via some sort of front-end program (e.g. I generally use my GNU Emacs front-end. Also see [#Set_Auto_List] below.

Here's a sample session using these commands:

(trepan2) setbasename# Short filenames in display
(trepan2) settrace# Show the events
(trepan2) step4line-gcd.py:13line-gcd.py:26line-gcd.py:40line-gcd.py:41
(gcd.py:41): <module>--41check_args()
(trepan2) s# 's' is an abbreviation for stepcall-gcd.py:13
(gcd.py:13): check_args->13defcheck_args():
(trepan2) step<# Step until the next returnline-gcd.py:14line-gcd.py:17line-gcd.py:18line-gcd.py:19line-gcd.py:17line-gcd.py:18line-gcd.py:19line-gcd.py:17return-gcd.py:17
(gcd.py:17): check_args<-17foriinrange(2):
(trepan2) settraceoff# That's enough tracing
(trepan2) next# like step but skips over function calls
(gcd.py:43): <module>--43 (a, b) =sys.argv[1:3]
(trepan2) # A carriage-return or empty command runs the last step/next
(gcd.py:44): <module>--44print"The GCD of %d and %d is %d"% (a, b, gcd(a, b))
(trepan2) s<# step until the next call
(gcd.py:26): gcd->26defgcd(a,b):
(trepan2) finish# run until return of *this* function; compare with s<
(gcd.py:38): gcd<-38returngcd(b-a, a)
(trepan2) retval# show the return value1
(trepan2)

In this section we describe cool commands not generally found in other Python debuggers that you may want to experiment with.

In addition to the sub-commands that we describe in more detail, also look at:

  • set autopython -- go into python automatically on every stop
  • set trace -- turn on/off event tracing
  • info threads -- show list of threads and where they are

Also check out the set, show, and info commands in general.

aliasalias-namedebugger-command

Add alias alias-name for a debugger command debugger-comand.

Add an alias when you want to use a command abbreviation for a command that would otherwise be ambigous. For example, by default we make s be an alias of step to force it to be used. Without the alias, s might be step, show, or set among others

Example:

alias cat list # "cat myprog.py" is the same as "list myprog.py"
alias s step # "s" is now an alias for "step".
# The above example is done by default.

See also unalias and show alias.

unaliasalias-name

Remove alias alias-name.

See also alias.

macromacro-namelambda-object

Define macro-name as a debugger macro. Debugger macros get a list of arguments which you supply without parenthesis or commas. See below for an example.

The macro (really a Python lambda) should return either a String or an List of Strings. The string in both cases is a debugger command. Each string gets tokenized by a simple split() . Note that macro processing is done right after splitting on ;;. As a result, if the macro returns a string containing ;; this will not be interpreted as separating debugger commands.

If a list of strings is returned, then the first string is shifted from the list and executed. The remaining strings are pushed onto the command queue. In contrast to the first string, subsequent strings can contain other macros. ;; in those strings will be split into separate commands.

Here is an trivial example. The below creates a macro called l= which is the same thing as list .:

macro l= lambda: 'list .'

A simple text to text substitution of one command was all that was needed here. But usually you will want to run several commands. So those have to be wrapped up into a list.

The below creates a macro called fin+ which issues two commands finish followed by step:

macro fin+ lambda: ['finish','step']

If you wanted to parameterize the argument of the finish command you could do that this way:

macro fin+ lambda levels: ['finish %s' % levels ,'step']

Invoking with:

fin+ 3

would expand to: ['finish 3', 'step']

If you were to add another parameter for step, the note that the invocation might be:

fin+ 3 2

rather than fin+(3,2) or fin+ 3, 2.

See also alias, and info macro.

setautoeval [on|off]

Evaluate unrecognized debugger commands.

Often inside the debugger, one would like to be able to run arbitrary Python commands without having to preface Python expressions with print or eval. Setting autoeval on will cause unrecognized debugger commands to be eval'd as a Python expression.

Note that if this is set, on error the message shown on type a bad debugger command changes from:

Undefined command: "fdafds". Try "help".

to something more Python-eval-specific such as:

NameError: name 'fdafds' is not defined

One other thing that trips people up is when setting autoeval is that there are some short debugger commands that sometimes one wants to use as a variable, such as in an assignment statement. For example:

s = 5

which produces when autoeval is on:

Command 'step' can take at most 1 argument(s); got 2.

because by default, s is an alias for the debugger step command. It is possible to remove that alias if this causes constant problem.

setautolist [on|off]

Run the list command every time you stop in the debugger. With this, you will get output like:

-> 1 from subprocess import Popen, PIPE
(trepan2) next
(/users/fbicknel/Projects/disk_setup/sqlplus.py:2): <module>
-- 2 import os
1 from subprocess import Popen, PIPE
2 -> import os
3 import re
4
5 class SqlPlusExecutor(object):
6 def __init__(self, connection_string='/ as sysdba', sid=None):
7 self.__connection_string = connection_string
8 self.session = None
9 self.stdout = None
10 self.stderr = None
(trepan2) next
(/users/fbicknel/Projects/disk_setup/sqlplus.py:3): <module>
-- 3 import re
1 from subprocess import Popen, PIPE
2 import os
3 -> import re
4
5 class SqlPlusExecutor(object):
6 def __init__(self, connection_string='/ as sysdba', sid=None):
7 self.__connection_string = connection_string
8 self.session = None
9 self.stdout = None
10 self.stderr = None
(trepan2)

You may also want to put this this in your debugger startup file. See [#Startup_Profile]

python [-d]

Run Python as a command subshell. The sys.ps1 prompt will be set to trepan2 >>>.

If -d is passed, you can access debugger state via local variable debugger.

To issue a debugger command use function dbgr(). For example:

dbgr('info program')

Set consecutive stops must be on different file/line positions.

By default, the debugger traces all events possible including line, exceptions, call and return events. Just this alone may mean that for any given source line several consecutive stops at a given line may occur. Independent of this, Python allows one to put several commands in a single source line of code. When a programmer does this, it might be because the programmer thinks of the line as one unit.

One of the challenges of debugging is getting the granualarity of stepping comfortable. Because of the above, stepping all events can often be too fine-grained and annoying. By setting different on you can set a more coarse-level of stepping which often still is small enough that you won't miss anything important.

Note that the 'step' and 'next' debugger commands have '+' and '-' suffixes if you wan to override this setting on a per-command basis.

See also set trace to change what events you want to filter.

disassemble [thing] [start-line [end-line]]

With no argument, disassemble the current frame. With an integer start-line, the disassembly is narrowed to show lines starting at that line number or later; with an end-line number, disassembly stops when the next line would be greater than that or the end of the code is hit.

If start-line or end-line is., +, or -, the current line number is used. If instead it starts with a plus or minus prefix to a number, then the line number is relative to the current frame number.

With a class, method, function, pyc-file, code or string argument disassemble that.

Examples:

disassemble # Possibly lots of stuff dissassembled
disassemble . # Disassemble lines starting at current stopping point.
disassemble + # Same as above
disassemble +0 # Same as above
disassemble os.path # Disassemble all of os.path
disassemble os.path.normcase # Disaassemble just method os.path.normcase
disassemble -3 # Disassemble subtracting 3 from the current line number
disassemble +3 # Disassemble adding 3 from the current line number
disassemble 3 # Disassemble starting from line 3
disassemble 3 10 # Disassemble lines 3 to 10
disassemble myprog.pyc # Disassemble file myprog.pyc

Clone this wiki locally

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
rocky edited this page Jun 2, 2015 · 1 revision

Until a more detailed guide is written, we'll give an overview of trepan2 here. You can find where we're going by comparing with the manuals for pydb and ruby-debug.

The help system has been reworked from pydb and pdb and it is more extensive now. Play around with it. Starting with a plain help

(trepan2) helpClasses of commands:breakpoints -- Making the program stop at certain pointsdata -- Examining data...(trepan2) help breakpointsList of commands:break -- Set breakpoint at specified line or functioncondition -- Specify breakpoint number N ......(trepan2) help *List of all debugger commands: break enable ipython python source condition examine jump quit step ...

You can set the line width to use in displaying the help output using the command: set width. To see the current line width, initially taken from the COLUMNS environment variable, type: show width.

The list command will show you your source code.

(trepan2) list21#!/usr/bin/python2"""Greatest Common Divisor 3 4 Some characterstics of this program used for testing check_args() does 5 not have a 'return' statement. 6 7 check_args() raises an uncaught exception when given the wrong number 8 of parameters. 9 10 -> """
(trepan2) list# keep going11importsys1213defcheck_args():
14iflen(sys.argv) !=3:
15# Rather than use sys.exit let's just raise an error16raiseException, "Need to give two numbers"17foriinrange(2):
18try:
19sys.argv[i+1] =int(sys.argv[i+1])
20exceptValueError:
(trepan2) importos.path# Assumes set autoeval on
(trepan2) listos.path1111"""Common operations on Posix pathnames. 2 3 Instead of importing this module directly, import os and refer to 4 this module as os.path. The "os.path" name is an alias for this 5 module on Posix systems; on other systems (e.g. Mac, Windows), 6 os.path provides the same operations in a manner specific to that 7 platform, and is an alias to another module (e.g. macpath, ntpath). 8 9 Some of this can actually be useful on non-Posix systems too, e.g. 10 for manipulation of the pathname component of URLs. 11 """
(trepan2) listos.path.join5152# Join pathnames.53# Ignore the previous parts if a part is absolute.54# Insert a '/' unless the first part is empty or already ends in '/'.5556defjoin(a, *p):
57"""Join two or more pathname components, inserting '/' as needed"""58path=a59forbinp:
60ifb.startswith('/'):
(trepan2) remember_this_line=17
(trepan2) listremember_this_line1213defcheck_args():
14iflen(sys.argv) !=3:
15# Rather than use sys.exit let's just raise an error16raiseException, "Need to give two numbers"17foriinrange(2):
18try:
19sys.argv[i+1] =int(sys.argv[i+1])
20exceptValueError:
21print"** Expecting an integer, got: %s"%repr(sys.argv[i])
(trepan2)

There are many more options and possibilities so check out help list for details. If you are not using trepan2 via some sort of front-end program (e.g. I generally use my GNU Emacs front-end. Also see [#Set_Auto_List] below.

Here's a sample session using these commands:

(trepan2) setbasename# Short filenames in display
(trepan2) settrace# Show the events
(trepan2) step4line-gcd.py:13line-gcd.py:26line-gcd.py:40line-gcd.py:41
(gcd.py:41): <module>--41check_args()
(trepan2) s# 's' is an abbreviation for stepcall-gcd.py:13
(gcd.py:13): check_args->13defcheck_args():
(trepan2) step<# Step until the next returnline-gcd.py:14line-gcd.py:17line-gcd.py:18line-gcd.py:19line-gcd.py:17line-gcd.py:18line-gcd.py:19line-gcd.py:17return-gcd.py:17
(gcd.py:17): check_args<-17foriinrange(2):
(trepan2) settraceoff# That's enough tracing
(trepan2) next# like step but skips over function calls
(gcd.py:43): <module>--43 (a, b) =sys.argv[1:3]
(trepan2) # A carriage-return or empty command runs the last step/next
(gcd.py:44): <module>--44print"The GCD of %d and %d is %d"% (a, b, gcd(a, b))
(trepan2) s<# step until the next call
(gcd.py:26): gcd->26defgcd(a,b):
(trepan2) finish# run until return of *this* function; compare with s<
(gcd.py:38): gcd<-38returngcd(b-a, a)
(trepan2) retval# show the return value1
(trepan2)

In this section we describe cool commands not generally found in other Python debuggers that you may want to experiment with.

In addition to the sub-commands that we describe in more detail, also look at:

  • set autopython -- go into python automatically on every stop
  • set trace -- turn on/off event tracing
  • info threads -- show list of threads and where they are

Also check out the set, show, and info commands in general.

aliasalias-namedebugger-command

Add alias alias-name for a debugger command debugger-comand.

Add an alias when you want to use a command abbreviation for a command that would otherwise be ambigous. For example, by default we make s be an alias of step to force it to be used. Without the alias, s might be step, show, or set among others

Example:

alias cat list # "cat myprog.py" is the same as "list myprog.py"
alias s step # "s" is now an alias for "step".
# The above example is done by default.

See also unalias and show alias.

unaliasalias-name

Remove alias alias-name.

See also alias.

macromacro-namelambda-object

Define macro-name as a debugger macro. Debugger macros get a list of arguments which you supply without parenthesis or commas. See below for an example.

The macro (really a Python lambda) should return either a String or an List of Strings. The string in both cases is a debugger command. Each string gets tokenized by a simple split() . Note that macro processing is done right after splitting on ;;. As a result, if the macro returns a string containing ;; this will not be interpreted as separating debugger commands.

If a list of strings is returned, then the first string is shifted from the list and executed. The remaining strings are pushed onto the command queue. In contrast to the first string, subsequent strings can contain other macros. ;; in those strings will be split into separate commands.

Here is an trivial example. The below creates a macro called l= which is the same thing as list .:

macro l= lambda: 'list .'

A simple text to text substitution of one command was all that was needed here. But usually you will want to run several commands. So those have to be wrapped up into a list.

The below creates a macro called fin+ which issues two commands finish followed by step:

macro fin+ lambda: ['finish','step']

If you wanted to parameterize the argument of the finish command you could do that this way:

macro fin+ lambda levels: ['finish %s' % levels ,'step']

Invoking with:

fin+ 3

would expand to: ['finish 3', 'step']

If you were to add another parameter for step, the note that the invocation might be:

fin+ 3 2

rather than fin+(3,2) or fin+ 3, 2.

See also alias, and info macro.

setautoeval [on|off]

Evaluate unrecognized debugger commands.

Often inside the debugger, one would like to be able to run arbitrary Python commands without having to preface Python expressions with print or eval. Setting autoeval on will cause unrecognized debugger commands to be eval'd as a Python expression.

Note that if this is set, on error the message shown on type a bad debugger command changes from:

Undefined command: "fdafds". Try "help".

to something more Python-eval-specific such as:

NameError: name 'fdafds' is not defined

One other thing that trips people up is when setting autoeval is that there are some short debugger commands that sometimes one wants to use as a variable, such as in an assignment statement. For example:

s = 5

which produces when autoeval is on:

Command 'step' can take at most 1 argument(s); got 2.

because by default, s is an alias for the debugger step command. It is possible to remove that alias if this causes constant problem.

setautolist [on|off]

Run the list command every time you stop in the debugger. With this, you will get output like:

-> 1 from subprocess import Popen, PIPE
(trepan2) next
(/users/fbicknel/Projects/disk_setup/sqlplus.py:2): <module>
-- 2 import os
1 from subprocess import Popen, PIPE
2 -> import os
3 import re
4
5 class SqlPlusExecutor(object):
6 def __init__(self, connection_string='/ as sysdba', sid=None):
7 self.__connection_string = connection_string
8 self.session = None
9 self.stdout = None
10 self.stderr = None
(trepan2) next
(/users/fbicknel/Projects/disk_setup/sqlplus.py:3): <module>
-- 3 import re
1 from subprocess import Popen, PIPE
2 import os
3 -> import re
4
5 class SqlPlusExecutor(object):
6 def __init__(self, connection_string='/ as sysdba', sid=None):
7 self.__connection_string = connection_string
8 self.session = None
9 self.stdout = None
10 self.stderr = None
(trepan2)

You may also want to put this this in your debugger startup file. See [#Startup_Profile]

python [-d]

Run Python as a command subshell. The sys.ps1 prompt will be set to trepan2 >>>.

If -d is passed, you can access debugger state via local variable debugger.

To issue a debugger command use function dbgr(). For example:

dbgr('info program')

Set consecutive stops must be on different file/line positions.

By default, the debugger traces all events possible including line, exceptions, call and return events. Just this alone may mean that for any given source line several consecutive stops at a given line may occur. Independent of this, Python allows one to put several commands in a single source line of code. When a programmer does this, it might be because the programmer thinks of the line as one unit.

One of the challenges of debugging is getting the granualarity of stepping comfortable. Because of the above, stepping all events can often be too fine-grained and annoying. By setting different on you can set a more coarse-level of stepping which often still is small enough that you won't miss anything important.

Note that the 'step' and 'next' debugger commands have '+' and '-' suffixes if you wan to override this setting on a per-command basis.

See also set trace to change what events you want to filter.

disassemble [thing] [start-line [end-line]]

With no argument, disassemble the current frame. With an integer start-line, the disassembly is narrowed to show lines starting at that line number or later; with an end-line number, disassembly stops when the next line would be greater than that or the end of the code is hit.

If start-line or end-line is., +, or -, the current line number is used. If instead it starts with a plus or minus prefix to a number, then the line number is relative to the current frame number.

With a class, method, function, pyc-file, code or string argument disassemble that.

Examples:

disassemble # Possibly lots of stuff dissassembled
disassemble . # Disassemble lines starting at current stopping point.
disassemble + # Same as above
disassemble +0 # Same as above
disassemble os.path # Disassemble all of os.path
disassemble os.path.normcase # Disaassemble just method os.path.normcase
disassemble -3 # Disassemble subtracting 3 from the current line number
disassemble +3 # Disassemble adding 3 from the current line number
disassemble 3 # Disassemble starting from line 3
disassemble 3 10 # Disassemble lines 3 to 10
disassemble myprog.pyc # Disassemble file myprog.pyc

Clone this wiki locally

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
rocky edited this page Jun 2, 2015 · 1 revision

Until a more detailed guide is written, we'll give an overview of trepan2 here. You can find where we're going by comparing with the manuals for pydb and ruby-debug.

The help system has been reworked from pydb and pdb and it is more extensive now. Play around with it. Starting with a plain help

(trepan2) helpClasses of commands:breakpoints -- Making the program stop at certain pointsdata -- Examining data...(trepan2) help breakpointsList of commands:break -- Set breakpoint at specified line or functioncondition -- Specify breakpoint number N ......(trepan2) help *List of all debugger commands: break enable ipython python source condition examine jump quit step ...

You can set the line width to use in displaying the help output using the command: set width. To see the current line width, initially taken from the COLUMNS environment variable, type: show width.

The list command will show you your source code.

(trepan2) list21#!/usr/bin/python2"""Greatest Common Divisor 3 4 Some characterstics of this program used for testing check_args() does 5 not have a 'return' statement. 6 7 check_args() raises an uncaught exception when given the wrong number 8 of parameters. 9 10 -> """
(trepan2) list# keep going11importsys1213defcheck_args():
14iflen(sys.argv) !=3:
15# Rather than use sys.exit let's just raise an error16raiseException, "Need to give two numbers"17foriinrange(2):
18try:
19sys.argv[i+1] =int(sys.argv[i+1])
20exceptValueError:
(trepan2) importos.path# Assumes set autoeval on
(trepan2) listos.path1111"""Common operations on Posix pathnames. 2 3 Instead of importing this module directly, import os and refer to 4 this module as os.path. The "os.path" name is an alias for this 5 module on Posix systems; on other systems (e.g. Mac, Windows), 6 os.path provides the same operations in a manner specific to that 7 platform, and is an alias to another module (e.g. macpath, ntpath). 8 9 Some of this can actually be useful on non-Posix systems too, e.g. 10 for manipulation of the pathname component of URLs. 11 """
(trepan2) listos.path.join5152# Join pathnames.53# Ignore the previous parts if a part is absolute.54# Insert a '/' unless the first part is empty or already ends in '/'.5556defjoin(a, *p):
57"""Join two or more pathname components, inserting '/' as needed"""58path=a59forbinp:
60ifb.startswith('/'):
(trepan2) remember_this_line=17
(trepan2) listremember_this_line1213defcheck_args():
14iflen(sys.argv) !=3:
15# Rather than use sys.exit let's just raise an error16raiseException, "Need to give two numbers"17foriinrange(2):
18try:
19sys.argv[i+1] =int(sys.argv[i+1])
20exceptValueError:
21print"** Expecting an integer, got: %s"%repr(sys.argv[i])
(trepan2)

There are many more options and possibilities so check out help list for details. If you are not using trepan2 via some sort of front-end program (e.g. I generally use my GNU Emacs front-end. Also see [#Set_Auto_List] below.

Here's a sample session using these commands:

(trepan2) setbasename# Short filenames in display
(trepan2) settrace# Show the events
(trepan2) step4line-gcd.py:13line-gcd.py:26line-gcd.py:40line-gcd.py:41
(gcd.py:41): <module>--41check_args()
(trepan2) s# 's' is an abbreviation for stepcall-gcd.py:13
(gcd.py:13): check_args->13defcheck_args():
(trepan2) step<# Step until the next returnline-gcd.py:14line-gcd.py:17line-gcd.py:18line-gcd.py:19line-gcd.py:17line-gcd.py:18line-gcd.py:19line-gcd.py:17return-gcd.py:17
(gcd.py:17): check_args<-17foriinrange(2):
(trepan2) settraceoff# That's enough tracing
(trepan2) next# like step but skips over function calls
(gcd.py:43): <module>--43 (a, b) =sys.argv[1:3]
(trepan2) # A carriage-return or empty command runs the last step/next
(gcd.py:44): <module>--44print"The GCD of %d and %d is %d"% (a, b, gcd(a, b))
(trepan2) s<# step until the next call
(gcd.py:26): gcd->26defgcd(a,b):
(trepan2) finish# run until return of *this* function; compare with s<
(gcd.py:38): gcd<-38returngcd(b-a, a)
(trepan2) retval# show the return value1
(trepan2)

In this section we describe cool commands not generally found in other Python debuggers that you may want to experiment with.

In addition to the sub-commands that we describe in more detail, also look at:

  • set autopython -- go into python automatically on every stop
  • set trace -- turn on/off event tracing
  • info threads -- show list of threads and where they are

Also check out the set, show, and info commands in general.

aliasalias-namedebugger-command

Add alias alias-name for a debugger command debugger-comand.

Add an alias when you want to use a command abbreviation for a command that would otherwise be ambigous. For example, by default we make s be an alias of step to force it to be used. Without the alias, s might be step, show, or set among others

Example:

alias cat list # "cat myprog.py" is the same as "list myprog.py"
alias s step # "s" is now an alias for "step".
# The above example is done by default.

See also unalias and show alias.

unaliasalias-name

Remove alias alias-name.

See also alias.

macromacro-namelambda-object

Define macro-name as a debugger macro. Debugger macros get a list of arguments which you supply without parenthesis or commas. See below for an example.

The macro (really a Python lambda) should return either a String or an List of Strings. The string in both cases is a debugger command. Each string gets tokenized by a simple split() . Note that macro processing is done right after splitting on ;;. As a result, if the macro returns a string containing ;; this will not be interpreted as separating debugger commands.

If a list of strings is returned, then the first string is shifted from the list and executed. The remaining strings are pushed onto the command queue. In contrast to the first string, subsequent strings can contain other macros. ;; in those strings will be split into separate commands.

Here is an trivial example. The below creates a macro called l= which is the same thing as list .:

macro l= lambda: 'list .'

A simple text to text substitution of one command was all that was needed here. But usually you will want to run several commands. So those have to be wrapped up into a list.

The below creates a macro called fin+ which issues two commands finish followed by step:

macro fin+ lambda: ['finish','step']

If you wanted to parameterize the argument of the finish command you could do that this way:

macro fin+ lambda levels: ['finish %s' % levels ,'step']

Invoking with:

fin+ 3

would expand to: ['finish 3', 'step']

If you were to add another parameter for step, the note that the invocation might be:

fin+ 3 2

rather than fin+(3,2) or fin+ 3, 2.

See also alias, and info macro.

setautoeval [on|off]

Evaluate unrecognized debugger commands.

Often inside the debugger, one would like to be able to run arbitrary Python commands without having to preface Python expressions with print or eval. Setting autoeval on will cause unrecognized debugger commands to be eval'd as a Python expression.

Note that if this is set, on error the message shown on type a bad debugger command changes from:

Undefined command: "fdafds". Try "help".

to something more Python-eval-specific such as:

NameError: name 'fdafds' is not defined

One other thing that trips people up is when setting autoeval is that there are some short debugger commands that sometimes one wants to use as a variable, such as in an assignment statement. For example:

s = 5

which produces when autoeval is on:

Command 'step' can take at most 1 argument(s); got 2.

because by default, s is an alias for the debugger step command. It is possible to remove that alias if this causes constant problem.

setautolist [on|off]

Run the list command every time you stop in the debugger. With this, you will get output like:

-> 1 from subprocess import Popen, PIPE
(trepan2) next
(/users/fbicknel/Projects/disk_setup/sqlplus.py:2): <module>
-- 2 import os
1 from subprocess import Popen, PIPE
2 -> import os
3 import re
4
5 class SqlPlusExecutor(object):
6 def __init__(self, connection_string='/ as sysdba', sid=None):
7 self.__connection_string = connection_string
8 self.session = None
9 self.stdout = None
10 self.stderr = None
(trepan2) next
(/users/fbicknel/Projects/disk_setup/sqlplus.py:3): <module>
-- 3 import re
1 from subprocess import Popen, PIPE
2 import os
3 -> import re
4
5 class SqlPlusExecutor(object):
6 def __init__(self, connection_string='/ as sysdba', sid=None):
7 self.__connection_string = connection_string
8 self.session = None
9 self.stdout = None
10 self.stderr = None
(trepan2)

You may also want to put this this in your debugger startup file. See [#Startup_Profile]

python [-d]

Run Python as a command subshell. The sys.ps1 prompt will be set to trepan2 >>>.

If -d is passed, you can access debugger state via local variable debugger.

To issue a debugger command use function dbgr(). For example:

dbgr('info program')

Set consecutive stops must be on different file/line positions.

By default, the debugger traces all events possible including line, exceptions, call and return events. Just this alone may mean that for any given source line several consecutive stops at a given line may occur. Independent of this, Python allows one to put several commands in a single source line of code. When a programmer does this, it might be because the programmer thinks of the line as one unit.

One of the challenges of debugging is getting the granualarity of stepping comfortable. Because of the above, stepping all events can often be too fine-grained and annoying. By setting different on you can set a more coarse-level of stepping which often still is small enough that you won't miss anything important.

Note that the 'step' and 'next' debugger commands have '+' and '-' suffixes if you wan to override this setting on a per-command basis.

See also set trace to change what events you want to filter.

disassemble [thing] [start-line [end-line]]

With no argument, disassemble the current frame. With an integer start-line, the disassembly is narrowed to show lines starting at that line number or later; with an end-line number, disassembly stops when the next line would be greater than that or the end of the code is hit.

If start-line or end-line is., +, or -, the current line number is used. If instead it starts with a plus or minus prefix to a number, then the line number is relative to the current frame number.

With a class, method, function, pyc-file, code or string argument disassemble that.

Examples:

disassemble # Possibly lots of stuff dissassembled
disassemble . # Disassemble lines starting at current stopping point.
disassemble + # Same as above
disassemble +0 # Same as above
disassemble os.path # Disassemble all of os.path
disassemble os.path.normcase # Disaassemble just method os.path.normcase
disassemble -3 # Disassemble subtracting 3 from the current line number
disassemble +3 # Disassemble adding 3 from the current line number
disassemble 3 # Disassemble starting from line 3
disassemble 3 10 # Disassemble lines 3 to 10
disassemble myprog.pyc # Disassemble file myprog.pyc

Clone this wiki locally

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content
rocky edited this page Jun 2, 2015 · 1 revision

Until a more detailed guide is written, we'll give an overview of trepan2 here. You can find where we're going by comparing with the manuals for pydb and ruby-debug.

The help system has been reworked from pydb and pdb and it is more extensive now. Play around with it. Starting with a plain help

(trepan2) helpClasses of commands:breakpoints -- Making the program stop at certain pointsdata -- Examining data...(trepan2) help breakpointsList of commands:break -- Set breakpoint at specified line or functioncondition -- Specify breakpoint number N ......(trepan2) help *List of all debugger commands: break enable ipython python source condition examine jump quit step ...

You can set the line width to use in displaying the help output using the command: set width. To see the current line width, initially taken from the COLUMNS environment variable, type: show width.

The list command will show you your source code.

(trepan2) list21#!/usr/bin/python2"""Greatest Common Divisor 3 4 Some characterstics of this program used for testing check_args() does 5 not have a 'return' statement. 6 7 check_args() raises an uncaught exception when given the wrong number 8 of parameters. 9 10 -> """
(trepan2) list# keep going11importsys1213defcheck_args():
14iflen(sys.argv) !=3:
15# Rather than use sys.exit let's just raise an error16raiseException, "Need to give two numbers"17foriinrange(2):
18try:
19sys.argv[i+1] =int(sys.argv[i+1])
20exceptValueError:
(trepan2) importos.path# Assumes set autoeval on
(trepan2) listos.path1111"""Common operations on Posix pathnames. 2 3 Instead of importing this module directly, import os and refer to 4 this module as os.path. The "os.path" name is an alias for this 5 module on Posix systems; on other systems (e.g. Mac, Windows), 6 os.path provides the same operations in a manner specific to that 7 platform, and is an alias to another module (e.g. macpath, ntpath). 8 9 Some of this can actually be useful on non-Posix systems too, e.g. 10 for manipulation of the pathname component of URLs. 11 """
(trepan2) listos.path.join5152# Join pathnames.53# Ignore the previous parts if a part is absolute.54# Insert a '/' unless the first part is empty or already ends in '/'.5556defjoin(a, *p):
57"""Join two or more pathname components, inserting '/' as needed"""58path=a59forbinp:
60ifb.startswith('/'):
(trepan2) remember_this_line=17
(trepan2) listremember_this_line1213defcheck_args():
14iflen(sys.argv) !=3:
15# Rather than use sys.exit let's just raise an error16raiseException, "Need to give two numbers"17foriinrange(2):
18try:
19sys.argv[i+1] =int(sys.argv[i+1])
20exceptValueError:
21print"** Expecting an integer, got: %s"%repr(sys.argv[i])
(trepan2)

There are many more options and possibilities so check out help list for details. If you are not using trepan2 via some sort of front-end program (e.g. I generally use my GNU Emacs front-end. Also see [#Set_Auto_List] below.

Here's a sample session using these commands:

(trepan2) setbasename# Short filenames in display
(trepan2) settrace# Show the events
(trepan2) step4line-gcd.py:13line-gcd.py:26line-gcd.py:40line-gcd.py:41
(gcd.py:41): <module>--41check_args()
(trepan2) s# 's' is an abbreviation for stepcall-gcd.py:13
(gcd.py:13): check_args->13defcheck_args():
(trepan2) step<# Step until the next returnline-gcd.py:14line-gcd.py:17line-gcd.py:18line-gcd.py:19line-gcd.py:17line-gcd.py:18line-gcd.py:19line-gcd.py:17return-gcd.py:17
(gcd.py:17): check_args<-17foriinrange(2):
(trepan2) settraceoff# That's enough tracing
(trepan2) next# like step but skips over function calls
(gcd.py:43): <module>--43 (a, b) =sys.argv[1:3]
(trepan2) # A carriage-return or empty command runs the last step/next
(gcd.py:44): <module>--44print"The GCD of %d and %d is %d"% (a, b, gcd(a, b))
(trepan2) s<# step until the next call
(gcd.py:26): gcd->26defgcd(a,b):
(trepan2) finish# run until return of *this* function; compare with s<
(gcd.py:38): gcd<-38returngcd(b-a, a)
(trepan2) retval# show the return value1
(trepan2)

In this section we describe cool commands not generally found in other Python debuggers that you may want to experiment with.

In addition to the sub-commands that we describe in more detail, also look at:

  • set autopython -- go into python automatically on every stop
  • set trace -- turn on/off event tracing
  • info threads -- show list of threads and where they are

Also check out the set, show, and info commands in general.

aliasalias-namedebugger-command

Add alias alias-name for a debugger command debugger-comand.

Add an alias when you want to use a command abbreviation for a command that would otherwise be ambigous. For example, by default we make s be an alias of step to force it to be used. Without the alias, s might be step, show, or set among others

Example:

alias cat list # "cat myprog.py" is the same as "list myprog.py"
alias s step # "s" is now an alias for "step".
# The above example is done by default.

See also unalias and show alias.

unaliasalias-name

Remove alias alias-name.

See also alias.

macromacro-namelambda-object

Define macro-name as a debugger macro. Debugger macros get a list of arguments which you supply without parenthesis or commas. See below for an example.

The macro (really a Python lambda) should return either a String or an List of Strings. The string in both cases is a debugger command. Each string gets tokenized by a simple split() . Note that macro processing is done right after splitting on ;;. As a result, if the macro returns a string containing ;; this will not be interpreted as separating debugger commands.

If a list of strings is returned, then the first string is shifted from the list and executed. The remaining strings are pushed onto the command queue. In contrast to the first string, subsequent strings can contain other macros. ;; in those strings will be split into separate commands.

Here is an trivial example. The below creates a macro called l= which is the same thing as list .:

macro l= lambda: 'list .'

A simple text to text substitution of one command was all that was needed here. But usually you will want to run several commands. So those have to be wrapped up into a list.

The below creates a macro called fin+ which issues two commands finish followed by step:

macro fin+ lambda: ['finish','step']

If you wanted to parameterize the argument of the finish command you could do that this way:

macro fin+ lambda levels: ['finish %s' % levels ,'step']

Invoking with:

fin+ 3

would expand to: ['finish 3', 'step']

If you were to add another parameter for step, the note that the invocation might be:

fin+ 3 2

rather than fin+(3,2) or fin+ 3, 2.

See also alias, and info macro.

setautoeval [on|off]

Evaluate unrecognized debugger commands.

Often inside the debugger, one would like to be able to run arbitrary Python commands without having to preface Python expressions with print or eval. Setting autoeval on will cause unrecognized debugger commands to be eval'd as a Python expression.

Note that if this is set, on error the message shown on type a bad debugger command changes from:

Undefined command: "fdafds". Try "help".

to something more Python-eval-specific such as:

NameError: name 'fdafds' is not defined

One other thing that trips people up is when setting autoeval is that there are some short debugger commands that sometimes one wants to use as a variable, such as in an assignment statement. For example:

s = 5

which produces when autoeval is on:

Command 'step' can take at most 1 argument(s); got 2.

because by default, s is an alias for the debugger step command. It is possible to remove that alias if this causes constant problem.

setautolist [on|off]

Run the list command every time you stop in the debugger. With this, you will get output like:

-> 1 from subprocess import Popen, PIPE
(trepan2) next
(/users/fbicknel/Projects/disk_setup/sqlplus.py:2): <module>
-- 2 import os
1 from subprocess import Popen, PIPE
2 -> import os
3 import re
4
5 class SqlPlusExecutor(object):
6 def __init__(self, connection_string='/ as sysdba', sid=None):
7 self.__connection_string = connection_string
8 self.session = None
9 self.stdout = None
10 self.stderr = None
(trepan2) next
(/users/fbicknel/Projects/disk_setup/sqlplus.py:3): <module>
-- 3 import re
1 from subprocess import Popen, PIPE
2 import os
3 -> import re
4
5 class SqlPlusExecutor(object):
6 def __init__(self, connection_string='/ as sysdba', sid=None):
7 self.__connection_string = connection_string
8 self.session = None
9 self.stdout = None
10 self.stderr = None
(trepan2)

You may also want to put this this in your debugger startup file. See [#Startup_Profile]

python [-d]

Run Python as a command subshell. The sys.ps1 prompt will be set to trepan2 >>>.

If -d is passed, you can access debugger state via local variable debugger.

To issue a debugger command use function dbgr(). For example:

dbgr('info program')

Set consecutive stops must be on different file/line positions.

By default, the debugger traces all events possible including line, exceptions, call and return events. Just this alone may mean that for any given source line several consecutive stops at a given line may occur. Independent of this, Python allows one to put several commands in a single source line of code. When a programmer does this, it might be because the programmer thinks of the line as one unit.

One of the challenges of debugging is getting the granualarity of stepping comfortable. Because of the above, stepping all events can often be too fine-grained and annoying. By setting different on you can set a more coarse-level of stepping which often still is small enough that you won't miss anything important.

Note that the 'step' and 'next' debugger commands have '+' and '-' suffixes if you wan to override this setting on a per-command basis.

See also set trace to change what events you want to filter.

disassemble [thing] [start-line [end-line]]

With no argument, disassemble the current frame. With an integer start-line, the disassembly is narrowed to show lines starting at that line number or later; with an end-line number, disassembly stops when the next line would be greater than that or the end of the code is hit.

If start-line or end-line is., +, or -, the current line number is used. If instead it starts with a plus or minus prefix to a number, then the line number is relative to the current frame number.

With a class, method, function, pyc-file, code or string argument disassemble that.

Examples:

disassemble # Possibly lots of stuff dissassembled
disassemble . # Disassemble lines starting at current stopping point.
disassemble + # Same as above
disassemble +0 # Same as above
disassemble os.path # Disassemble all of os.path
disassemble os.path.normcase # Disaassemble just method os.path.normcase
disassemble -3 # Disassemble subtracting 3 from the current line number
disassemble +3 # Disassemble adding 3 from the current line number
disassemble 3 # Disassemble starting from line 3
disassemble 3 10 # Disassemble lines 3 to 10
disassemble myprog.pyc # Disassemble file myprog.pyc

Clone this wiki locally