リファクタリングをPythonで実践!基本手法とコード例・注意点まで
スクレイピングにデータ分析、画像解析、AI処理などPythonはプログラム開始から終了まで時間がかかることがあります。
趣味のプログラムであれば「早く終わらないかな」程度で済みますが、実務の場合はクライアントの要件をクリアするために実行時間を気にしないといけないケースもあります。
プログラムの処理時間を計測する際に便利な「timeモジュール」をご紹介しますね。
1.Pythonのtimeモジュールとは?
Pythonの標準モジュールとして用意されている「timeモジュール」の概要をご紹介します。
①timeモジュールの概要
timeモジュールは、プログラム内で現在時刻を確認したり、処理を一時停止できるポピュラーなモジュールです。
データ分析、AI開発、Web開発などどのジャンルのPythonでもよく使用され、他言語でも時間に関する制御はよく使われるので基礎を押さえておきましょう。
②datetimeモジュールとの違い
Pythonには時間を扱うモジュールとして、「time」以外にも「datetime」というモジュールが標準で用意されています。
時刻の確認や実行時間の確認など、機能としては似ていますが、一般的には以下のように使い分けられます。
・カレンダーのように時刻以外の日付や曜日なども扱う場合は「datetime」
・プログラムの実行時間を計測する場合などは「time」
またtimeモジュールの場合は、ナノ秒まで時間を確認できます。
細かい時間の間隔を知りたい場合は、timeモジュールの利用が必要になるでしょう。
2.timeモジュールの基本的な使い方
実際にPythonでtimeモジュールを使う方法をご紹介します。
①モジュールのインポート
ここからtimeモジュールを使ったPythonプログラムをご紹介していきます。
Pythonプログラムを書いて実行する環境は、OSに依存しないGoogle Colaboratory(Google Colab)というWebサービスを使ってみます。
timeモジュールが記述されたGoogle Colab: https://colab.research.google.com/drive/1mNzPDXv-VSW2XjruTA-IpeqtzcYNBaDn#scrollTo=Fg5myX5MXErA
※ご利用にはGoogleアカウントが必要です。
Google Colabにアクセスした後は、画面右上の「接続」もしくは「再接続」をクリック。
そして一番上のセルの再生ボタンを左クリック。
これでtimeモジュールを使う準備ができました。
②現在時刻を取得する
timeモジュールで現在時刻を取得する方法はいくつかありますが、基本となるのが以下の書き方でしょう。
print(time.time())
上記コードを実行すると、意味のわからない数字が表示されます(下図左半分)。
これはタイムスタンプという時刻の表示形式で、 1970年1月1日0時0分0秒から何秒経っているかを教えてくれます。
タイムスタンプを年月日に変換してくれるWebサービス(https://www.epochconverter.com/)に、print(time.time()) の結果を入れると、現在時刻と一致していることが確認できます。(上図右半分)
アプリケーションのログや時間管理などでは便利なタイムスタンプですが、人間としてはもう少しわかりやすい方がいいですよね。
③見やすい形式で取得する
timeモジュールのstrftime関数やstrptime関数を使うと、時間をわかりやすく表示できます。
strftime関数
timeモジュールのstrftime関数を使うと、タイムスタンプを年月日等お好みの形式で表示できます。
ただ、今回はブラウザ上で実行していますので、サーバーにセットされている時間を基準としていますね。現在日本時間は、2/5 00:47です。
strptime関数
先ほどの「strftime」と似ていますが、こちらは日時などの文字列値を時間型に変換する関数です。
時間を時間型で扱うことで、翌日や翌月など日付の計算をする際に便利になります。
strptime関数は、 strptime(第一引数、第二引数)とふたつの引数を使用します。第一引数に文字列の日付、第二引数に時間型を記述しましょう。
%dは日、%bは月の略式名、%Yは4桁の西暦を意味します。
datetimeモジュールを使う方法もある
日時を見やすい形式で表示しようと思うと「datetimeモジュール」の方が便利かもしれません。
datetimeモジュールには時間や日付、曜日に関する表示や制御の機能が多数備わっています。たとえば、timeモジュールではズレていた時間も、datetimeモジュールなら日本の標準時間を簡単に採用できます。
この他にも曜日の特定や日付計算等も簡単に制御できる機能が用意されているので、必要に応じて使い分けましょう。
3.処理時間を計測する方法
Pythonプログラムの処理時間(実行時間)を計測する方法を、3つご紹介します。
①time関数を使う
単純なループ処理を1,000万回行う処理時間を上図のようにプログラムして、測ってみました。
プログラムスタート時の時間をtime.time()で取得し変数startに代入。プログラム終了時の時間を同じくtime.time()で取得し、変数endに代入。そして「終了時間(end) – 開始時間(start) = 処理にかかった時間」として算出しています。
time.time()で現在のタイムスタンプを取得できるので、時間差を簡単に求められますね。
②perf_counter関数を使う
perf_counter関数は、timeモジュールに備わっている関数で、パフォーマンスカウンタの値を取得します。
上図のように特定の処理にかかる時間を計測する際に役立ちます。time.time()より高精度で時間を計測できる特徴がありますね。
③process_time関数を使う
timeモジュールに備わっているprocess_time関数は、現在のプロセスのシステムおよびユーザーCPU時間の合計値を表示します。
time.time()やtime.pref_counter()と同じように、計測開始と計測終了を定めることで、その間の処理時間を計測できます。
pref_counter関数とprocess_time関数の違いは、time.sleep()の時間を取得するか、しないかという点です。前者はsleep間も処理時間をカウントするのに対し、後者はsleep間をカウントしません。
4.処理を一時停止する方法
プログラムを書いていると、試験的に途中で停止させたい時もありますよね。そのような場合もtimeモジュールが活用できます。
timeモジュールのsleep関数を使用することでプログラムの途中で”間”を設けられます。
sleep関数の第一引数に数値を入れると、その数値の間プログラムが停止します。数値に対する単位は「秒」で、上図の場合は1秒間停止する内容になりますね。小数点以下の値も待機処理してくれます。
大きいデータを読み込んだ後や、スクレイピングで画面が切り替わるまでの待機として使用されることが多いです。
5.timeモジュールを使う際の注意点
一昔前は、Windowsでtime.time()を使用すると+- 16ミリ秒誤差がある、といわれていました。
①time関数の時刻の取得精度はシステムに依存する
同じPythonでも実行する環境によって、time.time()の精度は異なっていました。LinuxやMacなどのUnix系は+-1ミリ秒程度の誤差が、Windowsの場合は+-16ミリ秒程度の誤差があったのです。
現在はtimeモジュールのpref_counter関数やprocess_time関数を使うことで、システム依存による誤差を小さくしています。
またtime.time()よりtime.clock()の方が高精度など、知っておくべきポイントがいくつかあります。
参考文献:https://stackoverflow.com/questions/1938048/high-precision-clock-in-python