使用 pdb 调试 Python 时引发 BdbQuit

问题描述 投票:0回答:11

最近在将

pdb
调试器添加到我的 Python 2.7.10 代码中时,我收到以下消息:

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

这是插入行后:

import pdb; pdb.set_trace()

在代码中。

我不明白为什么会发生这种情况。我已经阅读了 Bdb 和 Bdbquit,但无法弄清楚为什么我的代码中会发生这种情况。谁能给我提供一些关于为什么会发生这种情况的提示?我真的想让调试器再次工作。

python python-2.7 debugging pdb ipdb
11个回答
26
投票

当我在生产代码中留下

import pdb
pdb.set_trace()
时,我遇到了这个问题。当
pdb.set_trace()
行被执行时,python 正在等待我的输入来告诉它
c
继续或进入等...因为 python 代码正在由 Web 服务器调用,所以我不在那里按
 c
继续。经过这么长时间(不确定多久)它终于引发了
BdbQuit
异常。

我没有进行任何设置来捕获该异常,因此它在我的网络服务器中引发了 500。

我花了一段时间才明白是我在守护进程/后台运行的调试代码导致了这个问题。我觉得很傻。


18
投票

如果您从

(pdb)
提示继续并允许代码正常完成,我不会期望像您指示的回溯那样的输出,但如果您退出
pdb
,使用
quit
命令或 ^D (EOF) ,会发生类似的回溯,因为没有任何东西可以捕获调试器退出时引发的
BdbQuit
异常。在
bdb.py
中,
self.quitting
通过
True
方法(以及各种 run 方法中的
set_quit
子句)设置为
finally
。当
trace_dispatch
raise BdbQuit
时,由
self.quitting
True
调用的调度方法,并且
except:
的典型
BdbQuit
子句是一个简单的
pass
语句;
pdb
继承了
gdb
的所有内容。

简而言之,当调试器交互提前完成时,异常处理用于禁用调试器使用的系统跟踪功能。

完全避免回溯的一种方法是以不同方式使用

pdb
。您可以在
pdb.set_trace()
中调用代码(而不是相反),而不是从代码中调用
BdbQuit
(并且根本不处理
pdb
),此时
BdbQuit
异常将按预期处理数据库。这还允许您在不修改代码的情况下选择断点位置(使用
pdb
break
命令)。或者您可以混合使用这两种方法;在
pdb
pdb.set_trace()
调用等下运行您的代码,这些调用将成为断点,您只能通过修改代码来删除它们。

您可以使用

pdb
命令并将脚本调用作为其命令行参数,或使用
pdb
来调用
python -m pdb
中的代码。


17
投票

一个可能的原因是您正在后台运行 Python 脚本。当进程在后台运行时,您无法通过终端向进程发送输入,因此 pdb 控制台无法工作。最终,它提高了

BdbQuit


6
投票

除了 Eirik Fuller 的回答之外,我想补充一点,你不能在不同进程中运行的东西中使用

pdb
。为了调试,你可以检查这个答案:https://stackoverflow.com/a/23654936/7806805,但它看起来很黑客,或者你可以让你的程序在单线程中运行。请参阅文档:https://docs.python.org/3/library/concurrent.futures.html。对于多处理问题,您甚至可能需要浏览https://www.reddit.com/r/learnpython/comments/46x9sm/why_is_pdbset_trace_crashing_whenever_it_is_in_an/

无论如何,你的问题缺乏必要的背景。请补充您的问题。


3
投票

您可以使用命令

docker-compose run --rm --service-ports {YOUR_CONTAINER}
添加后:

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

例如:


1
投票

对于那些在 Django 测试中遇到此问题的人,这可能是由于将

--parallel
标志传递给测试命令造成的。正如之前的答复中指出的,这是由于多重处理造成的。尝试删除该标志,看看是否可以解决问题,它对我来说是这样。


1
投票

我在将数据传输到脚本中时遇到了这个问题。看起来

pdb
不想让管道保持打开状态,所以它会抛出
BdbQuit
。我通过将
stdin
数据保存到临时文件中,然后从 python 读取临时文件来解决了这个问题。

之前

$ 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

之后

$ pbpaste > temp.txt
$ python3 script.py test.txt 
> /Users/admin/Code/script.py(49)f()
-> hello = "world"
(Pdb) 

1
投票

我们需要为运行 Django 的 docker 服务启用 shell 输入。如果您使用 docker compose,请在 docker-compose 文件中添加:

stdin_open: true

version: '3'

services:
  ...
  django_app:
    build: .
    ports:
      - '8000:8000'
    stdin_open: true

0
投票

我使用

pdbpp
更幸运,它是
pdb
的替代品,即除了本身之外不需要任何其他东西(没有插件,没有额外的配置/选项)。它支持自动完成,这就是我所追求的
ipdb

您可以使用

pip install pdbpp
安装它。


0
投票

当我的代码中存在

breakpoint()
调用时,我遇到了此错误。它与这里提出的其他原因非常相似(
pdb
的各种用途)。只要知道这也是一种可能性即可。


0
投票

在这个SO答案中找到了最小的解决方案

tldr;它的版本放在

sys.stdin = open(0)

 之前 
pdb.set_trace()

    

© www.soinside.com 2019 - 2024. All rights reserved.