-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy patheffective5.html
769 lines (686 loc) · 30.4 KB
/
effective5.html
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
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
<!DOCTYPE html>
<!--[if IEMobile 7 ]><html class="no-js iem7"><![endif]-->
<!--[if lt IE 9]><html class="no-js lte-ie8"><![endif]-->
<!--[if (gt IE 8)|(gt IEMobile 7)|!(IEMobile)|!(IE)]><!--><html class="no-js" lang="en"><!--<![endif]-->
<head>
<meta charset="utf-8">
<title>Effective Python一人輪読会(Item 75 to 90) — Dreaming in Greater Boston</title>
<meta name="author" content="Kyos">
<!-- http://t.co/dKP3o1e -->
<meta name="HandheldFriendly" content="True">
<meta name="MobileOptimized" content="320">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="/favicon.png" rel="icon">
<link href="/theme/css/main.css" media="screen, projection"
rel="stylesheet" type="text/css">
<link href="//fonts.googleapis.com/css?family=PT+Serif:regular,italic,bold,bolditalic"
rel="stylesheet" type="text/css">
<link href="//fonts.googleapis.com/css?family=PT+Sans:regular,italic,bold,bolditalic"
rel="stylesheet" type="text/css">
</head>
<body>
<header role="banner"><hgroup>
<h1><a href="/">Dreaming in Greater Boston</a></h1>
</hgroup></header>
<nav role="navigation"><ul class="subscription" data-subscription="rss">
</ul>
<ul class="main-navigation">
<li><a href="/pages/about.html">About Me</a></li>
<li >
<a href="/category/blog.html">Blog</a>
</li>
<li >
<a href="/category/english.html">English</a>
</li>
<li >
<a href="/category/linux.html">Linux</a>
</li>
<li class="active">
<a href="/category/python.html">Python</a>
</li>
<li >
<a href="/category/tech.html">Tech</a>
</li>
</ul></nav>
<div id="main">
<div id="content">
<div>
<article class="hentry" role="article">
<header>
<h1 class="entry-title">Effective Python一人輪読会(Item 75 to 90)</h1>
<p class="meta">
<time datetime="2020-08-31T00:00:00-04:00" pubdate>Mon 31 August 2020</time> </p>
</header>
<div class="entry-content"><div id="table-of-contents">
<h2>Table of Contents</h2>
<div id="text-table-of-contents">
<ul>
<li><a href="#orgdec5e69">1. Chapter 9: テストとデバッグ</a>
<ul>
<li><a href="#org0b51bc3">1.1. Item 75: デバッグ用表示にはreprを使え</a></li>
<li><a href="#orgb27fa27">1.2. Item 76: TestCaseのサブクラスを使って関連する挙動を検証せよ</a></li>
<li><a href="#orgf4f3ffb">1.3. Item 77: setUp, tearDown, setUpModule, tearDownModuleを使って各テストを独立させよ</a></li>
<li><a href="#org7d96430">1.4. Item 78: 複雑な依存関係を持つコードをテストするために Mocks を使え</a></li>
<li><a href="#org1ac0c2e">1.5. Item 79: Mockingとテストを容易にするため依存関係をカプセル化せよ</a></li>
<li><a href="#orgceeca19">1.6. Item 80: pdbを使って対話的にデバッグせよ</a></li>
<li><a href="#orgc63be44">1.7. Item 81: メモリの利用状況とリークを調べるためtracemallocを使え</a></li>
</ul>
</li>
<li><a href="#org5ee9a19">2. Chapter 10: コラボレーション</a>
<ul>
<li><a href="#orgf0bb2f2">2.1. Item 82: コミュニティーが作るモジュールをどこで見つけるかを知れ</a></li>
<li><a href="#orgc602522">2.2. Item 83: 隔離された、再現可能な依存関係のために仮想環境を使え</a></li>
<li><a href="#orgf511424">2.3. Item 84: 全ての関数、クラス、モジュールにdocstringsを書け</a></li>
<li><a href="#org9c4dd73">2.4. Item 85: モジュールを管理し、安定したAPIを提供するためにパッケージを使え</a></li>
<li><a href="#org7ed74bb">2.5. Item 86: デプロイ環境をconfigureするためにモジュールスコープのコードを検討せよ</a></li>
<li><a href="#org0619d62">2.6. Item 87: APIから呼び主をinsulateするためにルート例外を定義せよ</a></li>
<li><a href="#orgbc1d770">2.7. Item 88: 循環依存を断ち切る方法を知れ</a></li>
<li><a href="#org93a1bba">2.8. Item 89: リファクタリングと利用の移行促進のために warningを検討せよ</a></li>
<li><a href="#org71dc2ca">2.9. Item 90: バグを取り除くためにtypingを使った静的解析を検討せよ</a></li>
</ul>
</li>
<li><a href="#orgb13a90e">3. 終わりに</a>
<ul>
<li><a href="#orga103549">3.1. 感想</a>
<ul>
<li><a href="#orgf279d18">3.1.1. 内容全般</a></li>
<li><a href="#orgb6e6bc8">3.1.2. この本の読み方</a></li>
<li><a href="#orgb982974">3.1.3. 第2版について</a></li>
<li><a href="#orgb04b71d">3.1.4. 前後参照の多さ</a></li>
<li><a href="#org948ff95">3.1.5. Kindle版</a></li>
</ul>
</li>
<li><a href="#org87eebb3">3.2. その次</a></li>
</ul>
</li>
</ul>
</div>
</div>
<div id="outline-container-orgdec5e69" class="outline-2">
<h2 id="orgdec5e69"><span class="section-number-2">1</span> Chapter 9: テストとデバッグ</h2>
<div class="outline-text-2" id="text-1">
</div>
<div id="outline-container-org0b51bc3" class="outline-3">
<h3 id="org0b51bc3"><span class="section-number-3">1.1</span> Item 75: デバッグ用表示にはreprを使え</h3>
<div class="outline-text-3" id="text-1-1">
<p>
print文を使ったデバッグは有用です。デバッグにおいてはintの5とstrの'5'の違いが重要になってくるので、reprを使って表示するべきです。
</p>
<p>
普通に作ったクラスを表示しても有用な情報は表示されないので、 <code>__repr__</code> を用意するか <code>__dict__</code> を表示します。本書には自分で作ったクラスなら前者をするように書いてありますが、 <code>__repr__</code> 自体が信用できないケースもあるような気がするので、 <code>__dict__</code> だけで十分なような。いや、__dict__は見づらいですね。
</p>
<p>
F-Stringsの <code>{}</code> は <code>f'...{..!r}...'</code> のように <code>!r</code> サフィックスを付けるとrepr扱いになります。
</p>
</div>
</div>
<div id="outline-container-orgb27fa27" class="outline-3">
<h3 id="orgb27fa27"><span class="section-number-3">1.2</span> Item 76: TestCaseのサブクラスを使って関連する挙動を検証せよ</h3>
<div class="outline-text-3" id="text-1-2">
<p>
ここではunittestを勧めていますが、<a href="https://realpython.com/pytest-python-testing/">pytest</a>の方が良さそうです。
</p>
</div>
</div>
<div id="outline-container-orgf4f3ffb" class="outline-3">
<h3 id="orgf4f3ffb"><span class="section-number-3">1.3</span> Item 77: setUp, tearDown, setUpModule, tearDownModuleを使って各テストを独立させよ</h3>
<div class="outline-text-3" id="text-1-3">
<p>
pytestにも<a href="https://docs.pytest.org/en/stable/xunit_setup.html">同様の機能</a>がありますが、よりパワフルなfixtureメカニズムが使えるかも知れません。
</p>
<div class="org-src-container">
<pre class="src src-python">def setup_module(module):
def teardown_module(module):
@classmethod
def setup_clas(cls):
@classmethod
def teardown_class(cls):
def setup_method(self, method):
def teardown_method(self, method):
def setup_function(function):
def teardown_function(function):
</pre>
</div>
</div>
</div>
<div id="outline-container-org7d96430" class="outline-3">
<h3 id="org7d96430"><span class="section-number-3">1.4</span> Item 78: 複雑な依存関係を持つコードをテストするために Mocks を使え</h3>
<div class="outline-text-3" id="text-1-4">
<p>
pytestの<a href="https://docs.pytest.org/en/stable/monkeypatch.html">monkeypatch</a> fixtureが相当するようです。
</p>
</div>
</div>
<div id="outline-container-org1ac0c2e" class="outline-3">
<h3 id="org1ac0c2e"><span class="section-number-3">1.5</span> Item 79: Mockingとテストを容易にするため依存関係をカプセル化せよ</h3>
<div class="outline-text-3" id="text-1-5">
<p>
この節もunittestをベースに話が進むため、斜め読みです。
</p>
<p>
独立した関数をクラスメソッドにしたりすると、テストが容易になる場合があるそうです。テストを読みやすくするためにもリファクタリングするとよい、とのこと。
</p>
</div>
</div>
<div id="outline-container-orgceeca19" class="outline-3">
<h3 id="orgceeca19"><span class="section-number-3">1.6</span> Item 80: pdbを使って対話的にデバッグせよ</h3>
<div class="outline-text-3" id="text-1-6">
<p>
pdbの使い方が衝撃的です。コードの止めたい部分に <code>breakpoint()</code> を埋め込みます。
以下の例では、 <code>if err_2 >= 1:</code> で止めたい条件を絞り込んでいます。
</p>
<div class="org-src-container">
<pre class="src src-python">import math
def compute_rmse(observed, ideal):
total_err_2 = 0
count = 0
for got, wanted in zip(observed, ideal):
err_2 = (got - wanted) ** 2
if err_2 >= 1: # Injected for pdb
breakpoint() # Breakpoint will trigger pdb
total_err_2 += err_2
count += 1
mean_err = total_err_2 / count
rmse = math.sqrt(mean_err)
return rmse
result = compute_rmse(
[1.8, 1.7, 3.2, 6],
[2, 1.5, 3, 5])
print(result)
</pre>
</div>
<p>
この状態で普通に実行すると、 <code>breakpoint()</code> の次の行(の直前)でpdbが起動します。変数を見るなり、ステップ実行するなりします。
</p>
<p>
pdbコマンドチートシート:
</p>
<pre class="example">
s - step; ステップ実行
n - next; 1行実行。関数だったら戻るまで実行。
c - continue; 次のブレークポイントまで実行再開
locals() - ローカル変数表示
help
q - quit
</pre>
<p>
post-mortemデバッグは以下のように実行します。例外が出たらpdbが起動します。変数の値を見るくらいしかできませんが。。。
</p>
<pre class="example">
python -m pdb -c continue <filename>.py
あるいは、
>>> import my_module
>>> my_module.some_func()
Traceback ...<snip>
>>> import pdb; pdb.pm()
</pre>
<p>
これまでprint文デバッグばかりでしたが、pdbも使うようにしたいと思います。
</p>
</div>
</div>
<div id="outline-container-orgc63be44" class="outline-3">
<h3 id="orgc63be44"><span class="section-number-3">1.7</span> Item 81: メモリの利用状況とリークを調べるためtracemallocを使え</h3>
<div class="outline-text-3" id="text-1-7">
<p>
まずはメモリを浪費する準備です。
</p>
<div class="org-src-container">
<pre class="src src-python">import os
class MyObject:
def __init__(self):
self.data = os.urandom(100)
def get_data():
values = []
for _ in range(100):
obj = MyObject()
values.append(obj)
return values
def run():
deep_values = []
for _ in range(100):
deep_values.append(get_data())
return deep_values
</pre>
</div>
<p>
tracemallocを使います。メモリ浪費関数(<code>run()</code>)の前後でメモリのスナップショットを取り、差分を見ます。
</p>
<div class="org-src-container">
<pre class="src src-python">import tracemalloc
tracemalloc.start(10) # Set stack depth
time1 = tracemalloc.take_snapshot()
x = run()
time2 = tracemalloc.take_snapshot()
stats = time2.compare_to(time1, 'lineno')
for stat in stats[:3]:
print(stat)
>>>
t.py:4: size=2314 KiB (+2314 KiB), count=29993 (+29993), average=79 B
t.py:9: size=469 KiB (+469 KiB), count=10001 (+10001), average=48 B
t.py:10: size=82.8 KiB (+82.8 KiB), count=100 (+100), average=848 B
</pre>
</div>
</div>
</div>
</div>
<div id="outline-container-org5ee9a19" class="outline-2">
<h2 id="org5ee9a19"><span class="section-number-2">2</span> Chapter 10: コラボレーション</h2>
<div class="outline-text-2" id="text-2">
</div>
<div id="outline-container-orgf0bb2f2" class="outline-3">
<h3 id="orgf0bb2f2"><span class="section-number-3">2.1</span> Item 82: コミュニティーが作るモジュールをどこで見つけるかを知れ</h3>
<div class="outline-text-3" id="text-2-1">
<p>
Python Package Index (PyPI)はPythonパッケージのセントラルレポジトリです。PyPIからパッケージをインストールするには pip を使います。
</p>
</div>
</div>
<div id="outline-container-orgc602522" class="outline-3">
<h3 id="orgc602522"><span class="section-number-3">2.2</span> Item 83: 隔離された、再現可能な依存関係のために仮想環境を使え</h3>
<div class="outline-text-3" id="text-2-2">
<p>
はい、venvなら使っています。
</p>
</div>
</div>
<div id="outline-container-orgf511424" class="outline-3">
<h3 id="orgf511424"><span class="section-number-3">2.3</span> Item 84: 全ての関数、クラス、モジュールにdocstringsを書け</h3>
<div class="outline-text-3" id="text-2-3">
<p>
docstringsを書きましょう。ただし、type annotationsと重複する情報は不要です。
</p>
<p>
docstringsは <code>__doc__</code> でアクセスできます。
</p>
<div class="org-src-container">
<pre class="src src-python">print(repr(some_func.__doc__))
</pre>
</div>
<p>
ビルトインの <code>pydoc</code> モジュールはWebサーバーを立ち上げ、自作のモジュールも含めてアクセス可能な全てのPythonドキュメントが見られるようになります。
</p>
<div class="org-src-container">
<pre class="src src-python">$ python -m pydoc -p 1234
Server ready at http://localhost:1234/
Server commands: [b]rowser, [q]uit
server> b
</pre>
</div>
</div>
</div>
<div id="outline-container-org9c4dd73" class="outline-3">
<h3 id="org9c4dd73"><span class="section-number-3">2.4</span> Item 85: モジュールを管理し、安定したAPIを提供するためにパッケージを使え</h3>
<div class="outline-text-3" id="text-2-4">
<p>
ディレクトリに <code>__init__.py</code> を入れることでパッケージが定義されます。パッケージの第1の目的は、ネームスペースを分けることです。モジュールは一つのファイルです。
</p>
<p>
異なるパッケージやモジュールから同名のファイルを import する場合、 <code>as</code> で区別しないと後のimportで上書きされてしまいます。
</p>
<div class="org-src-container">
<pre class="src src-python">from xxxx.xxxx import inspect as xxxx_inspect
from yyyy.yyyy import inspect as yyyy_inspect
</pre>
</div>
<p>
公開するAPIを限定したい場合に <code>__all__</code> のスペシャルアトリビュートが使えます。 <code>__all__</code> の値がパブリックAPIとして公開する名前のリストになっています。かなりの規模にならない限り <code>__all__</code> は不要です。
</p>
<p>
<code>__init__.py</code> で <code>__all__</code> をaggregateする例:
</p>
<div class="org-src-container">
<pre class="src src-python">__all__ = []
from . models import *
__all__ += models.__all__
from . utils import *
__all__ += utils.__all__
</pre>
</div>
</div>
</div>
<div id="outline-container-org7ed74bb" class="outline-3">
<h3 id="org7ed74bb"><span class="section-number-3">2.5</span> Item 86: デプロイ環境をconfigureするためにモジュールスコープのコードを検討せよ</h3>
<div class="outline-text-3" id="text-2-5">
<p>
複数の種類のデプロイ環境が考えられます。OSの種類、開発環境、テスト環境、等。これらはモジュールスコープの普通のPythonステートメントにて区別します。例えば os.environ 環境変数を見るなど。複雑になってきたら、設定ファイルで区別するようにします。
</p>
</div>
</div>
<div id="outline-container-org0619d62" class="outline-3">
<h3 id="org0619d62"><span class="section-number-3">2.6</span> Item 87: APIから呼び主をinsulateするためにルート例外を定義せよ</h3>
<div class="outline-text-3" id="text-2-6">
<p>
モジュールにおいてルート例外を定義するメリットは2つあります。
</p>
<ol class="org-ol">
<li>APIの呼び側のエラーハンドリングミスがわかる</li>
<li>API提供側の検討漏れがわかる</li>
</ol>
<p>
API側でルート例外を定義した例:
</p>
<div class="org-src-container">
<pre class="src src-python">class RootError(Exception):
pass
class InvalidValueError(RootError):
pass
class InvalidLengthError(RootError):
pass
def some_func(name, value):
if len(name) >= 10:
raise InvalidLengthError('name length must be 9 or less')
if value < 0:
raise InvalidValueError('value must be 0 or higher')
return name + str(value)
</pre>
</div>
<p>
上記において、API利用側が <code>InvalidValueError</code> のハンドリングしかしていない時に <code>InvalidLengthError</code> 例外が上がると、利用側のエラーハンドリングミスであることがわかります。
</p>
<p>
もしPython標準の <code>Exception</code> が上がったときには、API提供側のコードに検討漏れがあったことがわかります。
</p>
<p>
更に、中間の例外を定義すると例外のカテゴリー分けが可能です。実際に上げるエラーは中間例外を継承した具体的な例外です。
</p>
<div class="org-src-container">
<pre class="src src-python">class RootError(Exception): # ルート
pass
class ValueError(RootError): # 中間
pass
class NameError(RootError): # 中間
pass
...
</pre>
</div>
</div>
</div>
<div id="outline-container-orgbc1d770" class="outline-3">
<h3 id="orgbc1d770"><span class="section-number-3">2.7</span> Item 88: 循環依存を断ち切る方法を知れ</h3>
<div class="outline-text-3" id="text-2-7">
<p>
循環依存(import)になったら、相互依存部分を別のモジュールに切り出して依存ツリーのbottomに置くようにリファクタリングすることが望ましいです。
</p>
<p>
そこまでやらずに済む手っ取り早い方法としては、関数等の中に問題のimportを持ってくるダイナミックインポートをすることが考えられます。実行速度が低下する、エラーが出るタイミングが遅くなるなどの副作用があります。
</p>
</div>
</div>
<div id="outline-container-org93a1bba" class="outline-3">
<h3 id="org93a1bba"><span class="section-number-3">2.8</span> Item 89: リファクタリングと利用の移行促進のために warningを検討せよ</h3>
<div class="outline-text-3" id="text-2-8">
<p>
APIのI/Fに変更を入れた場合、warningを使って利用者に移行の促進をすることができます。 <code>warnings.warn()</code> の <code>stacklevel</code> 引数により、どのレベルの呼び主にwarningを出力するかを指定できます。
</p>
<div class="org-src-container">
<pre class="src src-python">import warnings
def require(name, value, default):
if value is not None:
return value
warnings.warn(
f'{name} will be required soon, update your code',
DeprecationWarning,
stacklevel=3)
return default
def print_distance(speed, duration, *,
speed_units=None,
time_units=None,
distance_units=None):
speed_units = require('speed_units', speed_units, 'mph')
time_units = require('time_units', time_units, 'hours')
distance_units = require('distance_units', distance_units, 'miles')
norm_speed = convert(speed, speed_units)
norm_duration = convert(duration, time_units)
norm_distance = norm_speed * norm_duration
distance = localize(norm_distance, distance_units)
print(f'{distance} {distance_units}')
</pre>
</div>
<p>
実行すると以下のようになりました。エラーと違って、コードの挙動には影響しません。
</p>
<div class="org-src-container">
<pre class="src src-python">import contextlib
import io
fake_stderr = io.StringIO()
with contextlib.redirect_stderr(fake_stderr):
print_distance(1000, 3,
speed_units='meters',
time_units='seconds')
print(fake_stderr.getvalue())
>>>
1.8641182099494205 miles
t.py:46: DeprecationWarning: distance_units will be required soon, update your code
print_distance(1000, 3,
</pre>
</div>
<p>
warningはエラーにすることもできます。 <code>-W error</code> を指定します。指定した場合には、実行が途中で終わって最後のdoneメッセージが表示されないことがわかります。
</p>
<div class="org-src-container">
<pre class="src src-python">import warnings
print('begin')
warnings.warn('This usage is deprecated',
DeprecationWarning)
print('done')
>>>
(blg) ~/Documents/AW/py/blg % python t.py # 普通に起動
begin
t.py:3: DeprecationWarning: This usage is deprecated
warnings.warn('This usage is deprecated',
done
(blg) ~/Documents/AW/py/blg % python -W error t.py # エラーを指定
begin
Traceback (most recent call last):
File "t.py", line 3, in <module>
warnings.warn('This usage is deprecated',
DeprecationWarning: This usage is deprecated
</pre>
</div>
<p>
warningを抑止することもできます。
</p>
<div class="org-src-container">
<pre class="src src-python">warnings.simplefilter('ignore')
warnings.warn('How about this?')
</pre>
</div>
<p>
よりよいアプローチは、ログにリダイレクトすることです。logging.captureWarningsを呼んで、対応するpy.warningsロガーを設定します。
</p>
<div class="org-src-container">
<pre class="src src-python">import io
import logging
import warnings
fake_stderr = io.StringIO()
handler = logging.StreamHandler(fake_stderr)
formatter = logging.Formatter(
'%(asctime)-15s WARNING] %(message)s')
handler.setFormatter(formatter)
logging.captureWarnings(True)
logger = logging.getLogger('py.warnings')
logger.addHandler(handler)
logger.setLevel(logging.DEBUG)
warnings.resetwarnings()
warnings.simplefilter('default')
warnings.warn('This will go to the logs output')
print(fake_stderr.getvalue())
>>>
2020-09-01 08:00:24,490 WARNING] t.py:17: UserWarning: This will go to the logs output
warnings.warn('This will go to the logs output')
</pre>
</div>
<p>
あれ、どこのファイルに出力されているのでしょう??? /var/log/system.logには無さそうですが。。。(macOSです)
</p>
</div>
</div>
<div id="outline-container-org71dc2ca" class="outline-3">
<h3 id="org71dc2ca"><span class="section-number-3">2.9</span> Item 90: バグを取り除くためにtypingを使った静的解析を検討せよ</h3>
<div class="outline-text-3" id="text-2-9">
<p>
type annotationsはコードの実行にはほとんど関係しませんが、静的解析でタイプエラーを見つけるのに役に立ちます。これまで何度か出てきていますが、こういうやつです:
</p>
<div class="org-src-container">
<pre class="src src-python">def subtract(a: int, b: int) -> int:
return a - b
</pre>
</div>
<p>
mypyのようなツールで実行前の静的解析が可能です。
</p>
<div class="org-src-container">
<pre class="src src-python">python -m mypy --strict t.py
</pre>
</div>
<p>
type annotationsには性能的な副作用もあるので、全てに付ける必要はありません。公開しているAPIや最も重要な部分だけに絞った方が良さそうです。
</p>
</div>
</div>
</div>
<div id="outline-container-orgb13a90e" class="outline-2">
<h2 id="orgb13a90e"><span class="section-number-2">3</span> 終わりに</h2>
<div class="outline-text-2" id="text-3">
<p>
Effective Pythonはなかなか難しい本でしたが、なんとか読み終えることができました。Effective Javaで挫折した経験があるので、少しほっとしています。2冊を比べると、もしかしてEffective Javaの方が難しいのでしょうか。
</p>
</div>
<div id="outline-container-orga103549" class="outline-3">
<h3 id="orga103549"><span class="section-number-3">3.1</span> 感想</h3>
<div class="outline-text-3" id="text-3-1">
</div>
<div id="outline-container-orgf279d18" class="outline-4">
<h4 id="orgf279d18"><span class="section-number-4">3.1.1</span> 内容全般</h4>
<div class="outline-text-4" id="text-3-1-1">
<p>
評判に違わず良書でした。位置づけとしては初中級くらいの人をターゲットにしていると思われますが、それにしては要求される前提知識のレベルが高めだと感じました。本書は、これをしろ、これをするな、という書き方が多いのですが、その理由を実際のコード例で示してくれるため、納得のいく内容になっています。
</p>
</div>
</div>
<div id="outline-container-orgb6e6bc8" class="outline-4">
<h4 id="orgb6e6bc8"><span class="section-number-4">3.1.2</span> この本の読み方</h4>
<div class="outline-text-4" id="text-3-1-2">
<p>
この本はわからないところが出てきたときに、自分でどれらけ調べられるかで、読み進められるかどうかが決まってくると思います。その際に<a href="https://realpython.com/">Real Pythonのサイト</a>にはとてもお世話になりました。フレンドリーな見かけによらず意外と中上級向けの解説記事があって助かりました。
</p>
<p>
この本のコードは半分くらい写経して、実際に動かしてみました。実際に動かしてみると(主にTYPOですが)エラーがたくさん出ます。これらのエラーを直すのに改めてコードを読み直したりして、結構勉強になりました。
</p>
</div>
</div>
<div id="outline-container-orgb982974" class="outline-4">
<h4 id="orgb982974"><span class="section-number-4">3.1.3</span> 第2版について</h4>
<div class="outline-text-4" id="text-3-1-3">
<p>
第2版を読んだのは正解でした。この版ではPython 3.8までの機能を普通に使っています。asyncio周りは動きが速く、最新の情報を元にしないとすぐに陳腐化してしまいますし、特にWalrus operator(<code>:=</code>)はエレガントなコードを書くために必須と思いました。
</p>
</div>
</div>
<div id="outline-container-orgb04b71d" class="outline-4">
<h4 id="orgb04b71d"><span class="section-number-4">3.1.4</span> 前後参照の多さ</h4>
<div class="outline-text-4" id="text-3-1-4">
<p>
この本は前後の項目への参照が非常に多く、最初は読みづらかったのですが、後半になってくると以前に読んだ内容が多くなり、逆に読みやすくなりました。ただ、後で説明する内容を前の項目で使うことが多く、この構成はどうにならないものかと感じます。
</p>
</div>
</div>
<div id="outline-container-org948ff95" class="outline-4">
<h4 id="org948ff95"><span class="section-number-4">3.1.5</span> Kindle版</h4>
<div class="outline-text-4" id="text-3-1-5">
<p>
何度も書きましたが、Kindle版はコードのインデントが崩れており、非常に読みづらいです。そのためにビットマップイメージへのリンクがある筈ですが、ビットマップでもインデントがずれている箇所がたくさんあり、辟易しました。Kindle版の技術書は2度と買いません。
</p>
<p>
また、ビットマップのリンクを見たり、前に出てきたコードを見返したりを多様するためか、Kindleデバイスの電池の減りがとても速かったです。
</p>
<p>
繰り返しますが、Kindle版は勧めません。紙かPDF版にしておけばよかったです。
</p>
</div>
</div>
</div>
<div id="outline-container-org87eebb3" class="outline-3">
<h3 id="org87eebb3"><span class="section-number-3">3.2</span> その次</h3>
<div class="outline-text-3" id="text-3-2">
<p>
fluent pythonに行くか、python cookbookに行くかでまだ悩んでいます。。。
</p>
</div>
</div>
</div>
</div>
<footer>
<p class="meta">
<span class="byline author vcard">
Posted by <span class="fn">
きょうす
</span>
</span>
<time datetime="2020-08-31T00:00:00-04:00" pubdate>Mon 31 August 2020</time> <span class="categories">
<a class='category' href='/category/python.html'>Python</a>
</span>
<span class="categories">
<a class="category" href="/tag/python.html">Python</a> </span>
</p><div class="sharing">
</div> </footer>
</article>
</div>
<aside class="sidebar">
<section>
<h1>Recent Posts</h1>
<ul id="recent_posts">
<li class="post">
<a href="/kakutei24.html">アメリカから日本の確定申告を準備する(令和6年分)</a>
</li>
<li class="post">
<a href="/utm_ub.html">M1 MacBook上にUbuntu+RetroArchを入れる</a>
</li>
<li class="post">
<a href="/tello.html">アメリカ格安SIMをSpeedtalkからTelloに変えました</a>
</li>
<li class="post">
<a href="/improve_eng2.html">上級者向け英語学習法(実践編)</a>
</li>
<li class="post">
<a href="/improve_eng1.html">上級者向け英語学習法(考察編)</a>
</li>
</ul>
</section>
<section>
<h1>Categories</h1>
<ul id="recent_posts">
<li><a href="/category/blog.html">Blog</a></li>
<li><a href="/category/english.html">English</a></li>
<li><a href="/category/linux.html">Linux</a></li>
<li><a href="/category/python.html">Python</a></li>
<li><a href="/category/tech.html">Tech</a></li>
</ul>
</section>
<section>
<h1>Tags</h1>
<a href="/tag/blog.html">Blog</a>, <a href="/tag/amerikasheng-huo.html">アメリカ生活</a>, <a href="/tag/linux.html">Linux</a>, <a href="/tag/tech.html">Tech</a>, <a href="/tag/ying-yu.html">英語</a>, <a href="/tag/emacs.html">emacs</a>, <a href="/tag/sekiyuritei.html">セキュリティ</a>, <a href="/tag/investment.html">Investment</a>, <a href="/tag/python.html">Python</a>, <a href="/tag/english.html">English</a>, <a href="/tag/mac.html">Mac</a>, <a href="/tag/toraburu.html">トラブル</a>, <a href="/tag/game.html">game</a>, <a href="/tag/vacation.html">Vacation</a>, <a href="/tag/ying-yu-jiao-yu.html">英語教育</a>, <a href="/tag/ying-jian.html">英検</a> </section>
<section>
<h1>Social</h1>
<ul>
<li><a href="#" target="_blank">You can add links in your config file</a></li>
</ul>
</section>
<section>
<h1>Blogroll</h1>
<ul>
<li><a href="https://getpelican.com/" target="_blank">Pelican</a></li>
</ul>
</section>
</aside> </div>
</div>
<footer role="contentinfo"><p>
Copyright © 2020–2025 Kyos —
<span class="credit">Powered by <a href="http://getpelican.com">Pelican</a></span>
</p></footer>
<script src="/theme/js/modernizr-2.0.js"></script>
<script src="/theme/js/ender.js"></script>
<script src="/theme/js/octopress.js" type="text/javascript"></script>
</body>
</html>