BdbQuit raised when debugging Python with pdb
Asked Answered
M

11

62

Recently when adding the pdb debugger to my Python 2.7.10 code, I get this message:

Traceback (most recent call last):
  File "/Users/isaachess/Programming/vivint/Platform/MessageProcessing/vivint_cloud/queues/connectors/amqplib_connector.py", line 191, in acking_callback
    callback(message.body)
  File "/Users/isaachess/Programming/vivint/Platform/MessageProcessing/vivint_cloud/queues/consumable_message_queue.py", line 32, in deserialized_callback
    self._callback_method(msg)
  File "/Users/isaachess/Programming/vivint/Platform/BusinessLogic/businesslogic/util/statsd_util.py", line 95, in _time_func
    retVal = f(*args, **kwargs)
  File "/Users/isaachess/Programming/vivint/Platform/MessageProcessing/vivint_cloud/net/router.py", line 226, in handle
    try:
  File "/Users/isaachess/Programming/vivint/Platform/MessageProcessing/vivint_cloud/net/router.py", line 226, in handle
    try:
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/bdb.py", line 49, in trace_dispatch
    return self.dispatch_line(frame)
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/bdb.py", line 68, in dispatch_line
    if self.quitting: raise BdbQuit
BdbQuit

This is after inserting the line:

import pdb; pdb.set_trace()

in the code.

I cannot figure out why this is happening. I've read up on Bdb and Bdbquit, but cannot figure out why this is happening in my code. Can anyone provide me with some hints of why this happens in general? I really want to get the debugger working again.

Motta answered 21/1, 2016 at 3:5 Comment(3)
How do you run your process? My guess is that your process is not attached to a terminal or something like that. Is this a subprocess or something like that?Lathrop
@shx2, subprocess? Could somehow the use of Luigi cause this?Fluxmeter
I encountered the same issue. Really hope it could be resolvedAlltime
R
28

I ran into this when I left import pdb and a pdb.set_trace() in my production code. When the pdb.set_trace() line was executed, python was waiting for my input to tell it to continue or step into, etc... Because the python code was being called by a web server I wasn't there to press c to continue. After so long (not sure how long) it finally raised the BdbQuit exception.

I didn't have anything setup to catch that exception so it raised a 500 in my web server.

It took me a while to understand that my debug code running in an a daemon/background was causing the issue. I felt silly.

Requiescat answered 10/2, 2018 at 10:46 Comment(4)
Updated my answer to whoever down voted. If you down voted, please do re read answer and leave an explanation as to why this is not answering the question.Requiescat
How exactly did you do it then?Chlorate
@AbhishekRai Are you trying to run PDB in production? I think what you need to do is not run that in production and remove the pdf.set_trace() from your code.Requiescat
still don't understand..how to debug it then?Chlorate
F
18

If you continue from the (pdb) prompt and allow your code to finish normally, I wouldn't expect output like the traceback you indicated, but if you quit pdb, with the quit command or ^D (EOF), a traceback like that occurs because there is nothing to catch the BdbQuit exception raised when the debugger quits. In bdb.py self.quitting gets set to True by the set_quit method (and by finally clauses in the various run methods). Dispatch methods called by trace_dispatch raise BdbQuit when self.quitting is True, and the typical except: clause for BdbQuit is a simple pass statement; pdb inherits all of that from gdb.

In short, exception handling is used to disable the system trace function used by the debugger, when the debugger interaction finishes early.

One way to avoid that traceback altogether is to use pdb differently. Rather than calling pdb.set_trace() from your code (and not handling BdbQuit at all), you can invoke your code within pdb (rather than vice versa), at which point the BdbQuit exception will be handled as intended by pdb. That will also allow you to choose breakpoint locations without modifying your code (using pdb's break command). Or you can mix the two approaches; run your code under pdb, pdb.set_trace() calls and all, and those calls will be breakpoints that you can remove only by modifying your code.

You can invoke your code within pdb by using the pdb command with your script invocation as its command line arguments, or with python -m pdb.

Frameup answered 21/1, 2016 at 23:47 Comment(4)
it would be great if you could specify possible causes of BdbQuit as pdb doesn't raise it in some scripts.Etherealize
this is not the complete answer, there are many other limitations of pdb like it cannot work in a multiprocess pool and so on. You fail to mention those.Outsize
Running with python -m pdb (even in python 3.7) still hits this issue.Dragonfly
Thanks for this answer! This is actually what is most likely going wrong for 99% of people coming here. In my case, I was piping input to a Python process over STDIN. This causes the EOF to be immediately read by the pdb debugger, hence an immediate BadQuit.Belter
L
18

One possible reason is that you are running the Python script in the background. When a process runs in the background, you can't send input to the process via terminal and hence pdb console can't work. Eventually, it raises BdbQuit.

Latishalatitude answered 29/1, 2019 at 11:31 Comment(0)
O
7

Apart from Eirik Fuller answer I would like to add that you can't be using pdb in something thats running in a different process. For debugging you can check this answer: https://mcmap.net/q/169415/-how-to-attach-debugger-to-a-python-subproccess but it seems very hackish or you can make your program run in a single thread. Consult the documentation: https://docs.python.org/3/library/concurrent.futures.html. For multiprocessing issues you might even want to go through https://www.reddit.com/r/learnpython/comments/46x9sm/why_is_pdbset_trace_crashing_whenever_it_is_in_an/

Anyways your question lacks much needed context. Please add on to your question.

Outsize answered 7/3, 2018 at 3:36 Comment(0)
H
3

you can use comand docker-compose run --rm --service-ports {YOUR_CONTAINER} after added:

def your_f():
    **import pdb
    pdb.set_trace()**
    result = your_logic
    return result

exmaple: enter image description here

Hysterectomize answered 26/11, 2021 at 12:49 Comment(1)
Thanks! But instead of container name I used compose service name and without --service-ports.Catsup
C
2

I encountered this issue when piping data into my script. It seems pdb doesn't want to hold the pipe open so it throws BdbQuit. I fixed the issue by saving my stdin data into a temp file and then reading the temp file from python.

Before

$ pbpaste | script.py
Traceback (most recent call last):
  File "/Users/admin/Code/script.py", line 78, in <module>
    process(args)
  ... blah blah ...
  File "/usr/local/Cellar/[email protected]/3.9.13_1/Frameworks/Python.framework/Versions/3.9/lib/python3.9/bdb.py", line 88, in trace_dispatch
    return self.dispatch_line(frame)
  File "/usr/local/Cellar/[email protected]/3.9.13_1/Frameworks/Python.framework/Versions/3.9/lib/python3.9/bdb.py", line 113, in dispatch_line
    if self.quitting: raise BdbQuit
bdb.BdbQuit

After

$ pbpaste > temp.txt
$ python3 script.py test.txt 
> /Users/admin/Code/script.py(49)f()
-> hello = "world"
(Pdb) 
Choate answered 27/7, 2022 at 18:57 Comment(0)
O
1

For those of you running into this with Django tests, it can be caused by passing the --parallel flag to the test command. This is due to multiprocessing, as pointed out in previous replies. Try removing that flag to see if it solves the problem, it did for me.

Ovalle answered 20/8, 2020 at 7:43 Comment(0)
A
1

We need to enable shell input for the docker service that runs Django. If you're using docker compose, add: stdin_open: true in your docker-compose file:

version: '3'

services:
  ...
  django_app:
    build: .
    ports:
      - '8000:8000'
    stdin_open: true
Atlas answered 12/11, 2022 at 1:4 Comment(0)
M
0

I've had more luck using pdbpp, which is a drop in replacement for pdb, i.e. in doesn't require anything else than being itself (no plugin, no extra configuration/options). It supports autocompletion, which is what I was after with ipdb.

You can install it with pip install pdbpp.

Martial answered 24/9, 2021 at 19:37 Comment(0)
B
0

I encountered this error when there was a breakpoint() call left in my code. It is pretty similar to other causes raised here (various uses of pdb). Just know that this is also a possibility.

Bayern answered 11/10, 2022 at 15:56 Comment(0)
C
0

Minimal solution found in this SO answer

The tldr; verison of it is put sys.stdin = open(0) before pdb.set_trace()

However note, that idfyou set_trace before from the main process and step with it into a breakpoint in the other process, you will create a race condition wrt. the input/stdin, i.e. part of the input will go to one process, the other part to the other process. So don't step or next when in the main process until you reach the other breakpoint.

Cuneal answered 5/9, 2023 at 18:51 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.