Reputation: 329
How I can setup a hotpluggable remote debugger with Python IDE integration? For example using PyCharm. By hotpluggable I mean: can connect and disconnect from dev server on fly.
I have dev server in the cloud (django, nginx, uwsgi, postgres, debian), and use PyCharm as the main IDE (but if you have solution for any other IDE, please provide it).
Sometimes, I need to connect and debug scripts without stopping/restarting the dev server. Using PyCharm's debugger (pydevd), dev server cannot start without working debugger server (Connection refused
), and if I stop the remote debugger while the dev server is running, it crashes e.g.
An existing connection was forcibly closed by the remote host
I found pdg/epdg but they have no integration with PyCharm. Also PyCharm has a nice feature : "Attach to process", but it works only with local processes.
Upvotes: 1
Views: 273
Reputation: 7098
The basic approach that would probably work is to set up a signal handler to the program you want to debug to load in a debugger. Then sending the process a signal to debug (via the kill
command) you could then attach remotely.
Here is how you'd do this via the python trepan debuggers
import signal
def signal_handler(num, f):
from trepan.interfaces import server as Mserver
from trepan.api import debug
connection_opts={'IO': 'TCP', 'PORT': 1955}
intf = Mserver.ServerInterface(connection_opts=connection_opts)
dbg_opts = {'interface': intf}
print('Starting TCP server listening on port 1955.')
debug(dbg_opts=dbg_opts)
return
signal.signal(signal.SIGUSR1, signal_handler)
# Go about your business...
import time
import os
print(os.getpid())
for i in range(10000):
time.sleep(0.2)
Now run that:
$ python /tmp/foo.py
8530
From above output we helpfully listed the pid of the Python process we want to debug.
Now in a shell we send a signal to tell the process to go into the debugger that is set up in the signal handler. You will have to adjust the process id.
$ kill -USR1 8530 # Adjust the pid to what you see above
And in the shell where we ran /tmp/foo.py
you should now see
the new output:
$ python /tmp/foo.py
8530
Starting TCP server listening on port 1955. # This is new
Back to the shell where we issued the kill -USR1
, we now attach the the process now stopped inside a debugger:
$ trepan2 --client --port 1955
Connected.
(/tmp/foo.py:11 @101): signal_handler
-- 11 return
(trepan2*) list
6 connection_opts={'IO': 'TCP', 'PORT': 1955}
7 intf = Mserver.ServerInterface(connection_opts=connection_opts)
8 dbg_opts = {'interface': intf}
9 print('Starting TCP server listening on port 1955.')
10 debug(dbg_opts=dbg_opts)
11 -> return
12
13 signal.signal(signal.SIGUSR1, signal_handler)
14 # Go about your business...
(trepan2*) backtrace
-> 0 signal_handler(num=10, f=<frame object at 0x7f9036796050>)
called from file '/tmp/foo.py' at line 11
## 1 <module> file '/tmp/foo.py' at line 20
Upvotes: 1