ある程度Pythonについて覚えてきたら、なにか実用的なものを作りたくなりますよね。
私はいろいろ考えてなかなか思いつかなかったのですが、ようやく自分が使いたいものが見つかりました。
このページでは、CUI(CLI)で動作する、簡単なタイマーを作ります。
カウントダウンを表示したり、スタート、ストップの機能はありません。
ターミナルから実行し、時間が来たら音を鳴らすだけのものです。
さくっと作れるので、とりあえず何か作ってみたい人の参考になればと思います。
使用した環境
Windows10
Git Bash
Python 3.10.0
playsound 1.3.0
時間を計測する
時間の計測、入力の受け取り、音を鳴らす、の順で実装していきます。
時間の計測には、標準ライブラリのtimeをインポートします。使うのはsleepメソッドです。
import time
time.sleep(secs)
引数には秒数を渡し、与えられた秒数ぶん待機するというメソッドです。
これだけで時間の計測を実現できます。
Python 3.10.0 (tags/v3.10.0:b494f59, Oct 4 2021, 19:00:18) [MSC v.1929 64 bit (AMD64)] on win32 Type "help", "copyright", "credits" or "license" for more information. >>> import time >>> time.sleep(5) >>>
上記は5秒待機してから入力を受け付けています。
もし30秒のタイマーにしたいなら、30を渡します。
つぎは別の例としてカウントダウン。
>>> for i in range(5, -1, -1): ... print(i) ... time.sleep(1) ... 5 4 3 2 1 0 >>>
sleepに1を渡すことで、一秒間隔でのカウントダウンを実現しています。
for文のなかでprintも合わせてしているので、タイマーとしての精度が落ちる可能性はありますが、今回はカウントダウンは実装しないので構いません。
次の項でユーザーから時間を受け取ります。
カップラーメンやルーティンワークなど、決まった時間があって、秒数をもらう必要がないのであれば、もうタイマーの部分は完成と言えるかもしれません。
cupnoodle_timer.py
import time time.sleep(180) print('カップラーメンできたよ!')
入力を受け取る
ユーザーから時間を指定してもらうようにしましょう。
user = int(input('何秒のタイマーを設定しますか\n?'))
しかしこれだけでは数値に変換できない場合に対応できないので、try文で例外を捕捉したいと思います。
timer.py
import time while True: try: user = int(input('何秒のタイマーを設定しますか?\n')) except ValueError: print('入力が正しくありません。数値で指定してください。') else: break time.sleep(user)
ターミナルからモジュールを実行します。
モジュール(ファイル)を渡してPythonの起動↓
$ python timer.py 何秒のタイマーを設定しますか? u 入力が正しくありません。数値で指定してください。 何秒のタイマーを設定しますか? 入力が正しくありません。数値で指定してください。 何秒のタイマーを設定しますか? 40
最初はアルファベット、次は空文字、最後は40を入力しました。
問題ないですね。もし少数だとしても切り捨てられてintになります。
仮に数値がマイナスの場合も想定したのですが、そこまで対応しなくてもいいかと思いスルーしました。
これだけのプログラムですが他に気になることが二つあります。
- 使うのは決まった時間が多いのでいちいち入力するのは面倒くさそう。
- 秒で指定するよりは分の方が使いやすい。
最初の問題については、モジュール実行時に引数がなかったらデフォルト値で実行させるようにします。
あった場合や数値に変換できなかったら、入力を受け付けるようにします。
モジュール実行時に渡された引数というのは、sys.argvにリストとして保存されます。
sysをインポートしてちょっと確認してみましょう。
test.py
import sys print(sys.argv)
$ python test.py これも引数 ['test.py', 'これも引数']
testモジュールを実行しました。
出力されたsys.argvを見てみると、['test.py', 'これも引数']が入っていますね。
リストの最初はモジュール名が入るので、もし他に引数がなければ['test.py']だけになるはずです。
他に引数があったら、sys.argv[1]以降で使うことができます。
コードにまとめました。
timer.py
import sys import time default_time = 5 if len(sys.argv) == 1: user = default_time user_input = False else: try: user = int(sys.argv[1]) except ValueError: user_input = True else: user_input = False while user_input: try: user = int(input('何秒のタイマーを設定しますか?\n')) except ValueError: print('入力が正しくありません。数値で指定してください。') else: break print(f'{user}秒のタイマーを実行中...') time.sleep(user) print('タイマーが終了しました。')
user_inputをスイッチとして使います。
sys.argvの長さが1だった場合、default_timeをタイマーの時間に設定し、スイッチをオフにします。
引数があった場合、数値に変換を試みます。成功すればスイッチオフ、失敗したらスイッチをオンにして改めてユーザーから入力を受け付けるようにします。
実行例
$ python timer.py 5秒のタイマーを実行中... タイマーが終了しました。 $ python timer.py 30 30秒のタイマーを実行中... タイマーが終了しました。 $ python timer.py t 何秒のタイマーを設定しますか? g 入力が正しくありません。数値で指定してください。 何秒のタイマーを設定しますか? 5 5秒のタイマーを実行中... タイマーが終了しました。
あとは、秒ではなく、分で受け取るようにしたいのですが、60をかけるだけですし、最後に修正したいと思います。
音を鳴らす
タイマーが終わるまでずっとコンソールを見ているわけにはいかないので、終わったら音を鳴らすようにします。
ビープ音を鳴らす(Windows)
標準ライブラリのwinsoudをインポートします。Beepメソッドを使います。
import winsound
winsound.Beep(frequency, duration)
frequencyは周波数、durationで鳴らす音の長さ(ms)を指定します。
Python 3.10.0 (tags/v3.10.0:b494f59, Oct 4 2021, 19:00:18) [MSC v.1929 64 bit (AMD64)] on win32 Type "help", "copyright", "credits" or "license" for more information. >>> import winsound >>> for _ in range(3): ... winsound.Beep(494, 150) ... >>>
上記では、494hz(ドレミでいうと、シの音)を0.15秒間×3回鳴らします。
私はWindows使用のため、Macユーザーには次のページが参考になるかもしれません。
ビープ音を鳴らす(Windows/Mac対応)YoheiM .NET
音を再生する
Windows以外のOSを考えたり、ビープ音じゃない方がいいのかも、と思ったので、別の方法もやってみます。
手持ちの音を再生できるように、外部パッケージのplaysoundをインストールします。
ターミナルから行います。
pip install playsound
playsoundパッケージには同名の関数がひとつだけ定義されていて、引数にはファイルのパスを指定します。
ファイルはmp3かwav形式なら再生できます。
from playsound imort playsound
playsound(file-path)
>>> from playsound import playsound >>> playsound('effect01.mp3')
効果音以外に、お気に入りの音楽、またセリフとかを再生するようにしたら、タイマー終わりにちょっとテンションが上がるかもしれませんね。
まとめ
これまでのコードをひとつにまとめます。
秒設定を分に見直し、printの文言などを修正しました。
import sys
import time
from playsound import playsound
default_time = 3
if len(sys.argv) == 1:
user = default_time
user_input = False
else:
try:
user = int(sys.argv[1])
except ValueError:
user_input = True
else:
user_input = False
while user_input:
try:
user = int(input('何分のタイマーを設定しますか?\n'))
except ValueError:
print('入力が正しくありません。数値で指定してください。')
else:
break
print(f'{user}分のタイマーを実行中...\nCtrl + Cで中止します。')
time.sleep(user * 60)
playsound('effect01.mp3')
print('タイマーが終了しました。')
$ python timer.py 1 1分のタイマーを実行中... Ctrl + Cで中止します。 タイマーが終了しました。
デフォルト値(default_time)はとりあえず3にしています。
もし試してもらえるなら自由に変えてください。
各部分ごとに関数にまとめた方がいいのか迷いましたが、30行ほどのコードですし、他で使い回すつもりもなかったのでこのままにしておきました。
手慣れた人ならもっとスマートな実装方法があるのだと思います。
実際使ってみると、残り時間を表示させた方がいいな、とか、コンソールアプリよりやっぱりGUIの方が使いやすいかな、とも思いますが、ひとまずこれで完成です。
いずれはGUIやWebアプリに手を付けていきたいですね。
GUIで作成してみました↓
このページが少しでもお役に立てたのなら幸いです。