36

Is there a simple way to detect, within Python code, that this code is being executed through the Python debugger?

I have a small Python application that uses Java code (thanks to JPype). When I'm debugging the Python part, I'd like the embedded JVM to be passed debug options too.

Adam Smooch
  • 1,167
  • 1
  • 12
  • 27
Stéphane Bonniez
  • 4,577
  • 3
  • 21
  • 16

10 Answers10

28

Python debuggers (as well as profilers and coverage tools) use the sys.settrace function (in the sys module) to register a callback that gets called when interesting events happen.

If you're using Python 2.6, you can call sys.gettrace() to get the current trace callback function. If it's not None then you can assume you should be passing debug parameters to the JVM.

It's not clear how you could do this pre 2.6.

babbageclunk
  • 8,523
  • 1
  • 33
  • 37
  • 5
    Though it seems to be a cleaner way, it does not work in pdb if there is no breakpoint set. – OOO Dec 05 '14 at 07:37
  • Hmm, you're right - it must be an optimisation the debugger uses. That said, most of the time when you're running in the debugger you'll have a breakpoint set. – babbageclunk Dec 05 '14 at 11:21
  • @babbageclunk, not if you're just trying to look at the environment when a program crashes (my most common way of doing things: `python -m pdb `). – Casey Kuball Jun 13 '19 at 22:50
  • You may want to check for alternate trace users like [pytest-cov](https://pytest-cov.readthedocs.io/en/latest/debuggers.html)... if it is truly a debugger, it should be of a type with `pydevd` in the name. – Chris R. Donnelly Jan 29 '21 at 23:44
16

Other alternative if you're using Pydev that also works in a multithreading is:

try:
    import pydevd
    DEBUGGING = True
except ImportError:
    DEBUGGING = False
jordeu
  • 6,711
  • 1
  • 19
  • 19
15

A solution working with Python 2.4 (it should work with any version superior to 2.1) and Pydev:

import inspect

def isdebugging():
  for frame in inspect.stack():
    if frame[1].endswith("pydevd.py"):
      return True
  return False

The same should work with pdb by simply replacing pydevd.py with pdb.py. As do3cc suggested, it tries to find the debugger within the stack of the caller.

Useful links:

twasbrillig
  • 17,084
  • 9
  • 43
  • 67
Stéphane Bonniez
  • 4,577
  • 3
  • 21
  • 16
9

Another way to do it hinges on how your python interpreter is started. It requires you start Python using -O for production and with no -O for debugging. So it does require an external discipline that might be hard to maintain .. but then again it might fit your processes perfectly.

From the python docs (see "Built-in Constants" here or here):

__debug__
This constant is true if Python was not started with an -O option.

Usage would be something like:

if __debug__:
    print 'Python started without optimization'
Travelling Man
  • 1,374
  • 10
  • 14
  • 2
    This is not truly an answer to the question - you get `__debug__` even when **not** running under a debugger (but have not used the `-O` "optimise" flag). – dsz Dec 26 '20 at 11:49
  • Indeed, hence the “requires an external discipline” caveat. – Travelling Man Dec 27 '20 at 15:33
7

If you're using Pydev, you can detect it in such way:

import sys
if 'pydevd' in sys.modules: 
    print "Debugger"
else:
    print "commandline"
Mvoicem
  • 471
  • 5
  • 5
2

In my perllib, I use this check:

if 'pdb' in sys.modules:
    # We are being debugged

It assumes the user doesn't otherwise import pdb

snoopyjc
  • 621
  • 4
  • 11
1

From taking a quick look at the pdb docs and source code, it doesn't look like there is a built in way to do this. I suggest that you set an environment variable that indicates debugging is in progress and have your application respond to that.

$ USING_PDB=1 pdb yourprog.py

Then in yourprog.py:

import os
if os.environ.get('USING_PDB'):
    # debugging actions
    pass
dowski
  • 3,188
  • 2
  • 20
  • 16
1

You can try to peek into your stacktrace.

https://docs.python.org/library/inspect.html#the-interpreter-stack

when you try this in a debugger session:

import inspect
inspect.getouterframes(inspect.currentframe()

you will get a list of framerecords and can peek for any frames that refer to the pdb file.

twasbrillig
  • 17,084
  • 9
  • 43
  • 67
do3cc
  • 204
  • 1
  • 8
1

Since the original question doesn't specifically call out Python2 - This is to confirm @babbageclunk's suggested usage of sys also works in python3:

from sys import gettrace as sys_gettrace

DEBUG = sys_gettrace() is not None
print("debugger? %s" % DEBUG)
Adam Smooch
  • 1,167
  • 1
  • 12
  • 27
  • Unfortunately, this only works if you are using "step". If you use "continue" then gettrace() returns None – snoopyjc Apr 16 '22 at 18:22
  • I'm familiar with the VSCode python debugger - can you elaborate on how you're launching the debugger with `step` or `continue` options? – Adam Smooch Apr 16 '22 at 21:09
  • python -m pdb Program.py - I'd like to know if the user did the "-m pdb". I wound up checking if "pdb" in sys.modules. – snoopyjc Apr 19 '22 at 04:38
  • 2
    Would you like to share that in your own answer? I'll add my assumptions to my own post. – Adam Smooch Apr 19 '22 at 14:00
-1

I found a cleaner way to do it,

Just add the following line in your manage.py

#!/usr/bin/env python
import os
import sys

if __debug__:
    sys.path.append('/path/to/views.py')


if __name__ == "__main__":
    ....

Then it would automatically add it when you are debugging.