PythonProgrammingInEmacs

Last edit

Changed:

< * [https://github.com/burakbayramli/kod/blob/master/site-lisp/pytexipy-notebook.py pytexipy], an Emacs extension that allows execution of notebook python code inside a TeX buffer and display its results, text or graphic in the section below. The extension uses Pymacs to connect to a ipython kernel to execute code.

to

> * [https://github.com/burakbayramli/emacs-ipython emacs-ipython], an Emacs extension that allows execution of python code inside a TeX buffer and display its results, text or graphic in the section below. The extension uses Pymacs to connect to a ipython kernel to execute code.


This page collects information for creating a usable Python programming environment in Emacs.

Python Modes

There are a number of Python modes for Emacs. The major ones are python.el which comes with Emacs 24.2 and up and python-mode.el, which is the most comprehensive; it integrated most of the stuff discussed below. The older python.el from Emacs 24.1 and before has a number of fans as well.

Emacs as a Python IDE

Beyond the basic Python modes described above, there are a number of modes that support Python programming.

Other Support Modes

Video from EuroPython? 2013 displays how to setup a complete IDE employing a few lines of code: https://ep2013.europython.eu/conference/p/andrea-crotti resp. http://www.youtube.com/watch?v=0cZ7szFuz18

Various Python Interpreters

IPython

python-mode.el comes with IPython support, setup as shown below has been integrated.

First try to use ipython.el, maybe by simply invoking :

(setq ipython-command "/SOME-PATH/ipython") ; discard this line Ipython is already in your PATH
(require 'ipython)

Recipes below should be tried only if this fails

ipython.el looks like it’s deprecated. It no longer comes with the IPython distribution. --ybendana

Emacs’ 24.2+ python.el contains the following guide on how to set it up to use IPython 0.11:

(setq
 python-shell-interpreter "ipython"
 python-shell-interpreter-args ""
 python-shell-prompt-regexp "In \\[[0-9]+\\]: "
 python-shell-prompt-output-regexp "Out\\[[0-9]+\\]: "
 python-shell-completion-setup-code
   "from IPython.core.completerlib import module_completion"
 python-shell-completion-module-string-code
   "';'.join(module_completion('''%s'''))\n"
 python-shell-completion-string-code
   "';'.join(get_ipython().Completer.all_completions('''%s'''))\n")

For iPython 0.10 everything would be the same except for `python-shell-completion-string-code` and `python-shell-completion-module-string-code`:

(setq python-shell-completion-string-code
      "';'.join(__IP.complete('''%s'''))\n"
      python-shell-completion-module-string-code "")

Unfortunately running iPython on Windows needs some more tweaking. The way you must set `python-shell-interpreter` and `python-shell-interpreter-args` is as follows:

(setq
 python-shell-interpreter "C:\\Python27\\python.exe"
 python-shell-interpreter-args
 "-i C:\\Python27\\Scripts\\ipython-script.py")

That will spawn the iPython process correctly (Of course you need to modify the paths according to your system).

IronPython

Further Reading

Various Configuration Tips

Comment/Uncomment Region

If you have ‘transient-mark-mode’ on, you can just use ‘comment-dwim’: select a region and hit `M-;’. The DoWhatIMean means that it will comment or uncomment the region as appropriate. If you do not have ‘transient-mark-mode’ on by default, you can hit C-SPC twice to activate it temporarily.

( doesn’t python-mode.el offer `py-comment-region? --CH )

Beside py-comment-region python-mode.el provides commands to comment/uncomment all known forms, def, block, clause etc.

Browse the Python Documentation using Info

To browse the new Python documentation using Info, you will need the necessary Info files. These files are not currently available from the official download site since they are generated by a development version of Sphinx, the documentation system used by Python. You can however download a copy of the documentation for

These Info files are different than the ones generated from the old Python documentation (prior to python 2.5) which were not built by Sphinx. One result of these differences is that ‘info-lookup-symbol’ (C-h S) will not work correctly in ‘python-mode’ since the InfoLook support in “python.el” is based on the old version. To fix this issue, you can add the following code to your .emacs:

(require 'info-look)

(info-lookup-add-help
 :mode 'python-mode
 :regexp "[[:alnum:]_]+"
 :doc-spec
 '(("(python)Index" nil "")))

An alternative method for fixing ‘info-lookup-symbol’ support is provided by the pydoc-info package.

Using Flymake with Python

Using flymake with multiple lint, style and syntax checkers

More than one code checking tool can be applied in flymake by using a wrapper script that runs the desired tools and combines their output. It has lots of issues, one being that flymake does not seem to show more than one error message per line of code, meaning that an error or warning which is intentionally left unfixed can mask an error or warning that would get more attention.

Additionally, the scripts that check python code are either rather anemic, and don’t notice too much (pychecker) or are aggressive, and warn about all sorts of things that they should not (pylint). pep8.py tends to be annoyingly aggressive about whitespace.

There are several scripts around to do this, supporting various tools. Each expects to find the code checking tools in your path (pep8.py, pychecker, pylint, pyflakes, etc). Additionally this script attempts to support virtual environments, but this is largely untested.

I added this code to pastebins (didn’t know which to prefer, so chose three) which should be better than dumping the code here. – Chris2048

Flycheck integrates flake8 and pylint. --ybendana

Using flymake with pylint

Please note that pylint now comes with an executable “epylint” that is meant to be the interface to Emacs.

The flymake mode in Emacs 22 does not understand Python, but it can be made to work with pylint. To do this, first you’ll need to create a script somewhere along your PATH called ‘epylint’. That script is here

more pastebins needed? – Chris2048

It might appear that for some combinations of flymake, pylint and epylint the above script might not work properly (it didn’t for me). Debugging showed that the regexp wasn’t matching the output of pylint, ever, so the lines were being printed from pylint verbatim, meaning that flymake was doing a “best effort” match, and everything was coming up as an error, even minor warnings.

Here is an alternative version of the epylint script that works great for me. It doesn’t throw away all the R and C errors, just the most annoying ones. You can easily modify it to include or exclude messages to your preference. I find it easier to have the messages in the script rather than messing about with .pylintrc and the like.

(I’ve also got a version that inserts the overall code quality metric, as determined by pylint, so you can see at a glance how close you are to pylint perfection; holler here if you want to see it).

that would be useful holler --Chris2048

Once you test that this works on sample Python files, then add the following to your InitFile to enable flymake checking of Python scripts using pylint:

    (when (load "flymake" t)
      (defun flymake-pylint-init ()
        (let* ((temp-file (flymake-init-create-temp-buffer-copy
                           'flymake-create-temp-inplace))
           (local-file (file-relative-name
                        temp-file
                        (file-name-directory buffer-file-name))))
          (list "epylint" (list local-file))))
      (add-to-list 'flymake-allowed-file-name-masks
               '("\\.py\\'" flymake-pylint-init)))

Now if you turn on ‘flymake-mode’ inside a Python file, you should see lines with warnings highlighted in blue, and lines with errors highlighted in red. Just hover your mouse over either type of line for a few seconds and you’ll see a tooltip describing the error/warning. Plus, the modeline will show you two numbers, X/Y, where X is the number of errors in your script, and Y is the total number of warnings. – JohnWiegley

wait, this is for XEmacs, right? – Chris2048

You can customise the way flymake highlights your Python by running ‘M-x customize-face’ on ‘flymake-errline’ or ‘flymake-warnline’. For example, you can remove the background highlight and make the face be just a subtle coloured underline.

Using flymake with pyflakes

Found a desciption on how to use this pair at www.plope.com/Members/chrism/flymake-mode I did a copy ‘n paste for simplicity.

(when (load "flymake" t)
  (defun flymake-pyflakes-init ()
     ; Make sure it's not a remote buffer or flymake would not work
     (when (not (subsetp (list (current-buffer)) (tramp-list-remote-buffers)))
      (let* ((temp-file (flymake-init-create-temp-buffer-copy
                         'flymake-create-temp-inplace))
             (local-file (file-relative-name
                          temp-file
                          (file-name-directory buffer-file-name))))
        (list "pyflakes" (list local-file)))))
  (add-to-list 'flymake-allowed-file-name-masks
               '("\\.py\\'" flymake-pyflakes-init)))

The normal operation of flymake allows the user to see the error message for a particular line by “hovering” the mouse over the line. This is inconvenient for people who try to use the keyboard for all input. FlymakeCursor was designed to address that: it displays the flymake error in the minibuffer region, when the cursor is placed on a line containing a flymake error.

Using flymake with pyflakes on Windows

Download the pyflakes tgz file from Pypi. Unpack it, then run the setup:

\Python27\python.exe \temp\\temp\pyflakes-0.5.0\setup.py install

This will install pyflakes.

To run pyflakes from a command prompt, you then need something like this:

\Python27\python.exe \Python27\Scripts\pyflakes myfile.py

To make it simpler, you can create a file called pyflakes.cmd and put it into c:\python27 . The contents should be:

@echo off
goto START
-------------------------------------------------------
 pyflakes.cmd
-------------------------------------------------------
:START
SETLOCAL
if  _%1==_ goto USAGE
%~dp0\python.exe %~dp0\Scripts\pyflakes %*
goto ALL_DONE

:USAGE
  echo usage:  pyflakes ^<file^> [^<optionalargs^>]
  echo run the pyflakes syntax checker on a python source file.

:ALL_DONE
ENDLOCAL

Then, modify one line in the elisp snip given above, to be like this:

(when (load "flymake" t)
  (defun flymake-pyflakes-init ()
     ; Make sure it's not a remote buffer or flymake would not work
     (when (not (subsetp (list (current-buffer)) (tramp-list-remote-buffers)))
      (let* ((temp-file (flymake-init-create-temp-buffer-copy
                         'flymake-create-temp-inplace))
             (local-file (file-relative-name
                          temp-file
                          (file-name-directory buffer-file-name))))
        (list "c:\\Python27\\pyflakes.cmd" (list local-file)))))
  (add-to-list 'flymake-allowed-file-name-masks
               '("\\.py\\'" flymake-pyflakes-init)))

Also see PyIndent

IPython debugging/pdbtrack

I made the following changes to python-mode.el to make debugging work again with current IPython (0.9.1):

[…]

 ;; pdbtrack constants
 (defconst py-pdbtrack-stack-entry-regexp
  "^> \\(.*\\)(\\([0-9]+\\))\\([?a-zA-Z0-9_<>]+\\)()"; this is new
 ;  "^> \\([^(]+\\)(\\([0-9]+\\))\\([?a-zA-Z0-9_]+\\)()"
 ;  "^> \\(.*\\)(\\([0-9]+\\))\\([?a-zA-Z0-9_]+\\)()"
   "Regular expression pdbtrack uses to find a stack trace entry.")
 ;(defconst py-pdbtrack-input-prompt "\n[(<]*[Pp]db[>)]+ "
 (defconst py-pdbtrack-input-prompt "\n[(<]*[Ii]?[Pp]db[>)]+ "; this is new
   "Regular expression pdbtrack uses to recognize a pdb prompt.")

[…]

            (py-pdbtrack-overlay-arrow nil)
          (setq block (ansi-color-filter-apply block)) ; this is new
          (setq target (py-pdbtrack-get-source-buffer block))

[…]

Now when I debug in the IPython console (using %run -d, or %pdb on, etc.) pdbtrack makes sure to show me the current source code and corresponding line. Note that these changes may break debugging in a standard python-shell, I have not tested this.

Using PythonTidy to pretty-print a buffer

PythonTidy can be used to pretty-print a buffer in combination with shell-command-on-region. Installing PythonTidy? somewhere on the path, and add this to your .emacs

(defun pytidy-whole-buffer ()
  (interactive)
  (let ((a (point)))
    (shell-command-on-region (point-min) (point-max) "<Name_Of_Executable_Script>" t)
    (goto-char a)))

Note: <Name_Of_Executable_Script> should match the name of the pythonTidy script on your path, make sure you set execute permissions.

bind this to any key you wish, I have:

(define-key python-mode-map  (kbd "<f9>") 'pytidy-whole-buffer)

in my python-mode-hook. invoking the command pretty-prints the hole buffer, you can invoke undo if something went wrong, and the cursor stays put.

Unicode on Mac OS X

When using Emacs 24.1 on Mac OS X compiled via homebrew. The python-shell always used US-ASCII as encoding. To fix it I used:

(setenv "LC_CTYPE" "UTF-8")

To determine your encoding in the python-shell use:

>>> import sys; sys.stdout.encoding
'US-ASCII'

Not having the right encoding set leads to errors in ipython:

ERROR - failed to write data to stream: <_io.TextIOWrapper name='<stdout>' mode='w' encoding='US-ASCII'>

Shortcuts to automatically write commands

The code below adds some shortcuts to automatically write the frequently used python commands.

(define-key
  python-mode-map
  (kbd "C-c C-x l")
  (lambda () (interactive)  (insert "lambda ")))

(define-key
  python-mode-map
  (kbd "C-c C-x m")
  (lambda ()
    (interactive)
    (insert "map()")
    (backward-char) 1))

(define-key python-mode-map
  (kbd "C-c C-x r")
  (lambda ()
    (interactive)
    (insert "reduce()")
    (backward-char 1)))

(define-key python-mode-map
  (kbd "C-c C-x e")
  (lambda ()
    (interactive)
    (insert "return ")))

Categories: CategoryProgramming, ProgrammingModes