Esto interrumpirá su proceso (a menos que lo inicie en un hilo), pero puede usar el codemódulo para iniciar una consola Python:
import code
code.interact()
Esto se bloqueará hasta que el usuario salga de la consola interactiva ejecutando exit().
El codemódulo está disponible al menos en Python v2.6, probablemente en otros.
Tiendo a usar este enfoque en combinación con señales para mi trabajo con Linux (para Windows, ver más abajo). Pongo esto en la parte superior de mis scripts de Python:
import code
import signal
signal.signal(signal.SIGUSR2, lambda sig, frame: code.interact())
Y luego desencadenarlo desde un shell con kill -SIGUSR2 <PID>, donde <PID>está el ID del proceso. Luego, el proceso detiene lo que esté haciendo y presenta una consola:
Python 2.6.2 (r262:71600, Oct 9 2009, 17:53:52)
[GCC 3.4.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>>
Generalmente, desde allí cargaré el componente del lado del servidor de un depurador remoto como el excelente WinPDB .
Windows no es un sistema operativo compatible con POSIX , por lo que no proporciona las mismas señales que Linux. Sin embargo, Python v2.2 y superior exponen una señal específica de WindowsSIGBREAK (activada presionando CTRL+ Pause/Break). Esto no interfiere con el funcionamiento normal CTRL+ C( SIGINT), por lo que es una alternativa útil.
Por lo tanto, una versión portátil, pero un poco fea, de lo anterior es:
import code
import signal
signal.signal(
vars(signal).get("SIGBREAK") or vars(signal).get("SIGUSR2"),
lambda sig, frame: code.interact()
)
Ventajas de este enfoque:
- Sin módulos externos (todas las cosas estándar de Python)
- Apenas consume recursos hasta que se activa (importación 2x)
Aquí está el código que utilizo en mi entorno de producción que cargará el lado del servidor de WinPDB (si está disponible) y volverá a abrir una consola Python.
def debug_signal_handler(signal, frame):
del signal
del frame
try:
import rpdb2
print
print
print "Starting embedded RPDB2 debugger. Password is 'foobar'"
print
print
rpdb2.start_embedded_debugger("foobar", True, True)
rpdb2.setbreak(depth=1)
return
except StandardError:
pass
try:
import code
code.interact()
except StandardError as ex:
print "%r, returning to normal program flow" % ex
import signal
try:
signal.signal(
vars(signal).get("SIGBREAK") or vars(signal).get("SIGUSR1"),
debug_signal_handler
)
except ValueError:
pass