Simple "devops" in practice, but requires a lot of words.
One feature of Emacs often overlooked - it's a terminal-based editor:
emacs -nw
or the same emacs --no-window-system
(it should be launched in activated Python virtual environment)
All IDE's work only in Graphic Display mode. "Remote debugging" stems from this: a special process on a debugged machine and a communication protocol from IDE to that remote process.
Emacs being a terminal-based capable interface: using SSH launch Emacs on a debugged machine and have an unexcelled interface to it.
Local Emacs init script that installs all known by the user extensions can be transferred to the remote machine and launched from .emacs start file - replication of all user's local setups.
Realgud - debugger extension for Emacs.
To debug Python the only robust method is to insert code lines into source that invoke one of the existing debuggers for Python - inline breakpoints. Some devs believe such method "pollutes the sources", but it always works, unlike others. Python debuggers do not trap breakpoints in functions that are executed in other threads, so just setting a breakpoint in a debugger doesn't guarantee it will be trapped.
This method of debugging in realgud is called "delayed"
M-x pdb-delayed
M-x trepan3k-delayed
Trepan is a debugger with a GDB-like command interface, shows threads, is more precise, but is very slow when stepping over expensive functions(like getting web response). For special cases.
These functions ask for the module path and its args to debug(default: current buffer) and create a buffer with Python process that serves as a debugger's command line interface.
When the debugged program hits a line in source: import pdb; pdb.set_trace()
that file is opened in other buffer(python-mode) with minor mode for key mappings of basic debugger commands: F10 for next, F5 continue, etc.
Hence it's "delayed".
Vagrant
If debugging is done by launching a development server like Django's:
M-x pdb-delayed ->
Emacs prompt in minibuffer: pdb /pathto/manage.py runserver
(runserver added manually)
then it may require forwarded port used by the dev server to a host machine in Vagrantfile configuration:
config.vm.network :forwarded_port, guest: 8000, host: 8000
And the dev server must be launched with explicit IP:PORT(for Virtualbox provider in Vagrant that IP must be 0.0.0.0, not 127.0.0.1):
pdb /pathto/manage.py runserver 0.0.0.0:8000
What if the debugged source must serve website users?
M-x pdb-delayed ->
Emacs minibuffer prompt: ./pdb /pathto/manage.py runserver
("runserver" added manually)
Where ./pdb
is a shell script in project's directory:
#!/bin/sh
AKDEBUG=on python -m pdb $*
So debugger's buffer process will have AKDEBUG environment variable defined, and a breakpoint in python source would be then:
import os
if os.getenv('AKDEBUG'):import pdb;pdb.set_trace()
Debugger will be triggered only for the dev Django server.
Similar principle for any other framework.
Some convenient tools
M-x rgrep - recursive search for breakpoint lines in code.
Standard Abbrev extension: to insert inline breakpoints.
So that typing "pd"(for example) and space, would expand to:
import os
if os.getenv('AKDEBUG'):import pdb;pdb.set_trace()
In Emacs init, inside Python mode hook:
(define-abbrev python-mode-abbrev-table "pd" "import os
if os.getenv('AKDEBUG'):import pdb;pdb.set_trace()
" 'some-function-to-indent-this-abbrev-expansion)
(defun some-function-to-indent-abbrev-expansion ()
(forward-line -1)
(funcall indent-line-function)
(move-end-of-line 1)
(save-buffer 0))