Python Tricks

     Introduction
          Starting the Debugger Automatically After an Uncaught Exception
          Running pdb under emacs
          Emacs function to insert debugging print statements
          Runing PyChecker inside of Emacs

Introduction

Every once in a while I am reduced to figuring something out for my self with very little help from the documentation. So I will jot them down here in hopes of sparing someone else a bit of confusion. If you can think of a better way to do any of these things, please let me know. If I will probably add it here. If you have other suggestions,

Email: email me at [rozen at mcn dot org] *

* If you're wondering why the email address is written like this, it's because some vile people use
automated programs to read email addresses from web pages, then send spam to those email addresses.

Specifying the address in an unfamiliar form, and dynamically constructing the link via JavaScript,
makes it impossible for those programs to obtain the address. If you want to steal the code, please go right ahead.
I got this information from Mike Ridley http://www.matt-ridley.com.

Starting the Debugger Automatically After an Uncaught Exception

This came from "Python Cookbook". I found it so helpful that I am putting it here.

I added the following code to the python library member: /usr/local/python2.2/site-packages/sitecustomize.py

import sys

def info(type, value, tb):
    if hasattr(sys, 'ps1') or not sys.stderr.isatty():
        # You are in interactive mode or don't have a tty-like
        # device, so call the default hook
        sys.__execthook__(type, value, tb)
    else:
        import traceback, pdb
        # You are not in interactive mode; print the exception
        traceback.print_exception(type, value, tb)
        print
        # ... then star the debugger in post-mortem mode
        pdb.pm()


sys.excepthook = info

By doing this, when I run emacs or otherwise and hit an unhandled exception it puts me into the debugger so that I can run around the traceback and see what happened. Very helpful indeed.

Running pdb under emacs

This always intrigued me and so I spent the time to figure out a way for me to get it working. The steps are:

Emacs function to insert debugging print statements

These function can be found in pyp.el and can be added to your .emacs or you can put them in your load path and add

(load "pyp.el")
to your .emacs file.

The function, pyp, will go to the end of the current line and insert a new line containing "print 'function: expr =', expr". The expr is picked up from the minibuffer following the prompt.

; This is a function which simplifies the insertion of debugging
; print statements in a python program.

(defun pyp (expr)
  "Insert a print statement as the next statement of the program.
   Include the name of the enclosing function or and accept from
   the minibuffer the expresion to be printed. The form of the
   statement to be entered and indented is:
      print 'function: expr =', expr"
  (interactive "sExpression to be printed: ")
  (save-excursion
	(py-beginning-of-def-or-class)
	(re-search-forward "[ ]*def[ ]+\\(\\w+\\)\\W")
	(setq pyp-funct (buffer-substring (match-beginning 1) (match-end 1))))
  (end-of-line)
  (newline)
  (insert "print '" pyp-funct ": " expr " =', " expr)
  (indent-for-tab-command))

The emacs function, ppy, will go to the end of the current line and insert two new lines containing "print 'function: pretty printing variable '" and "pp.pprint(variable)". The variable is picked up from the minibuffer following the prompt.

(defun ppy (variable)
  "Insert statements following the next statements of the program which
   will pretty print the variable. Note that this is a variable and not
   an expression."
  (interactive "sVariable to be printed: ")
  (save-excursion
	(py-beginning-of-def-or-class)
	(re-search-forward "[ ]*def[ ]+\\(\\w+\\)\\W")
	(setq pyp-funct (buffer-substring (match-beginning 1) (match-end 1))))
  (end-of-line)
  (newline)
  (insert "print '" pyp-funct ": pretty printing " variable "'")
  (indent-for-tab-command)
  (newline)
  (insert "pp.pprint(" variable ")")
  (indent-for-tab-command)
)

For the previous function, ppy, to generate working code it is necessary to have the proper import statements at the top of the module. To get them, go to a correct spot and execute the following function.

(defun ppyi ()
  "Insert the code necessary to import pprint and create the necessary
   PrettyPrinter object at the current point."
  (interactive)
  (newline)
  (insert "import pprint")
  (indent-for-tab-command)
  (newline)
  (insert "pp = pprint.PrettyPrinter()")
  (indent-for-tab-command)
)

Runing PyChecker inside of Emacs

I really like PyChecker. So I fussed around until I was able to run the program under Emacs. The following code added to my .emacs did the trick. It will run PyChecker against the file behind the current buffer. It will also check if you want unsaved files saved. Warning from PyChecker are displayed in a buffer and you can use that buffer like a compile buffer to find corresponding lines in the source file. The emacs command is 'pychecker'. Suggestions welcome, especially if they come with code.

I know that a new version of python-mode.el will contain support for PyChecker; however, I was not able to get it to work with GNU emacs 21.2.1.

(setq pychecker-regexp-alist
  '(("\\([a-zA-Z]?:?[^:(\t\n]+\\)[:( \t]+\\([0-9]+\\)[:) \t]" 1 2)))
;;;###autoload
(defun pychecker ()
  "Run pychecker against the file behind the current buffer after
  checking if unsaved buffers should be saved."

  (interactive)
  (let* ((file (buffer-file-name (current-buffer)))
		 (command (concat "pychecker " file)))
		 (save-some-buffers (not compilation-ask-about-save) nil) ; save  files.
		 (compile-internal command "No more errors or warnings" "pychecker"
						   nil pychecker-regexp-alist)))

PAGE Home