use*_*028 12 python debugging pdb
据我所知,pdb无法识别源代码何时在"运行"之间发生了变化.也就是说,如果我正在调试,注意一个错误,修复该错误,并在pdb中重新运行程序(即不退出pdb),pdb将不会重新编译代码.即使pdb列出了新的源代码,我仍然会调试旧版本的代码.
那么,pdb是否在源更改时不更新已编译的代码?如果没有,有没有办法让它这样做?我希望能够留在单个pdb会话中以保持我的断点等.
FWIW,gdb会注意到它正在调试的程序在它下面发生变化,尽管只是重新启动该程序.这是我试图在pdb中复制的行为.
以下迷你模块可能会有所帮助。如果在 pdb 会话中导入它,则可以使用:
pdb> pdbs.r()
Run Code Online (Sandbox Code Playgroud)
随时强制重新加载除main之外的所有非系统模块。代码跳过它,因为它抛出一个 ImportError('Cannot re-init internal module main ') 异常。
pdb> pdbs.r()
Run Code Online (Sandbox Code Playgroud)
基于 @pourhaus 的回答(2014 年起),本秘籍通过命令增强了pdb++调试器reload(预计适用于 Linux 和 Windows,任何 Python 安装)。
提示:新reload命令接受一个可选的模块前缀列表来重新加载(并排除),而不是在恢复调试时破坏已加载的全局变量。
只需将以下Python-3.6代码插入到您的~/.pdbrc.py文件中:
## Augment `pdb++` with a `reload` command
#
# See https://stackoverflow.com/questions/724924/how-to-make-pdb-recognize-that-the-source-has-changed-between-runs/64194585#64194585
from pdb import Pdb
def _pdb_reload(pdb, modules):
"""
Reload all non system/__main__ modules, without restarting debugger.
SYNTAX:
reload [<reload-module>, ...] [-x [<exclude-module>, ...]]
* a dot(`.`) matches current frame's module `__name__`;
* given modules are matched by prefix;
* any <exclude-modules> are applied over any <reload-modules>.
EXAMPLES:
(Pdb++) reload # reload everything (brittle!)
(Pdb++) reload myapp.utils # reload just `myapp.utils`
(Pdb++) reload myapp -x . # reload `myapp` BUT current module
"""
import importlib
import sys
## Derive sys-lib path prefix.
#
SYS_PREFIX = importlib.__file__
SYS_PREFIX = SYS_PREFIX[: SYS_PREFIX.index("importlib")]
## Parse args to decide prefixes to Include/Exclude.
#
has_excludes = False
to_include = set()
# Default prefixes to Exclude, or `pdb++` will break.
to_exclude = {"__main__", "pdb", "fancycompleter", "pygments", "pyrepl"}
for m in modules.split():
if m == "-x":
has_excludes = True
continue
if m == ".":
m = pdb._getval("__name__")
if has_excludes:
to_exclude.add(m)
else:
to_include.add(m)
to_reload = [
(k, v)
for k, v in sys.modules.items()
if (not to_include or any(k.startswith(i) for i in to_include))
and not any(k.startswith(i) for i in to_exclude)
and getattr(v, "__file__", None)
and not v.__file__.startswith(SYS_PREFIX)
]
print(
f"PDB-reloading {len(to_reload)} modules:",
*[f" +--{k:28s}:{getattr(v, '__file__', '')}" for k, v in to_reload],
sep="\n",
file=sys.stderr,
)
for k, v in to_reload:
try:
importlib.reload(v)
except Exception as ex:
print(
f"Failed to PDB-reload module: {k} ({v.__file__}) due to: {ex!r}",
file=sys.stderr,
)
Pdb.do_reload = _pdb_reload
Run Code Online (Sandbox Code Playgroud)
“在 pdb 中重新运行程序”是什么意思?如果您导入了一个模块,Python 不会重新读取它,除非您明确要求这样做,即使用reload(module). 然而,reload它远非万无一失(请参阅xreload了解另一种策略)。
Python 代码重载存在很多陷阱。为了更可靠地解决您的问题,您可以使用一个类来包装 pdb,该类将断点信息记录到磁盘上的文件中,并根据命令回放它们。
(抱歉,忽略这个答案的第一个版本;现在还很早,我没有足够仔细地阅读你的问题。)