Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
529 views
in Technique[技术] by (71.8m points)

python: is it possible to attach a console into a running process

I just want to see the state of the process, is it possible to attach a console into the process, so I can invoke functions inside the process and see some of the global variables.

It's better the process is running without being affected(of course performance can down a little bit)

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

This will interrupt your process (unless you start it in a thread), but you can use the code module to start a Python console:

import code
code.interact()

This will block until the user exits the interactive console by executing exit().

The code module is available in at least Python v2.6, probably others.

I tend to use this approach in combination with signals for my Linux work (for Windows, see below). I slap this at the top of my Python scripts:

import code
import signal
signal.signal(signal.SIGUSR2, lambda sig, frame: code.interact())

And then trigger it from a shell with kill -SIGUSR2 <PID>, where <PID> is the process ID. The process then stops whatever it is doing and presents a console:

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)
>>>

Generally from there I'll load the server-side component of a remote debugger like the excellent WinPDB.

Windows is not a POSIX-compliant OS, and so does not provide the same signals as Linux. However, Python v2.2 and above expose a Windows-specific signal SIGBREAK (triggered by pressing CTRL+Pause/Break). This does not interfere with normal CTRL+C (SIGINT) operation, and so is a handy alternative.

Therefore a portable, but slightly ugly, version of the above is:

import code
import signal
signal.signal(
        vars(signal).get("SIGBREAK") or vars(signal).get("SIGUSR2"),
        lambda sig, frame: code.interact()
        )

Advantages of this approach:

  • No external modules (all standard Python stuff)
  • Barely consumes any resources until triggered (2x import)

Here's the code I use in my production environment which will load the server-side of WinPDB (if available) and fall back to opening a Python console.

# Break into a Python console upon SIGUSR1 (Linux) or SIGBREAK (Windows:
# CTRL+Pause/Break).  To be included in all production code, just in case.
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:
    # Typically: ValueError: signal only works in main thread
    pass

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...