Overview

cpdb - pdb/ipdb speed up using c extension and set/unset breakpoints without code reload or restart.

What the what?

cpdb lets you load a modified pdb/ipdb early in your (long running) python program, and set break points during run time. It uses a c extension to minimize performance impact when the debugger is enabled. The debugger watches a file (~/.cpdb/breakpoints) for breakpoints, you can add breakpoints in this file using any method and the debugger will stop your program and drop to a ipdb prompt when it hits the specified line.

The break point file is in the format

<full filename>:<lineno>

Eg:

    #this is a comment
    /home/foo/pythonfu.py:15
    /home/foo/bar.py:10

you can use you favorite editor to insert breakpoints \o/.

There is no need to reload code or restart the app to set pdb break points. If there are no breakpoints specified in the file the debugger is disabled and there will be no performance impact, until the debugger is enabled again.

Works across threads created by the threading module.

How ?

Pdb basically hooks on sys.settrace to analyze each line being executed, running pdb on a large app, significantly slows it down. cpdb has a c-api extension method to use as the sys.settrace method which filters out lines on which there are no breakpoints set and calls the pdb dispatch only if there is a break point on the line.

Usage :

    from cpdb import Debugger
    Debugger().observe_breakpoints()

Emacs config :

    (defun clear-breakpoints nil
      (interactive)
      (write-region "" nil "~/.cpdb/breakpoints"))

    (defun remove-breakpoint nil
      (interactive)
      (let ((bpfile "~/.cpdb/breakpoints")
            (bpline (format "%s:%s" (buffer-file-name) (line-number-at-pos (point)))))
        (with-temp-buffer
          (insert-file-contents bpfile)
          (goto-char (point-min))
          (flush-lines bpline)
          (when (file-writable-p bpfile)
            (write-region (point-min) (point-max) bpfile)))))

    (defun add-breakpoint nil
      (interactive)
      (let ((bpfile "~/.cpdb/breakpoints")
            (bpline (format "%s:%s" (buffer-file-name) (line-number-at-pos (point)))))
        (with-temp-buffer
          (insert-file-contents bpfile)
          (goto-char (point-min))
          (flush-lines bpline)
          (insert bpline)
          (insert "\n")
          (sort-lines nil (point-min) (point-max))
          (when (file-writable-p bpfile)
            (write-region (point-min) (point-max) bpfile)))))

    (define-key global-map (kbd "<f8>" ) 'add-breakpoint)
    (define-key global-map (kbd "<f7>" ) 'remove-breakpoint)