python条件调试断点—3.7 PEP 553之前版本的一行程序,其作用类似于Perl';s$DB::single=1

python条件调试断点—3.7 PEP 553之前版本的一行程序,其作用类似于Perl';s$DB::single=1,python,perl,debugging,breakpoints,conditional-execution,Python,Perl,Debugging,Breakpoints,Conditional Execution,在PEP 553breakpoint()实用程序之前的python版本中,建议使用什么方法添加(理想情况下是一行代码)代码,使其具有一个断点,该断点可以在某个条件下被忽略(例如,全局调试标志或args.debug标志) 在Perl中,我习惯于使用$DB::single=1;1;单行,我知道我可以安全地保留在代码中,并且不会影响perl code.pl的正常运行,除非显式调用perl-d code.pl。例如: my $a = 1; $DB::single=1;1; # breakpoint li

在PEP 553
breakpoint()
实用程序之前的python版本中,建议使用什么方法添加(理想情况下是一行代码)代码,使其具有一个断点,该断点可以在某个条件下被忽略(例如,全局调试标志或args.debug标志)

在Perl中,我习惯于使用
$DB::single=1;1;单行,我知道我可以安全地保留在代码中,并且不会影响
perl code.pl
的正常运行,除非显式调用
perl-d code.pl
。例如:

my $a = 1;
$DB::single=1;1; # breakpoint line
my $b = 2;
print "$a $b\n";
如果我以:
perl code.pl
的形式运行此代码,它将一直运行到完成。 如果我使用:
perl-dcode.pl
运行此代码,则
pdb
将在断点行停止(而不是在下一行使用
my$b=2;
语句之前),因为它包含
1$DB::single=1之后的code>语句语句

同样,如果我写:

my $debug = 1;
my $a = 1;
$DB::single=$debug;1; # first breakpoint line
my $b = 2;
$DB::single=$debug;1; # second breakpoint line
print "$a $b\n";
# [...] Lots more code sprinkled with more of these
$DB::single=$debug;1; # n'th breakpoint line
然后我可以执行
perl-dcode.pl
,它将在第一个断点行停止,然后在
pdb
会话中,一旦我很高兴它不需要在任何其他地方停止,然后执行:
$debug=0
,然后
pdb
继续
c
,这将使它不会在代码中的第二行或其他类似断点行停止

我如何在python中(PEP553之前的2.x和3.x版本)实现同样的效果,最好是在单行语句中

我知道PEP 553,除了必须显式设置
PYTHONBREAKPOINT=0 python3.7 code.py
或注释掉
breakpoint()
行的麻烦之外,它是这里问题的解决方案

我想到了如下选择:

import pdb; pdb.set_trace()
dummy=None;
pdb.set_trace()
下面的语句是为了实现与
1相同的功能$DB::single=1后的同一行中的code>在Perl中,这是让调试器停止在我放置断点的地方,而不是下一条语句。这样,如果中间有大量注释代码或文档,调试器就不会跳转到离断点很远的下一条语句

或使用以下条件:

if args.debug or debug:
    import pdb; pdb.set_trace()
    _debug=False; #args.debug=False

因此,如果我完成了脚本调试,我可以设置
args.debug=False
debug=False
,而不必触及代码中的所有断点。

以下是使用当前目录中的
.pdbrc
文件的简单方法:

t.py

def my_trace():
    global debug
    if debug:
        import pdb; pdb.set_trace()

debug = True
a= 1
my_trace()
b = 2
c = 3
my_trace()
d = 4
.pdbrc

r
$ python t.py
--Return--
> [...]/t.py(12)<module>()
-> b = 2
(Pdb) p a
1
(Pdb) p b
*** NameError: name 'b' is not defined
(Pdb) !debug=False
(Pdb) c
$ 
示例会话

r
$ python t.py
--Return--
> [...]/t.py(12)<module>()
-> b = 2
(Pdb) p a
1
(Pdb) p b
*** NameError: name 'b' is not defined
(Pdb) !debug=False
(Pdb) c
$ 
$python t.py
--返回--
>[…]/t.py(12)()
->b=2
(Pdb)p a
1.
(Pdb)p b
***名称错误:未定义名称“b”
(Pdb)!调试=错误
(Pdb)c
$ 
设置条件断点 与perl相同,python可以与
-d
一起运行,以设置调试标志:

$python--帮助
[...]
-d:解析器的调试输出;另外,PYTHONDEBUG=x
[...]
您可以在运行时通过
sys.flags
检查其状态:

$python-d
Python 2.7.15+(默认值,2018年11月27日,23:36:35)
[GCC 7.3.0]在linux2上
有关详细信息,请键入“帮助”、“版权”、“信用证”或“许可证”。
>>>导入系统
>>>系统标志
系统标志(调试=1,py3k_警告=0,分区_警告=0,…)
#^在那里,就在前面
允许以下一个线性程序启用调试:

导入pdb,系统;pdb.set_trace()如果sys.flags[0]否则无

从调试器禁用条件断点 关于这一部分

[…]一旦我很高兴它不需要在任何其他地方停止,那么执行[something],这将使它不会在代码中的第二行或其他类似断点行停止

但它变得有点棘手,因为python不允许对它进行变异,甚至不允许创建它的实例:

导入系统 >>>sys.flags.debug=0#无变异。。。 回溯(最近一次呼叫最后一次): 文件“”,第1行,在 TypeError:只读属性 >>>键入(系统标志)(#。。。而且没有实例化 回溯(最近一次呼叫最后一次): 文件“”,第1行,在 TypeError:无法创建“sys.flags”实例
但就我所测试的而言,除非您使用其他标志运行python,否则以下功能可以在不改变程序其他行为的情况下停用后续跟踪:

导入系统;sys.flags=[0]*len(sys.flags)#甚至可以放在一行上

要获得一个稍微更健壮的猴子补丁,以防前一个补丁导致奇怪的bug,您需要有如下内容:

def untrace():
“”“在pdb会话中调用此函数以跳过仅调试的set_trace()调用”“”
进口稀土
导入系统
从集合导入namedtuple#与struct sequence具有相同的接口
sys.flags=namedtuple(
“系统标志”,
[m.group()用于re.FindItemer(r'\w{2,}',repr(sys.flags)[10:-1])中的m]
)(0,*系统标志[1:])
虽然这句话可以放在一行上,但可能有点太多了。您可以将此函数粘贴到计划使用它的
.py
文件中,或者使用某种类型的
utils.py
,在调试期间从中导入它,然后c(continue)应再次运行程序的其余部分:

(Pdb)导入UTIL;utils.untrace()
(Pdb)c

谢谢您的回答。似乎pdb跳转到
导入pdb;pdb.set_trace()
当我运行脚本时,不要停留在
my_trace()之外。你知道为什么吗?奇怪的是,它适合我(Python 3.7.1)。您是否将
.pdbrc
保存在当前目录中?没有它和
r
return
)命令,它将无法工作!抱歉,我运行的是Python2.x而不是Python3.x。我现在可以使用您在使用Python3.4.3(旧的Ubuntu14.04笔记本电脑)时描述的行为。最后一件事是能够有一个单线等价物