IDE Features


Elpy supports the notion of projects, a related collection of files under a common directory. This common directory is called the project root. A number of Elpy’s commands work on all files inside the project root.

C-c C-f (elpy-find-file)

Find a file in the current project. This uses a search-as-you-type interface for all files under the project root.

A prefix argument enables “do what I mean” mode. On an import statement, it will try to open the module imported. Elsewhere in a file, it will look for an associated test or implementation file, and if found, open that. If this fails, either way, it will fall back to the normal find file in project behavior.

If the current file is called, then this will search for a in the same directory, or in a test or tests subdirectory. If the current file is already called, it will try and find a nearby.

This command uses find-file-in-project under the hood, so see there for more options.

C-c C-s (elpy-rgrep-symbol)

Search the files in the current project for a string. By default, this uses the symbol at point. With a prefix argument, it will prompt for a regular expression to search.

This is basically a grep -r through the project.

In addition to these two commands, elpy-check also supports optionally checking all files in the current project.

Elpy’s idea of the project root and which files belong to a project and which don’t can be influenced as well.

M-x elpy-set-project-root

Set the current project root directory. This directory should contain all files related to the current project.

elpy-project-ignored-directories (Customize Option)

When Elpy searches for files in the current project, it will ignore files in directories listed here.

elpy-project-root-finder-functions (Customize Option)

To find the project root, Elpy can utilize a number of heuristics. With this option, you can configure which are used.

To configure Elpy specifically for a single project, you can use Emacs’ Directory Variables. Elpy provides a simple interface to this.

M-x elpy-set-project-variable

Set or change the value of a project-wide variable. With a prefix argument, the value for the variable is removed.

This only takes effect in new buffers.


When you type Python code, Elpy will try and figure out possible completions and provide them in a suggestion window. If Elpy doesn’t do so automatically, you can force it to complete right where you are.

M-TAB (elpy-company-backend)

Provide completion suggestions for a completion at point.

You can use cursor keys or M-n and M-p to scroll through the options, RET to use the selected completion, or TAB to complete the common part.

On any completion option, C-d or <f1> will display a temporary window with documentation. C-w will display a temporary window showing the source code of the completion to get some context.

Elpy uses Company Mode for the completion interface, so its documentation is a good place for further information.

Interactive Python

Emacs can run a Python interpreter in a special buffer, making it much easier to send code snippets over.

C-c C-z (elpy-shell-switch-to-shell)

Switch to buffer with a Python interpreter running, starting one if necessary.

Do note that Elpy only starts a single interactive Python process. This process will inherit the current virtual env. If you want to start a Python interpreter with a different virtual env, you can either kill the existing one, or rename the buffer.

C-c C-c (elpy-shell-send-region-or-buffer)

Whenever you are in an Elpy buffer, C-c C-c will send Python code to the subprocess. If there is an active region, that region will be sent; if not, the whole buffer is sent.

This command will also escape any uses of the if __name__ == '__main__' idiom, to prevent accidental execution of a script. If you want this to be evaluated, pass a prefix argument with C-u.

C-RET (elpy-shell-send-current-statement)

Send current statement to Python shell.

This command sends statements to shell without indentation. If you send nested statements, shell will throw IndentationError. To send nested statements, it is recommended to select region and run elpy-shell-send-region-or-buffer

C-M-x (python-shell-send-defun)

Similar to C-c C-c, this will send the code of the current top level class or function to the interactive Python process.

C-c C-k (elpy-shell-kill)

Kill the current python shell. If elpy-dedicated-shells is non-nil, kill the current buffer dedicated shell.

C-c C-K (elpy-shell-kill-all)

Kill all active python shells.

M-x elpy-use-ipython
M-x elpy-use-cpython

Use these commands, either interactively or from your .emacs, to set the interactive interpreter to either ipython or cpython. As ipython requires some more setup work in older Emacsen, these will take care of the right setup for you.

As an IPython user, you might be interested in the Emacs IPython Notebook, too.

Syntax Checking

Whenever you save a file, Elpy will run a syntax check and highlight possible errors or warnings inline.

C-c C-n (elpy-flymake-next-error)
C-c C-p (elpy-flymake-previous-error)

You can navigate between any error messages with these keys. The current error will be shown in the minibuffer.

Elpy uses the built-in Flymake library to find syntax errors on the fly, so see there for more configuration options.

C-c C-v (elpy-check)

Alternatively, you can run a syntax check on the current file where the output is displayed in a new buffer, giving you an overview and allowing you to jump to the errors from there.

With a prefix argument, this will run the syntax check on all files in the current project.

python-check-command (Customize Option)

To change which command is used for syntax checks, you can customize this option. By default, Elpy uses the flake8 program, which you have to install separately. The elpy-config command will prompt you to do this if Elpy can’t find the program.

It is possible to create a single virtual env for the sole purpose of installing flake8 in there, and then simply link the command script to a directory inside your PATH, meaning you do not need to install the program in every virtual env separately.


Elpy provides a single interface to documentation.

C-c C-d (elpy-doc)

When point is on a symbol, Elpy will try and find the documentation for that object, and display that. If it can’t find the documentation for whatever reason, it will try and look up the symbol at point in pydoc. If it’s not there, either, it will prompt the user for a string to look up in pydoc.

With a prefix argument, Elpy will skip all the guessing and just prompt the user for a string to look up in pydoc.


Testing is an important part of programming. Elpy provides a central interface to testing, which allows for a good workflow for tests.

Elpy’s test interface is built around Emacs’ compilation framework. Elpy will run test commands as a compilation job, with all the advantages this brings.

C-c C-t (elpy-test)

Start a test run. This uses the currently configured test runner to discover and run tests. If point is inside a test case, the test runner will run exactly that test case. Otherwise, or if a prefix argument is given, it will run all tests.

M-x elpy-set-test-runner

This changes the current test runner. Elpy supports the standard unittest discovery runner, the Django discovery runner, nose and py.test. You can also write your own, as described in Writing Test Runners.

Note on Django runners: by default, elpy runs Django tests with You must set the environment variable DJANGO_SETTINGS_MODULE accordingly. Alternatively, you can set elpy-test-django-with-manage to t in order to use your project’s You then don’t need to set the environment variable, but change virtual envs (see virtualenvwrapper.el).

This enables a good workflow. You write a test and use C-c C-t to watch it fail. You then go to your implementation file, for example using C-u C-c C-f, and make the test pass. You can use a key bound to recompile (I use <f5> for this) to just re-run that one test. Once that passes, you can use C-c C-t again to run all tests to make sure they all pass as well. Repeat.

For an even more automated way, you can use tdd.el, which will run your last compile command whenever you save a file.


Elpy supports various forms of refactoring Python code.

C-c C-e (elpy-multiedit-python-symbol-at-point)

Edit all occurrences of the symbol at point at once. This will highlight all such occurrences, and editing one of them will edit all. This is an easy way to rename identifiers.

If the backend does not support finding occurrences (currently only Jedi does), or if a prefix argument is given, this will edit syntactic occurrences instead of semantic ones. This can match more occurrences than it should, so be careful. You can narrow the current buffer to the current function using C-x n d to restrict where this matches.

Finally, if there is a region active, Elpy will edit all occurrences of the text in the region.

C-c C-r f (elpy-format-code)

Format code using the available formatter.

This command formats code using yapf or autopep8 formatter. If a region is selected, only that region is formatted. Otherwise current buffer is formatted.

C-c C-r i (elpy-importmagic-fixup)

Query for new imports of unresolved symbols, and remove unreferenced imports. Also sort the imports in the import statement blocks.

C-c C-r r (elpy-refactor)

Run the Elpy refactoring interface for Python code.

This command uses rope package and provides various refactoring options depending on the context.


Elpy has basic Django support such as parsing either or (If it does not find it falls back to for command completion assistance. Can also start runserver automatically and you can give an ip address and port.

C-c C-x c (elpy-django-command)

Choose what command you’d like to run via or

C-c C-x r (elpy-django-runserver)

Start the development server command, runserver. Default arguments are for ip address and 8000 for port. These can be changed via elpy-django-server-ipaddr and elpy-django-server-port.


Elpy allows to profile asynchronously python scripts using cProfile.

M-x elpy-profile-buffer-or-region

Send the current buffer or region to the profiler and display the result with elpy-profile-visualizer. The default visualizer is snakeviz, a browser-based graphical profile viewer that can be installed with pip install snakeviz. If the profiling fails, the python error output is displayed.