我在 ipython 中使用 --pdb 命令,所以当我调试代码并发生错误时,它会显示堆栈跟踪。很多这些错误来自于使用错误输入调用 numpy 或 pandas 函数。堆栈跟踪从这些库的代码中的最新帧开始。重复 5-10 次 up 命令后,我实际上可以看到我做错了什么,这在 90% 的情况下会立即显而易见(例如,使用列表而不是数组调用)。
有什么方法可以指定调试器最初从哪个堆栈帧开始?最初运行的 python 文件中最旧的堆栈帧或最新的堆栈帧,或类似的。这对于调试会更有效率。
这是一个简单的例子
import pandas as pd
def test(df): # (A)
df[:,0] = 4 #Bad indexing on dataframe, will cause error
return df
df = test(pd.DataFrame(range(3))) # (B)
为清楚起见添加了结果回溯,(A)、(B)、(C)
In [6]: ---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-6-66730543fac0> in <module>()
----> 1 import codecs, os;__pyfile = codecs.open('''/tmp/py29142W1d''', encoding='''utf-8''');__code = __pyfile.read().encode('''utf-8''');__pyfile.close();os.remove('''/tmp/py29142W1d''');exec(compile(__code, '''/test/stack_frames.py''', 'exec'));
/test/stack_frames.py in <module>()
6
7 if __name__ == '__main__':
(A)----> 8 df = test(pd.DataFrame(range(3)))
/test/stack_frames.py in test(df)
2
3 def test(df):
(B)----> 4 df[:,0] = 4
5 return df
6
/usr/local/lib/python2.7/dist-packages/pandas/core/frame.pyc in __setitem__(self, key, value)
2355 else:
2356 # set column
-> 2357 self._set_item(key, value)
2358
2359 def _setitem_slice(self, key, value):
/usr/local/lib/python2.7/dist-packages/pandas/core/frame.pyc in _set_item(self, key, value)
2421
2422 self._ensure_valid_index(value)
-> 2423 value = self._sanitize_column(key, value)
2424 NDFrame._set_item(self, key, value)
2425
/usr/local/lib/python2.7/dist-packages/pandas/core/frame.pyc in _sanitize_column(self, key, value)
2602
2603 # broadcast across multiple columns if necessary
-> 2604 if key in self.columns and value.ndim == 1:
2605 if (not self.columns.is_unique or
2606 isinstance(self.columns, MultiIndex)):
/usr/local/lib/python2.7/dist-packages/pandas/indexes/base.pyc in __contains__(self, key)
1232
1233 def __contains__(self, key):
-> 1234 hash(key)
1235 # work around some kind of odd cython bug
1236 try:
TypeError: unhashable type
> /usr/local/lib/python2.7/dist-packages/pandas/indexes/base.py(1234)__contains__()
1232
1233 def __contains__(self, key):
(C)-> 1234 hash(key)
1235 # work around some kind of odd cython bug
1236 try:
ipdb>
现在理想情况下,我希望调试器从 (B) 或什至 (A) 处的第二旧帧开始。但绝对不在 (C) 默认情况下。
最佳答案
为自己记录过程的长答案。底部的半工作解决方案:
此处尝试失败:
import sys
import pdb
import pandas as pd
def test(df): # (A)
df[:,0] = 4 #Bad indexing on dataframe, will cause error
return df
mypdb = pdb.Pdb(skip=['pandas.*'])
mypdb.reset()
df = test(pd.DataFrame(range(3))) # (B) # fails.
mypdb.interaction(None, sys.last_traceback) # doesn't work.
The skip argument, if given, must be an iterable of glob-style module name patterns. The debugger will not step into frames that originate in a module that matches one of these patterns.
class Pdb(bdb.Bdb, cmd.Cmd):
_previous_sigint_handler = None
def __init__(self, completekey='tab', stdin=None, stdout=None, skip=None,
nosigint=False, readrc=True):
bdb.Bdb.__init__(self, skip=skip)
[...]
# Post-Mortem interface
def post_mortem(t=None):
# handling the default
if t is None:
# sys.exc_info() returns (type, value, traceback) if an exception is
# being handled, otherwise it returns None
t = sys.exc_info()[2]
if t is None:
raise ValueError("A valid traceback must be passed if no "
"exception is being handled")
p = Pdb()
p.reset()
p.interaction(None, t)
def pm():
post_mortem(sys.last_traceback)
class Bdb:
"""Generic Python debugger base class.
This class takes care of details of the trace facility;
a derived class should implement user interaction.
The standard debugger class (pdb.Pdb) is an example.
"""
def __init__(self, skip=None):
self.skip = set(skip) if skip else None
[...]
def is_skipped_module(self, module_name):
for pattern in self.skip:
if fnmatch.fnmatch(module_name, pattern):
return True
return False
def stop_here(self, frame):
# (CT) stopframe may now also be None, see dispatch_call.
# (CT) the former test for None is therefore removed from here.
if self.skip and \
self.is_skipped_module(frame.f_globals.get('__name__')):
return False
if frame is self.stopframe:
if self.stoplineno == -1:
return False
return frame.f_lineno >= self.stoplineno
if not self.stopframe:
return True
return False
很明显,跳过列表不用于事后分析。为了解决这个问题,我创建了一个覆盖设置方法的自定义类。
import pdb
class SkipPdb(pdb.Pdb):
def setup(self, f, tb):
# This is unchanged
self.forget()
self.stack, self.curindex = self.get_stack(f, tb)
while tb:
# when setting up post-mortem debugging with a traceback, save all
# the original line numbers to be displayed along the current line
# numbers (which can be different, e.g. due to finally clauses)
lineno = pdb.lasti2lineno(tb.tb_frame.f_code, tb.tb_lasti)
self.tb_lineno[tb.tb_frame] = lineno
tb = tb.tb_next
self.curframe = self.stack[self.curindex][0]
# This loop is new
while self.is_skipped_module(self.curframe.f_globals.get('__name__')):
self.curindex -= 1
self.stack.pop()
self.curframe = self.stack[self.curindex][0]
# The rest is unchanged.
# The f_locals dictionary is updated from the actual frame
# locals whenever the .f_locals accessor is called, so we
# cache it here to ensure that modifications are not overwritten.
self.curframe_locals = self.curframe.f_locals
return self.execRcLines()
def pm(self):
self.reset()
self.interaction(None, sys.last_traceback)
如果您将其用作:
x = 42
df = test(pd.DataFrame(range(3))) # (B) # fails.
# fails. Then do:
mypdb = SkipPdb(skip=['pandas.*'])
mypdb.pm()
>> <ipython-input-36-e420cf1b80b2>(2)<module>()
>-> df = test(pd.DataFrame(range(3))) # (B) # fails.
> (Pdb) l
> 1 x = 42
> 2 -> df = test(pd.DataFrame(range(3))) # (B) # fails.
> [EOF]
您已进入正确的框架。现在您只是需要弄清楚 ipython 如何调用它们的 pdb pm/post_mortem 函数,并创建一个类似的脚本。哪个appears to be hard ,所以我几乎放弃了。
这也不是一个很好的实现。它假定您要跳过的帧位于堆栈的顶部,并且会产生其他奇怪的结果。例如。 df.apply 的输入函数中的错误会产生一些非常奇怪的东西。
TLDR:stdlib 不支持,但您可以创建自己的调试器类,但要使其与 IPython 调试器一起使用并非易事。
关于python - 发生异常后在最旧的堆栈帧中启动 python 调试器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40429957/
关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。
最近,当我启动我的Rails服务器时,我收到了一长串警告。虽然它不影响我的应用程序,但我想知道如何解决这些警告。我的估计是imagemagick以某种方式被调用了两次?当我在警告前后检查我的git日志时。我想知道如何解决这个问题。-bcrypt-ruby(3.1.2)-better_errors(1.0.1)+bcrypt(3.1.7)+bcrypt-ruby(3.1.5)-bcrypt(>=3.1.3)+better_errors(1.1.0)bcrypt和imagemagick有关系吗?/Users/rbchris/.rbenv/versions/2.0.0-p247/lib/ru
我正在学习Rails,并阅读了关于乐观锁的内容。我已将类型为integer的lock_version列添加到我的articles表中。但现在每当我第一次尝试更新记录时,我都会收到StaleObjectError异常。这是我的迁移:classAddLockVersionToArticle当我尝试通过Rails控制台更新文章时:article=Article.first=>#我这样做:article.title="newtitle"article.save我明白了:(0.3ms)begintransaction(0.3ms)UPDATE"articles"SET"title"='dwdwd
在Cooper的书BeginningRuby中,第166页有一个我无法重现的示例。classSongincludeComparableattr_accessor:lengthdef(other)@lengthother.lengthenddefinitialize(song_name,length)@song_name=song_name@length=lengthendenda=Song.new('Rockaroundtheclock',143)b=Song.new('BohemianRhapsody',544)c=Song.new('MinuteWaltz',60)a.betwee
GivenIamadumbprogrammerandIamusingrspecandIamusingsporkandIwanttodebug...mmm...let'ssaaay,aspecforPhone.那么,我应该把“require'ruby-debug'”行放在哪里,以便在phone_spec.rb的特定点停止处理?(我所要求的只是一个大而粗的箭头,即使是一个有挑战性的程序员也能看到:-3)我已经尝试了很多位置,除非我没有正确测试它们,否则会发生一些奇怪的事情:在spec_helper.rb中的以下位置:require'rubygems'require'spork'
我早就知道Ruby中的“常量”(即大写的变量名)不是真正常量。与其他编程语言一样,对对象的引用是唯一存储在变量/常量中的东西。(侧边栏:Ruby确实具有“卡住”引用对象不被修改的功能,据我所知,许多其他语言都没有提供这种功能。)所以这是我的问题:当您将一个值重新分配给常量时,您会收到如下警告:>>FOO='bar'=>"bar">>FOO='baz'(irb):2:warning:alreadyinitializedconstantFOO=>"baz"有没有办法强制Ruby抛出异常而不是打印警告?很难弄清楚为什么有时会发生重新分配。 最佳答案
使用Ruby1.9.2运行IDE提示说需要gemruby-debug-base19x并提供安装它。但是,在尝试安装它时会显示消息Failedtoinstallgems.Followinggemswerenotinstalled:C:/ProgramFiles(x86)/JetBrains/RubyMine3.2.4/rb/gems/ruby-debug-base19x-0.11.30.pre2.gem:Errorinstallingruby-debug-base19x-0.11.30.pre2.gem:The'linecache19'nativegemrequiresinstall
这个问题在这里已经有了答案:关闭10年前。PossibleDuplicate:Pythonconditionalassignmentoperator对于这样一个简单的问题表示歉意,但是谷歌搜索||=并不是很有帮助;)Python中是否有与Ruby和Perl中的||=语句等效的语句?例如:foo="hey"foo||="what"#assignfooifit'sundefined#fooisstill"hey"bar||="yeah"#baris"yeah"另外,类似这样的东西的通用术语是什么?条件分配是我的第一个猜测,但Wikipediapage跟我想的不太一样。
在启用Rack::Deflater来gzip我的响应主体时偶然发现了一些奇怪的东西。也许我遗漏了一些东西,但启用此功能后,响应被压缩,但是资源的ETag在每个请求上都会发生变化。这会强制应用程序每次都响应,而不是发送304。这在没有启用Rack::Deflater的情况下有效,我已经验证页面源没有改变。我正在运行一个使用thin作为Web服务器的Rails应用程序。Gemfile.lockhttps://gist.github.com/2510816有没有什么方法可以让我从Rack中间件获得更多的输出,这样我就可以看到发生了什么?提前致谢。 最佳答案
什么是ruby的rack或python的Java的wsgi?还有一个路由库。 最佳答案 来自Python标准PEP333:Bycontrast,althoughJavahasjustasmanywebapplicationframeworksavailable,Java's"servlet"APImakesitpossibleforapplicationswrittenwithanyJavawebapplicationframeworktoruninanywebserverthatsupportstheservletAPI.ht