今さらPython3 (80) - 第12章一気読み その2

一気読みと言いながら一回で収まらなかったので続きを。

入門 Python 3

入門 Python 3

デバッグ

デバッグというとデバッガを立ち上げてというのをイメージしがちだけど、怪しいところに何かしらのログを吐かせるというのも、もちろん有効なわけで。


$ python3 dump_test.py
Function name: double
Input arguments: 3 5
Input keyword arguments: dict_items([('next', 98.6), ('first', 100), ('last', -40)])
Output: ([6, 10], {'next': 197.2, 'first': 200, 'last': -80})

デコレータを使ってダンプを吐くみたいなのは用意しておくと汎用的に使えるかも。

南米の首都と来て、quitで終了みたいなフリされたら、簡単にオチが予想るっつーの。

$ python3 capitals.py cities1.csv
Paris,France
Caracas,Venezuela
Vilinius,Lithunia
$ python3 capitals.py cities2.csv
Buenos Aires,Argentina
La Paz,Bolivia
Brasilia,Brazil
Santiago,Chile
Bogotá,Colombia

そうじゃなくてデバッグの練習なので。

$ python3 -m pdb capitals.py cities2.csv
> /Users/ken/PycharmProjects/IntroducingPython3/capitals.py(1)<module>()
-> def process_cities(filename):
(Pdb) c
Buenos Aires,Argentina
La Paz,Bolivia
Brasilia,Brazil
Santiago,Chile
Bogotá,Colombia
The program finished and will be restarted
> /Users/ken/PycharmProjects/IntroducingPython3/capitals.py(1)<module>()
-> def process_cities(filename):
(Pdb) 
Buenos Aires,Argentina
La Paz,Bolivia
Brasilia,Brazil
Santiago,Chile
Bogotá,Colombia
The program finished and will be restarted
> /Users/ken/PycharmProjects/IntroducingPython3/capitals.py(1)<module>()
-> def process_cities(filename):
(Pdb) s
> /Users/ken/PycharmProjects/IntroducingPython3/capitals.py(12)<module>()
-> if __name__ == '__main__':
(Pdb) s
> /Users/ken/PycharmProjects/IntroducingPython3/capitals.py(13)<module>()
-> import sys
(Pdb) s
> /Users/ken/PycharmProjects/IntroducingPython3/capitals.py(14)<module>()
-> process_cities(sys.argv[1])
(Pdb) s
--Call--
> /Users/ken/PycharmProjects/IntroducingPython3/capitals.py(1)process_cities()
-> def process_cities(filename):
(Pdb) l
  1  ->	def process_cities(filename):
  2  	    with open(filename, 'rt') as file:
  3  	        for line in file:
  4  	            line = line.strip()
  5  	            if 'quit' in line.lower():
  6  	                return
  7  	            country, city = line.split(',')
  8  	            city = city.strip()
  9  	            country = country.strip()
 10  	            print(city.title(), country.title(), sep=',')
 11  	
(Pdb) 

昔、ググってこの方法を見つけて試した記憶がある。sがsingle stepで1ステップずつ、nがnextでかたまり単位で実行。lは覚えてないけど、本によるとプログラムの数行先まで見れると。cはcontinueで続行かな?

(Pdb) s
> /Users/ken/PycharmProjects/IntroducingPython3/capitals.py(2)process_cities()
-> with open(filename, 'rt') as file:
(Pdb) l
  1  	def process_cities(filename):
  2  ->	    with open(filename, 'rt') as file:
  3  	        for line in file:
  4  	            line = line.strip()
  5  	            if 'quit' in line.lower():
  6  	                return
  7  	            country, city = line.split(',')
  8  	            city = city.strip()
  9  	            country = country.strip()
 10  	            print(city.title(), country.title(), sep=',')
 11  	
(Pdb) b 6
Breakpoint 1 at /Users/ken/PycharmProjects/IntroducingPython3/capitals.py:6
(Pdb) c
Buenos Aires,Argentina
La Paz,Bolivia
Brasilia,Brazil
Santiago,Chile
Bogotá,Colombia
> /Users/ken/PycharmProjects/IntroducingPython3/capitals.py(6)process_cities()
-> return
(Pdb) p line
'ecuador,quito'

さらに1行だけ進んで(s)、もう1回リストを出して(l)、6行目のreturnのところにブレークポイント(b 6)を指定したら、今度はcで継続(ってか再実行っぽいな)すると、さっきのブレークポイントで止まる。変数lineの値を見てみる(p line)と、中身はあらあらw。

(Pdb) b
Num Type         Disp Enb   Where
1   breakpoint   keep yes   at /Users/ken/PycharmProjects/IntroducingPython3/capitals.py:6
	breakpoint already hit 1 time
(Pdb) l 1
  1  	def process_cities(filename):
  2  	    with open(filename, 'rt') as file:
  3  	        for line in file:
  4  	            line = line.strip()
  5  	            if 'quit' in line.lower():
  6 B->	                return
  7  	            country, city = line.split(',')
  8  	            city = city.strip()
  9  	            country = country.strip()
 10  	            print(city.title(), country.title(), sep=',')
 11  	
(Pdb) q

ブレークポイントの一覧を出して(b)、もう1回1行目からのリストを出す(l 1)と、ブレークポイントの行にB印が付いてる。あと、デバッガ終了の時はq。

ということでプログラムを流し、capitals2.pyで再実行をする。

$ python3 capitals2.py cities2.csv
Buenos Aires,Argentina
La Paz,Bolivia
Brasilia,Brazil
Santiago,Chile
Bogotá,Colombia
Quito,Ecuador
Stanley,Falkland Islands
Cayenne,French Guiana
Georgetown,Guyana
Asunción,Paraguay
Lima,Peru
Paramaribo,Suriname
Montevideo,Urguay
Caracas,Venezuela

だん。

ロギング

>>> import logging
>>> logging.basicConfig(level=logging.DEBUG)
>>> logging.debug("It's raining again")
>>> 

レベル変えても何も起こらないな。。。いつか使う日のためにリンクを残しておく。

16.6. logging — Python 用ロギング機能 — Python 3.4.3 ドキュメント

実行時間計測

from time import time

t1 = time()
num = 5
num *= 2
print(time()-t1)

これは古典的な手法だね。

>>> from timeit import repeat
>>> print(repeat('num =5; num *= 2', number=1, repeat=5))
[2.2899912437424064e-06, 4.429894033819437e-07, 4.4099579099565744e-07, 2.4901237338781357e-07, 2.7799978852272034e-07]

repeatを使うと複数回計測できるので便利だね。


time_lists.py
time_list_1 takes 0.13075238499732222 sec
time_list_2 takes 0.044669875991530716 sec

確かに内包リストの方が3倍近く速いね。

終わりに

という感じで、入門Python3の本文を読破しちゃいました。実際に手を動かしつつ、ログをこのブログに残していたら80回シリーズになってしまった訳だけど、これまで虫食いだったPythonの知識がもう少し網羅的に分かるようになったのが収穫かなと思います。いったん、このシリーズは終わりにしますが、100ページもある付録にも面白そうなところがあるので、また触ってみようかなと思います。

(おわり)