Normally you would start a debug session by launching a script from the debugger. However, in some scenarios this is not possible. For example python scripts that are embedded in other programs. You can still debug embedded scripts by using the following technique:
Add the following line to any script you wish to debug with the embedded debugging technique:
import rpdb2; rpdb2.start_embedded_debugger(password)
Once this line is invoked, the script will freeze for a default period of 5 minutes, waiting for a debugger to attach. The password is used to secure client/server (debugger/debuggee) communication. Naturally, the debugger has to use the same password in order to successfully attach.
It is recommended not to use a hard coded password in a script, since anyone with read access rights to the script may read the password and compromise your system security. Instead it is preferable to query the password interactively. If applicable you can use the following line as an alternative to the one suggested above:
import rpdb2; rpdb2.start_embedded_debugger_interactive_password()
What if for any reason you fail to attach to the frozen script? The frozen script waits for you to attach for a default period of 5 minutes, and when this timeout expires it will resume execution. This prevents the need to terminate the server hosting the python script or all kinds of other desperate attempts in the hope of terminating the frozen script.
Winpdb Hang on an Inactive Embedded Interpreter
Embedded Python interpreters are not always active. Usually they become active to invoke a script method, and when this method returns they return to inactivity. During this time the embedded debugger is inactive as well. Asking Winpdb to break when the embedded Python interpreter is inactive will result in Winpdb becoming unresponsive. Once the embedded Python interpreter becomes active again, Winpdb will return to life and break into the debugged script.
The relevant functions are brought here for your convenience:
def start_embedded_debugger( pwd, fAllowUnencrypted = True, fAllowRemote = False, timeout = TIMEOUT_FIVE_MINUTES, fDebug = False ): """ Use 'start_embedded_debugger' to invoke the debugger engine in embedded scripts. put the following line as the first line in your script: import rpdb2; rpdb2.start_embedded_debugger(pwd) This will cause the script to freeze until a debugger console attaches. pwd - The password that governs security of client/server communication fAllowUnencrypted - Allow unencrypted communications. Communication will be authenticated but encrypted only if possible. fAllowRemote - Allow debugger consoles from remote machines to connect. timeout - Seconds to wait for attachment before giving up. If None, never give up. Once the timeout period expires, the debuggee will resume execution. fDebug - debug output. IMPORTNAT SECURITY NOTE: USING A HARDCODED PASSWORD MAY BE UNSECURE SINCE ANYONE WITH READ PERMISSION TO THE SCRIPT WILL BE ABLE TO READ THE PASSWORD AND CONNECT TO THE DEBUGGER AND DO WHATEVER THEY WISH VIA THE 'EXEC' DEBUGGER COMMAND. It is safer to use: start_embedded_debugger_interactive_password() """ return __start_embedded_debugger( pwd, fAllowUnencrypted, fAllowRemote, timeout, fDebug ) def start_embedded_debugger_interactive_password( fAllowUnencrypted = True, fAllowRemote = False, timeout = TIMEOUT_FIVE_MINUTES, fDebug = False, stdin = sys.stdin, stdout = sys.stdout ): if g_server is not None: return if stdout is not None: stdout.write('Please type password:') pwd = stdin.readline().rstrip('n') return __start_embedded_debugger( pwd, fAllowUnencrypted, fAllowRemote, timeout, fDebug )