-
Notifications
You must be signed in to change notification settings - Fork 11
Expand file tree
/
Copy pathDebugging.html
More file actions
595 lines (569 loc) · 44.5 KB
/
Debugging.html
File metadata and controls
595 lines (569 loc) · 44.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
<!DOCTYPE html>
<html class="writer-html5" lang="en" >
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Debugging — Programming in Python 7.0 documentation</title>
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
<link rel="stylesheet" href="../_static/css/theme.css" type="text/css" />
<!--[if lt IE 9]>
<script src="../_static/js/html5shiv.min.js"></script>
<![endif]-->
<script data-url_root="../" id="documentation_options" src="../_static/documentation_options.js"></script>
<script src="../_static/jquery.js"></script>
<script src="../_static/underscore.js"></script>
<script src="../_static/doctools.js"></script>
<script src="../_static/js/theme.js"></script>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
<link rel="next" title="No SQL Databases" href="NoSQL.html" />
<link rel="prev" title="Logging and the logging module" href="Logging.html" />
</head>
<body class="wy-body-for-nav">
<div class="wy-grid-for-nav">
<nav data-toggle="wy-nav-shift" class="wy-nav-side">
<div class="wy-side-scroll">
<div class="wy-side-nav-search" style="background: #4b2e83" >
<a href="../index.html">
<img src="../_static/UWPCE_logo_full.png" class="logo" alt="Logo"/>
</a>
<div role="search">
<form id="rtd-search-form" class="wy-form" action="../search.html" method="get">
<input type="text" name="q" placeholder="Search docs" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
</div>
</div><div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="Navigation menu">
<p class="caption" role="heading"><span class="caption-text">Topics in the Program</span></p>
<ul class="current">
<li class="toctree-l1"><a class="reference internal" href="../topics/01-setting_up/index.html">1. Setting up your Environment</a></li>
<li class="toctree-l1"><a class="reference internal" href="../topics/02-basic_python/index.html">2. Basic Python</a></li>
<li class="toctree-l1"><a class="reference internal" href="../topics/03-recursion_booleans/index.html">3. Booleans and Recursion</a></li>
<li class="toctree-l1"><a class="reference internal" href="../topics/04-sequences_iteration/index.html">4. Sequences and Iteration</a></li>
<li class="toctree-l1"><a class="reference internal" href="../topics/05-text_handling/index.html">5. Basic Text Handling</a></li>
<li class="toctree-l1"><a class="reference internal" href="../topics/06-exceptions/index.html">6. Exception Handling</a></li>
<li class="toctree-l1"><a class="reference internal" href="../topics/07-unit_testing/index.html">7. Unit Testing</a></li>
<li class="toctree-l1"><a class="reference internal" href="../topics/08-dicts_sets/index.html">8. Dictionaries and Sets</a></li>
<li class="toctree-l1"><a class="reference internal" href="../topics/09-files/index.html">9. File Handling</a></li>
<li class="toctree-l1"><a class="reference internal" href="../topics/10-modules_packages/index.html">10. Modules and Packages</a></li>
<li class="toctree-l1"><a class="reference internal" href="../topics/11-argument_passing/index.html">11. Advanced Argument Passing</a></li>
<li class="toctree-l1"><a class="reference internal" href="../topics/12-comprehensions/index.html">12. Comprehensions</a></li>
<li class="toctree-l1"><a class="reference internal" href="../topics/13-intro_oo/index.html">13. Intro to Object Oriented Programing</a></li>
<li class="toctree-l1"><a class="reference internal" href="../topics/14-magic_methods/index.html">14. Properties and Magic Methods</a></li>
<li class="toctree-l1"><a class="reference internal" href="../topics/15-subclassing/index.html">15. Subclassing and Inheritance</a></li>
<li class="toctree-l1"><a class="reference internal" href="../topics/16-multiple_inheritance/index.html">16. Multiple Inheritance</a></li>
<li class="toctree-l1"><a class="reference internal" href="../topics/17-functional_programming/index.html">17. Introduction to Functional Programming</a></li>
<li class="toctree-l1"><a class="reference internal" href="../topics/18-advanced_testing/index.html">18. Advanced Testing</a></li>
<li class="toctree-l1 current"><a class="reference internal" href="../topics/99-extras/index.html">19. Extra Topics</a><ul class="current">
<li class="toctree-l2"><a class="reference internal" href="Pep8.html">Coding Style and Linting</a></li>
<li class="toctree-l2"><a class="reference internal" href="CodeReviews.html">Code Reviews</a></li>
<li class="toctree-l2"><a class="reference internal" href="PersistanceAndSerialization.html">Persistence and Serialization</a></li>
<li class="toctree-l2"><a class="reference internal" href="Unicode.html">Unicode in Python</a></li>
<li class="toctree-l2"><a class="reference internal" href="IteratorsAndGenerators.html">Iterators and Generators</a></li>
<li class="toctree-l2"><a class="reference internal" href="Decorators.html">Decorators</a></li>
<li class="toctree-l2"><a class="reference internal" href="../exercises/mailroom/mailroom-decorator.html">Mailroom – Decoratoring it</a></li>
<li class="toctree-l2"><a class="reference internal" href="ContextManagers.html">Context Managers</a></li>
<li class="toctree-l2"><a class="reference internal" href="../exercises/context-managers-exercise.html">A Couple Handy Context Managers</a></li>
<li class="toctree-l2"><a class="reference internal" href="MetaProgramming.html">Metaprogramming</a></li>
<li class="toctree-l2"><a class="reference internal" href="../exercises/mailroom/mailroom-meta.html">Mailroom – metaprogramming it!</a></li>
<li class="toctree-l2"><a class="reference internal" href="Logging.html">Logging and the logging module</a></li>
<li class="toctree-l2 current"><a class="current reference internal" href="#">Debugging</a></li>
<li class="toctree-l2"><a class="reference internal" href="NoSQL.html">No SQL Databases</a></li>
<li class="toctree-l2"><a class="reference internal" href="GraphDatabases.html">Graph Databases</a></li>
<li class="toctree-l2"><a class="reference internal" href="Concurrency.html">Concurrent Programming</a></li>
<li class="toctree-l2"><a class="reference internal" href="Async.html">Asychronous Programming</a></li>
<li class="toctree-l2"><a class="reference internal" href="Coroutines.html">Notes on Coroutines</a></li>
<li class="toctree-l2"><a class="reference internal" href="ThreadingMultiprocessing.html">Threading and multiprocessing</a></li>
<li class="toctree-l2"><a class="reference internal" href="../exercises/threaded_downloader.html">Threaded Web Scraper</a></li>
<li class="toctree-l2"><a class="reference internal" href="Profiling.html">Performance and Profiling</a></li>
</ul>
</li>
</ul>
</div>
</div>
</nav>
<section data-toggle="wy-nav-shift" class="wy-nav-content-wrap"><nav class="wy-nav-top" aria-label="Mobile navigation menu" style="background: #4b2e83" >
<i data-toggle="wy-nav-top" class="fa fa-bars"></i>
<a href="../index.html">Programming in Python</a>
</nav>
<div class="wy-nav-content">
<div class="rst-content style-external-links">
<div role="navigation" aria-label="Page navigation">
<ul class="wy-breadcrumbs">
<li><a href="../index.html" class="icon icon-home"></a> »</li>
<li><a href="../topics/99-extras/index.html"><span class="section-number">19. </span>Extra Topics</a> »</li>
<li>Debugging</li>
<li class="wy-breadcrumbs-aside">
<a href="../_sources/modules/Debugging.rst.txt" rel="nofollow"> View page source</a>
</li>
</ul><div class="rst-breadcrumbs-buttons" role="navigation" aria-label="Sequential page navigation">
<a href="Logging.html" class="btn btn-neutral float-left" title="Logging and the logging module" accesskey="p"><span class="fa fa-arrow-circle-left" aria-hidden="true"></span> Previous</a>
<a href="NoSQL.html" class="btn btn-neutral float-right" title="No SQL Databases" accesskey="n">Next <span class="fa fa-arrow-circle-right" aria-hidden="true"></span></a>
</div>
<hr/>
</div>
<div role="main" class="document" itemscope="itemscope" itemtype="http://schema.org/Article">
<div itemprop="articleBody">
<div class="section" id="debugging">
<span id="id1"></span><h1>Debugging<a class="headerlink" href="#debugging" title="Permalink to this headline"></a></h1>
<p>System Development with Python</p>
<ul class="simple">
<li><p>Maria McKinley</p></li>
</ul>
<p><code class="docutils literal notranslate"><span class="pre">parody@uw.edu</span></code></p>
<div class="section" id="topics">
<h2>Topics<a class="headerlink" href="#topics" title="Permalink to this headline"></a></h2>
<ul class="simple">
<li><p>The call stack</p></li>
<li><p>Exceptions</p></li>
<li><p>Debugging</p></li>
</ul>
<div class="section" id="the-call-stack">
<h3>The Call Stack<a class="headerlink" href="#the-call-stack" title="Permalink to this headline"></a></h3>
<ul class="simple">
<li><p>A stack is a Last-In-First-Out (LIFO) data structure (stack of plates)</p></li>
<li><p>The call stack is a stack data structure that stores information
about the current active function calls</p></li>
<li><p>The objects in the stack are known as “stack frames”. Each frame
contains the arguments passed to the function, space for local
variables, and the return address</p></li>
<li><p>It is usually (unintuitively) displayed like an upside-down stack of
plates, with most recent frame on the bottom.</p></li>
<li><p>When a function is called, a stack frame is created for it and pushed
onto the stack</p></li>
<li><p>When a function returns, it is popped off the stack and control is
passed to the next item in the stack. If the stack is empty, the
program exits</p></li>
</ul>
<p><a class="reference external" href="http://www.pythontutor.com/visualize.html#mode=edit">http://www.pythontutor.com/visualize.html#mode=edit</a></p>
</div>
<div class="section" id="visualize-the-stack">
<h3>Visualize the stack!<a class="headerlink" href="#visualize-the-stack" title="Permalink to this headline"></a></h3>
<a class="reference internal image-reference" href="../_images/program_callstack.png"><img alt="../_images/program_callstack.png" src="../_images/program_callstack.png" style="height: 580px;" /></a>
<p class="rubric">How deep can that stack be?</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span>
<span class="k">def</span> <span class="nf">recurse</span><span class="p">():</span>
<span class="k">global</span> <span class="n">i</span>
<span class="n">i</span> <span class="o">+=</span> <span class="mi">1</span>
<span class="nb">print</span><span class="p">(</span><span class="n">i</span><span class="p">)</span>
<span class="n">recurse</span><span class="p">()</span>
<span class="n">recurse</span><span class="p">()</span>
</pre></div>
</div>
<p>That value can be changed with sys.setrecursionlimit(N)</p>
<p>If we try to put more than sys.getrecursionlimit() frames on the stack, we get a RecursionError (derived from RuntimeError), which is python’s version of StackOverflow</p>
<div class="highlight-ipython notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">inspect</span>
<span class="k">def</span> <span class="nf">recurse</span><span class="p">(</span><span class="n">limit</span><span class="p">):</span>
<span class="n">local_variable</span> <span class="o">=</span> <span class="s1">'.'</span> <span class="o">*</span> <span class="n">limit</span>
<span class="nb">print</span><span class="p">(</span><span class="n">limit</span><span class="p">,</span> <span class="n">inspect</span><span class="o">.</span><span class="n">getargvalues</span><span class="p">(</span><span class="n">inspect</span><span class="o">.</span><span class="n">currentframe</span><span class="p">()))</span>
<span class="k">if</span> <span class="n">limit</span> <span class="o"><=</span> <span class="mi">0</span><span class="p">:</span>
<span class="k">return</span>
<span class="n">recurse</span><span class="p">(</span><span class="n">limit</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span>
<span class="k">return</span>
<span class="n">recurse</span><span class="p">(</span><span class="mi">3</span><span class="p">)</span>
</pre></div>
</div>
<p>module <a class="reference external" href="https://docs.python.org/3/library/inspect.html">https://docs.python.org/3/library/inspect.html</a></p>
<p>more on recursion <a class="reference external" href="http://www.mariakathryn.net/Blog/60">http://www.mariakathryn.net/Blog/60</a></p>
</div>
<div class="section" id="exceptions">
<h3>Exceptions<a class="headerlink" href="#exceptions" title="Permalink to this headline"></a></h3>
<p>It’s easier to ask for forgiveness than permission (Grace Hopper)</p>
<p>When either the interpreter or your own code detects an error condition,
an exception will be raised</p>
<p>The exception will bubble up the call stack until it is handled. If it’s
not handled anywhere in the stack, the interpreter will exit the program.</p>
<p>At each level in the stack, a handler can either:</p>
<ul class="simple">
<li><p>let it bubble through (the default if no handler)</p></li>
<li><p>swallow the exception (the default for a handler)</p></li>
<li><p>catch the exception and raise it again</p></li>
<li><p>catch the exception and raise a new one</p></li>
</ul>
</div>
<div class="section" id="handling-exceptions">
<h3>Handling exceptions<a class="headerlink" href="#handling-exceptions" title="Permalink to this headline"></a></h3>
<p>The most basic form uses the builtins try and except</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">temp_f_to_c</span><span class="p">(</span><span class="n">var</span><span class="p">):</span>
<span class="k">try</span><span class="p">:</span>
<span class="k">return</span><span class="p">(</span><span class="nb">float</span><span class="p">(</span><span class="n">var</span><span class="p">)</span> <span class="o">-</span> <span class="mi">32</span><span class="p">)</span><span class="o">/</span><span class="mf">1.8000</span>
<span class="k">except</span> <span class="ne">ValueError</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
<span class="nb">print</span><span class="p">(</span><span class="s2">"The argument does not contain numbers</span><span class="se">\n</span><span class="s2">"</span><span class="p">,</span> <span class="n">e</span><span class="p">)</span>
</pre></div>
</div>
</div>
<div class="section" id="a-few-more-builtins-for-exception-handling-finally-else-and-raise">
<h3>A few more builtins for exception handling: finally, else, and raise<a class="headerlink" href="#a-few-more-builtins-for-exception-handling-finally-else-and-raise" title="Permalink to this headline"></a></h3>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="n">x</span> <span class="o">=</span> <span class="mi">5</span>
<span class="n">y</span> <span class="o">=</span> <span class="s2">"this"</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">result</span> <span class="o">=</span> <span class="n">x</span> <span class="o">/</span> <span class="n">y</span>
<span class="k">except</span> <span class="p">(</span><span class="ne">ZeroDivisionError</span><span class="p">,</span> <span class="ne">ValueError</span><span class="p">)</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
<span class="nb">print</span><span class="p">(</span><span class="s2">"caught division error or maybe a value error:</span><span class="se">\n</span><span class="s2">"</span><span class="p">,</span> <span class="n">e</span><span class="p">)</span>
<span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span> <span class="c1"># only do this if absolutely necessary, or if planning to re-raise</span>
<span class="n">errors</span> <span class="o">=</span> <span class="n">e</span><span class="o">.</span><span class="n">args</span>
<span class="nb">print</span><span class="p">(</span><span class="s2">"Error(</span><span class="si">{0}</span><span class="s2">)"</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">errors</span><span class="p">))</span>
<span class="c1"># or you can just print e</span>
<span class="nb">print</span><span class="p">(</span><span class="s2">"unhandled, unexpected exception:</span><span class="se">\n</span><span class="s2">"</span><span class="p">,</span> <span class="n">e</span><span class="p">)</span>
<span class="k">raise</span>
<span class="k">else</span><span class="p">:</span>
<span class="nb">print</span><span class="p">(</span><span class="s2">"do this if there is code you want to run only if no exceptions, caught or not"</span><span class="p">)</span>
<span class="nb">print</span><span class="p">(</span><span class="s2">"errors here will not be caught by above excepts"</span><span class="p">)</span>
<span class="k">finally</span><span class="p">:</span>
<span class="nb">print</span><span class="p">(</span><span class="s2">"this is executed no matter what"</span><span class="p">)</span>
<span class="nb">print</span><span class="p">(</span><span class="s1">'this is only printed if there is no uncaught exception'</span><span class="p">)</span>
</pre></div>
</div>
<p>It is even possible to use a try block without the exception clause:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">try</span><span class="p">:</span>
<span class="mi">5</span><span class="o">/</span><span class="mi">0</span>
<span class="k">finally</span><span class="p">:</span>
<span class="nb">print</span><span class="p">(</span><span class="s1">'did it work? why would you do this?'</span><span class="p">)</span>
</pre></div>
</div>
<p class="rubric" id="built-in-exceptions">Built-in exceptions</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">[</span><span class="n">name</span> <span class="k">for</span> <span class="n">name</span> <span class="ow">in</span> <span class="nb">dir</span><span class="p">(</span><span class="n">__builtin__</span><span class="p">)</span> <span class="k">if</span> <span class="s2">"Error"</span> <span class="ow">in</span> <span class="n">name</span><span class="p">]</span>
</pre></div>
</div>
<p>If one of these meets your needs, by all means use it. You can add messages:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">raise</span> <span class="ne">SyntaxError</span><span class="p">(</span><span class="s2">"That was a mispelling"</span><span class="p">)</span>
</pre></div>
</div>
<p>If no builtin exceptions work, define a new exception type by subclassing Exception.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">MyException</span><span class="p">(</span><span class="ne">Exception</span><span class="p">):</span>
<span class="k">pass</span>
<span class="k">raise</span> <span class="n">MyException</span><span class="p">(</span><span class="s2">"An exception doesn't always prove the rule!"</span><span class="p">)</span>
</pre></div>
</div>
<p>It is possible, but discouraged to catch all exceptions.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">try</span><span class="p">:</span>
<span class="n">my_cool_code</span><span class="p">()</span>
<span class="k">except</span><span class="p">:</span>
<span class="nb">print</span><span class="p">(</span><span class="s1">'no idea what the exceptions is, but I caught it'</span><span class="p">)</span>
</pre></div>
</div>
<p>An exception to this exception rule is when you are running a service that should not ever crash,
like a web server. In this case, it is extremely important to have very good logging so that you
have reports of exactly what happened and what exception would have been thrown.</p>
<p class="rubric" id="further-reading">Further reading</p>
<ul class="simple">
<li><p><a class="reference external" href="http://docs.python.org/3/library/exceptions.html">http://docs.python.org/3/library/exceptions.html</a></p></li>
<li><p><a class="reference external" href="http://docs.python.org/3/tutorial/errors.html">http://docs.python.org/3/tutorial/errors.html</a></p></li>
</ul>
</div>
<div class="section" id="id2">
<h3>Debugging<a class="headerlink" href="#id2" title="Permalink to this headline"></a></h3>
<p class="rubric" id="python-debugging">Python Debugging</p>
<ul class="simple">
<li><p>You will spend most of your time as a developer debugging.</p></li>
<li><p>You will spend more time than you expect on google.</p></li>
<li><p>Small, tested functions are easier to debug.</p></li>
<li><p>Find a bug, make a test, so it doesn’t come back</p></li>
</ul>
<div class="section" id="tools">
<h4>Tools<a class="headerlink" href="#tools" title="Permalink to this headline"></a></h4>
<ul class="simple">
<li><p>interpreter hints</p></li>
<li><p>print()</p></li>
<li><p>logging</p></li>
<li><p>assert()</p></li>
<li><p>tests</p></li>
<li><p>debuggers</p></li>
</ul>
</div>
<div class="section" id="the-stack-trace">
<h4>The Stack Trace<a class="headerlink" href="#the-stack-trace" title="Permalink to this headline"></a></h4>
<p>You already know what it looks like. Simple traceback:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>maria$ python3 define.py python
Traceback (most recent call last):
File "define.py", line 15, in <module>
definition = Definitions.article(title)
File "/Users/maria/python/300/Py300/Examples/debugging/wikidef/definitions.py", line 7, in article
return Wikipedia.article(title)
File "/Users/maria/python/300/Py300/Examples/debugging/wikidef/api.py", line 26, in article
contents = json_response['parse']['text']['*']
TypeError: 'method' object is not subscriptable
</pre></div>
</div>
<p>But things can quickly get complicated. You may have already run into stacktraces that go on for a 50 lines or more.</p>
</div>
<div class="section" id="some-helpful-hints-with-stacktraces">
<h4>Some helpful hints with stacktraces:<a class="headerlink" href="#some-helpful-hints-with-stacktraces" title="Permalink to this headline"></a></h4>
<ul class="simple">
<li><p>May seem obvious, but… Read it carefully!</p></li>
<li><p>What is the error? Try reading it aloud.</p></li>
<li><p>The first place to look is the bottom.</p></li>
<li><p>Trace will show the line number and file of exception/calling functions.</p></li>
<li><p>More than likely the error is in your code, not established packages
- look at lines in your code mentioned in the stacktrace first
- Sometimes that error was triggered by something else, and you need to look higher. (probably more than one file in the stacktrace is your code)</p></li>
</ul>
<p>If that fails you…</p>
<ul class="simple">
<li><p>Make sure the code you think is executing is really executing.</p></li>
<li><p>Simplify your code (smallest code that causes bug).</p></li>
<li><p>Debugger</p></li>
<li><p>Save (and print) intermediate results from long expressions</p></li>
<li><p>Try out bits of code at the command line</p></li>
</ul>
<p>If all else fails…</p>
<p>Write out an email that describes the problem:</p>
<ul class="simple">
<li><p>include the stacktrace</p></li>
<li><p>include steps you have taken to find the bug</p></li>
<li><p>inlude the relative function of your code</p></li>
</ul>
<p>Often after writing out this email, you will realize what you forgot to check, and more often than not, this will happen just after you hit send. Good places to send these emails are other people on same project and mailing list for software package. For the purpose of this class, of course, copy it into slack or the class email list.</p>
</div>
<div class="section" id="print">
<h4>Print<a class="headerlink" href="#print" title="Permalink to this headline"></a></h4>
<ul class="simple">
<li><p>print(“my_module.py: my_variable: “, my_variable)</p></li>
<li><p>can use print statements to make sure you are editing a file in the stack</p></li>
</ul>
</div>
<div class="section" id="console-debuggers">
<h4>Console Debuggers<a class="headerlink" href="#console-debuggers" title="Permalink to this headline"></a></h4>
<ul class="simple">
<li><p>pdb/ipdb</p></li>
</ul>
</div>
<div class="section" id="gui-debuggers-more-about-these-below">
<h4>GUI debuggers (more about these below)<a class="headerlink" href="#gui-debuggers-more-about-these-below" title="Permalink to this headline"></a></h4>
<ul class="simple">
<li><p>Winpdb</p></li>
<li><p>IDEs: Eclipse, Wing IDE, PyCharm, Visual Studio Code</p></li>
</ul>
<p class="rubric" id="help-from-the-interpreter">help from the interpreter</p>
<ol class="arabic simple">
<li><p>investigate import issues with -v:</p></li>
</ol>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">python</span> <span class="o">-</span><span class="n">v</span> <span class="n">myscript</span><span class="o">.</span><span class="n">py</span>
</pre></div>
</div>
<p>Verbose (trace import statements)</p>
<ol class="arabic simple" start="2">
<li><p>inspect environment after running script with -i</p></li>
</ol>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">python</span> <span class="o">-</span><span class="n">i</span> <span class="n">myscript</span><span class="o">.</span><span class="n">py</span>
</pre></div>
</div>
<p>Forces interpreter to remain active, and still in scope</p>
</div>
<div class="section" id="useful-tools-from-interpreter">
<h4>Useful tools from interpreter:<a class="headerlink" href="#useful-tools-from-interpreter" title="Permalink to this headline"></a></h4>
<ul class="simple">
<li><p>In IPython, ‘who’ will list all currently defined variables</p></li>
<li><p>locals()</p></li>
<li><p>globals()</p></li>
<li><p>dir()</p></li>
</ul>
<p class="rubric" id="pdb-the-python-debugger"><a class="reference external" href="http://docs.python.org/2/library/pdb.html">Pdb - The Python
Debugger</a></p>
<p class="rubric">Pros:</p>
<ul class="simple">
<li><p>You have it already, ships with the standard library</p></li>
<li><p>Easy remote debugging (since it is non-graphical, see remote-pdb for true remote debugging)</p></li>
<li><p>Works with any development environment</p></li>
</ul>
<p class="rubric">Cons:</p>
<ul class="simple">
<li><p>Steep-ish learning curve</p></li>
<li><p>Easy to get lost in a deep stack</p></li>
<li><p>Watching variables isn’t hard, but non-trivial</p></li>
</ul>
<p class="rubric"><a class="reference external" href="https://docs.python.org/3.7/library/pdb.html">Pdb - The Python Debugger</a></p>
</div>
<div class="section" id="the-4-fold-ways-of-invoking-pdb">
<h4>The 4-fold ways of invoking pdb<a class="headerlink" href="#the-4-fold-ways-of-invoking-pdb" title="Permalink to this headline"></a></h4>
<ul class="simple">
<li><p>Postmortem mode</p></li>
<li><p>Run mode</p></li>
<li><p>Script mode</p></li>
<li><p>Trace mode</p></li>
</ul>
<p>Note: in most cases where you see the word ‘pdb’ in the examples, you
can replace it with ‘ipdb’. ipdb is the ipython enhanced version of pdb
which is mostly compatible, and generally easier to work with. But it
doesn’t ship with Python.</p>
<p class="rubric" id="postmortem-mode">Postmortem mode</p>
<p>For analyzing crashes due to uncaught exceptions</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">python</span> <span class="o">-</span><span class="n">i</span> <span class="n">script</span><span class="o">.</span><span class="n">py</span>
<span class="kn">import</span> <span class="nn">pdb</span><span class="p">;</span> <span class="n">pdb</span><span class="o">.</span><span class="n">pm</span><span class="p">()</span>
</pre></div>
</div>
<p>More info on using Postmortem mode:</p>
<p><a class="reference external" href="http://www.almarklein.org/pm-debugging.html">http://www.almarklein.org/pm-debugging.html</a></p>
<p class="rubric" id="run-mode">Run mode</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">pdb</span><span class="o">.</span><span class="n">run</span><span class="p">(</span><span class="s1">'some.expression()'</span><span class="p">)</span>
</pre></div>
</div>
<p class="rubric" id="script-mode">Script mode</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">python</span> <span class="o">-</span><span class="n">m</span> <span class="n">pdb</span> <span class="n">script</span><span class="o">.</span><span class="n">py</span>
</pre></div>
</div>
<p>“-m [module]” finds [module] in sys.path and executes it as a script</p>
<p class="rubric" id="trace-mode">Trace mode</p>
<p>Insert the following line into your code where you want execution to
halt:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">pdb</span><span class="p">;</span> <span class="n">pdb</span><span class="o">.</span><span class="n">set_trace</span><span class="p">()</span>
</pre></div>
</div>
<p>It’s not always OK/possible to modify your code in order to debug it,
but this is often the quickest way to begin inspecting state</p>
<p class="rubric" id="pdb-in-ipython">pdb in ipython</p>
<div class="highlight-ipython notranslate"><div class="highlight"><pre><span></span><span class="gp">In [2]: </span><span class="n">pdb</span>
<span class="go">Automatic pdb calling has been turned ON</span>
<span class="go">%run app.py</span>
<span class="go"># now halts execution on uncaught exception</span>
</pre></div>
</div>
<p>If you forget to turn on pdb, the magic command <code class="docutils literal notranslate"><span class="pre">%debug</span></code> will activate the
debugger (in ‘post-mortem mode’).</p>
<p class="rubric" id="navigating-pdb">Navigating pdb</p>
<p>The goal of each of the preceding techniques was to get to the pdb
prompt and get to work inspecting state. Most commands can be short-cutted
to the first letter.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">%</span> <span class="n">python</span> <span class="o">-</span><span class="n">m</span> <span class="n">pdb</span> <span class="n">define</span><span class="o">.</span><span class="n">py</span>
<span class="n">pdb</span><span class="o">></span> <span class="n">args</span> <span class="c1"># print arguments and values to current function</span>
<span class="n">pdb</span><span class="o">></span> <span class="n">pp</span> <span class="n">a_variable</span> <span class="c1"># pretty-print a_variable</span>
<span class="n">pdb</span><span class="o">></span> <span class="n">where</span> <span class="c1"># print stack trace, bottom is most recent command</span>
<span class="n">pdb</span><span class="o">></span> <span class="nb">list</span> <span class="c1"># list the code including and surrounding the current running code</span>
</pre></div>
</div>
<p>To repeat the current command, press only the Enter key</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="c1"># execute until current function returns</span>
<span class="n">pdb</span><span class="o">></span> <span class="k">return</span>
<span class="c1"># Execute the current line, stop at the first possible occasion</span>
<span class="n">pdb</span><span class="o">></span> <span class="n">step</span>
<span class="c1"># Continue execution until the next line in the current function is reached or it returns.</span>
<span class="n">pdb</span><span class="o">></span> <span class="nb">next</span>
<span class="c1"># Continue execution until the line with a number greater than the current one is reached</span>
<span class="ow">or</span> <span class="n">until</span> <span class="n">the</span> <span class="n">current</span> <span class="n">frame</span> <span class="n">returns</span><span class="o">.</span> <span class="n">Good</span> <span class="k">for</span> <span class="n">exiting</span> <span class="n">loops</span><span class="o">.</span>
<span class="n">pdb</span><span class="o">></span> <span class="n">until</span>
<span class="c1"># move one level up the stack</span>
<span class="n">pdb</span><span class="o">></span> <span class="n">up</span>
<span class="c1"># move one level down the stack</span>
<span class="n">pdb</span><span class="o">></span> <span class="n">down</span>
<span class="n">pdb</span><span class="o">></span> <span class="k">continue</span> <span class="c1"># goes until next breakpoint or end of program</span>
<span class="c1"># advanced: create commands to be executed on a breakpoint</span>
<span class="n">pdb</span><span class="o">></span> <span class="n">commands</span>
</pre></div>
</div>
<p class="rubric" id="breakpoints">Breakpoints</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">pdb</span><span class="o">></span> <span class="n">help</span> <span class="k">break</span>
<span class="n">b</span><span class="p">(</span><span class="n">reak</span><span class="p">)</span> <span class="p">([</span><span class="n">file</span><span class="p">:]</span><span class="n">lineno</span> <span class="o">|</span> <span class="n">function</span><span class="p">)</span> <span class="p">[,</span> <span class="n">condition</span><span class="p">]</span>
<span class="n">With</span> <span class="n">a</span> <span class="n">line</span> <span class="n">number</span> <span class="n">argument</span><span class="p">,</span> <span class="nb">set</span> <span class="n">a</span> <span class="k">break</span> <span class="n">there</span> <span class="ow">in</span> <span class="n">the</span> <span class="n">current</span>
<span class="n">file</span><span class="o">.</span> <span class="n">With</span> <span class="n">a</span> <span class="n">function</span> <span class="n">name</span><span class="p">,</span> <span class="nb">set</span> <span class="n">a</span> <span class="k">break</span> <span class="n">at</span> <span class="n">first</span> <span class="n">executable</span> <span class="n">line</span>
<span class="n">of</span> <span class="n">that</span> <span class="n">function</span><span class="o">.</span> <span class="n">Without</span> <span class="n">argument</span><span class="p">,</span> <span class="nb">list</span> <span class="nb">all</span> <span class="n">breaks</span><span class="o">.</span> <span class="n">If</span> <span class="n">a</span> <span class="n">second</span>
<span class="n">argument</span> <span class="ow">is</span> <span class="n">present</span><span class="p">,</span> <span class="n">it</span> <span class="ow">is</span> <span class="n">a</span> <span class="n">string</span> <span class="n">specifying</span> <span class="n">an</span> <span class="n">expression</span>
<span class="n">which</span> <span class="n">must</span> <span class="n">evaluate</span> <span class="n">to</span> <span class="n">true</span> <span class="n">before</span> <span class="n">the</span> <span class="nb">breakpoint</span> <span class="ow">is</span> <span class="n">honored</span><span class="o">.</span>
<span class="n">The</span> <span class="n">line</span> <span class="n">number</span> <span class="n">may</span> <span class="n">be</span> <span class="n">prefixed</span> <span class="k">with</span> <span class="n">a</span> <span class="n">filename</span> <span class="ow">and</span> <span class="n">a</span> <span class="n">colon</span><span class="p">,</span>
<span class="n">to</span> <span class="n">specify</span> <span class="n">a</span> <span class="nb">breakpoint</span> <span class="ow">in</span> <span class="n">another</span> <span class="n">file</span> <span class="p">(</span><span class="n">probably</span> <span class="n">one</span> <span class="n">that</span>
<span class="n">hasn</span><span class="s1">'t been loaded yet). The file is searched for on sys.path;</span>
<span class="n">the</span> <span class="o">.</span><span class="n">py</span> <span class="n">suffix</span> <span class="n">may</span> <span class="n">be</span> <span class="n">omitted</span><span class="o">.</span>
</pre></div>
</div>
<p>Can use up, down, where and list to evalutate where you are, and use that to
set a new breakpoint in code coming up. Useful for getting out of rabbit holes.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">pdb</span><span class="o">></span> <span class="k">break</span> <span class="n">api</span><span class="o">.</span><span class="n">py</span><span class="p">:</span><span class="mi">21</span> <span class="c1"># set a breakpoint file:line #</span>
<span class="n">pdb</span><span class="o">></span> <span class="k">break</span> <span class="c1"># list breakpoints</span>
<span class="n">pdb</span><span class="o">></span> <span class="n">clear</span> <span class="mi">1</span> <span class="c1"># get rid of first breakpoint</span>
<span class="n">pdb</span><span class="o">></span> <span class="k">break</span> <span class="mi">35</span> <span class="c1"># set a breakpoint in current file at line 35</span>
<span class="c1"># print lines in range</span>
<span class="n">pdb</span><span class="o">></span> <span class="nb">list</span> <span class="mi">1</span><span class="p">,</span><span class="mi">28</span>
</pre></div>
</div>
<p>You can also delete(clear), disable and enable breakpoints</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">clear</span> <span class="p">[</span><span class="n">bpnumber</span> <span class="p">[</span><span class="n">bpnumber</span><span class="o">...</span><span class="p">]]</span>
<span class="n">disable</span> <span class="p">[</span><span class="n">bpnumber</span> <span class="p">[</span><span class="n">bpnumber</span><span class="o">...</span><span class="p">]]</span>
<span class="n">enable</span> <span class="p">[</span><span class="n">bpnumber</span> <span class="p">[</span><span class="n">bpnumber</span><span class="o">...</span><span class="p">]]</span>
</pre></div>
</div>
<p class="rubric" id="conditional-breakpoints">Conditional Breakpoints</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">pdb</span><span class="o">></span> <span class="k">break</span> <span class="mi">9</span><span class="p">,</span> <span class="n">j</span><span class="o">></span><span class="mi">3</span>
<span class="n">Breakpoint</span> <span class="mi">1</span> <span class="n">at</span> <span class="o">.../</span><span class="n">pdb_break</span><span class="o">.</span><span class="n">py</span><span class="p">:</span><span class="mi">9</span>
<span class="n">pdb</span><span class="o">></span> <span class="k">break</span>
<span class="n">Num</span> <span class="n">Type</span> <span class="n">Disp</span> <span class="n">Enb</span> <span class="n">Where</span>
<span class="mi">1</span> <span class="nb">breakpoint</span> <span class="n">keep</span> <span class="n">yes</span> <span class="n">at</span> <span class="o">.../</span><span class="n">pdb_break</span><span class="o">.</span><span class="n">py</span><span class="p">:</span><span class="mi">9</span>
<span class="n">stop</span> <span class="n">only</span> <span class="k">if</span> <span class="n">j</span><span class="o">></span><span class="mi">3</span>
</pre></div>
</div>
<p>Condition can be used to add a conditional to an existing breakpoint</p>
<p class="rubric">Invoking pdb with pytest</p>
<p>pytest allows one to drop into the PDB prompt via a command line option:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">pytest</span> <span class="o">--</span><span class="n">pdb</span>
</pre></div>
</div>
<p>This will invoke the Python debugger on every failure.
Often you might only want to do this for the first failing
test to understand a certain failure situation:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">pytest</span> <span class="o">-</span><span class="n">x</span> <span class="o">--</span><span class="n">pdb</span> <span class="c1"># drop to PDB on first failure, then end test session</span>
<span class="n">pytest</span> <span class="o">--</span><span class="n">pdb</span> <span class="o">--</span><span class="n">maxfail</span><span class="o">=</span><span class="mi">3</span> <span class="c1"># drop to PDB for first three failures</span>
</pre></div>
</div>
<p>Try some debugging! Here is a fun tutorial intro to pdb that someone created:</p>
<p><a class="reference external" href="https://github.com/spiside/pdb-tutorial">https://github.com/spiside/pdb-tutorial</a></p>
</div>
</div>
<div class="section" id="python-ides">
<h3>Python IDEs<a class="headerlink" href="#python-ides" title="Permalink to this headline"></a></h3>
<p class="rubric">PyCharm</p>
<p>From JetBrains, — integrates some of their vast array of development
tools</p>
<p>Free Community Edition (CE) is available</p>
<p>Good visual debugging support</p>
<p class="rubric">Eclipse</p>
<p>A multi-language IDE</p>
<p>Python support via <a class="reference external" href="http://pydev.org/">http://pydev.org/</a></p>
<p>Automatic variable and expression watching</p>
<p>Supports a lot of debugging features like conditional breakpoints,
provided you look in the right places!</p>
<p>Further reading</p>
<p><a class="reference external" href="http://pydev.org/manual_adv_debugger.html">http://pydev.org/manual_adv_debugger.html</a></p>
<p class="rubric">Visual Studio Code</p>
<p>Visual Studio Code has support for Python</p>
<p>(not the same as the monstrosity that is Visual Studio)</p>
<p><a class="reference external" href="https://code.visualstudio.com/">https://code.visualstudio.com/</a></p>
<p class="rubric">winpdb</p>
<p>A multi platform Python debugger with threading support</p>
<p>Easier to start up and get debugging:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">winpdb</span> <span class="n">your_app</span><span class="o">.</span><span class="n">py</span>
</pre></div>
</div>
<p><a class="reference external" href="http://winpdb.org/tutorial/WinpdbTutorial.html">http://winpdb.org/tutorial/WinpdbTutorial.html</a></p>
</div>
<div class="section" id="remote-debugging">
<h3>Remote debugging<a class="headerlink" href="#remote-debugging" title="Permalink to this headline"></a></h3>
<p>To debug an application running a different Python, even remotely:</p>
<p>remote-pdb</p>
<p><a class="reference external" href="https://pypi.python.org/pypi/remote-pdb">https://pypi.python.org/pypi/remote-pdb</a></p>
</div>
</div>
</div>
</div>
</div>
<footer><div class="rst-footer-buttons" role="navigation" aria-label="Footer">
<a href="Logging.html" class="btn btn-neutral float-left" title="Logging and the logging module" accesskey="p" rel="prev"><span class="fa fa-arrow-circle-left" aria-hidden="true"></span> Previous</a>
<a href="NoSQL.html" class="btn btn-neutral float-right" title="No SQL Databases" accesskey="n" rel="next">Next <span class="fa fa-arrow-circle-right" aria-hidden="true"></span></a>
</div>
<hr/>
<div role="contentinfo">
<p>© Copyright 2020, University of Washington, Natasha Aleksandrova, Christopher Barker, Brian Dorsey, Cris Ewing, Christy Heaton, Jon Jacky, Maria McKinley, Andy Miles, Rick Riehle, Joseph Schilz, Joseph Sheedy, Hosung Song. Creative Commons Attribution-ShareAlike 4.0 license.</p>
</div>
Built with <a href="https://www.sphinx-doc.org/">Sphinx</a> using a
<a href="https://github.com/readthedocs/sphinx_rtd_theme">theme</a>
provided by <a href="https://readthedocs.org">Read the Docs</a>.
</footer>
</div>
</div>
</section>
</div>
<script>
jQuery(function () {
SphinxRtdTheme.Navigation.enable(true);
});
</script>
</body>
</html>