こんにちは!フリーランスエンジニア・ライターの平山です。
プログラミングを学習していて、次のような悩みを持ったことはありませんか?
基本的な文法はわかったけど何を作ったらいいのかわからない
テキストを一通り学習し終えたあたりで、このような悩みは誰しもが持つものです。先輩にアドバイスを求めても「作りたいものを作ればいい」なんて身もふたもない回答が返ってきたり・・・
そこで、この記事では初心者の方でも簡単に作れるタイマーを題材にして
- timeモジュールの基礎
- 仕様を考える手順
- カウントダウン、カウントアップタイマーを実装
までをステップバイステップでお伝えしていきます。また、最後に少し難易度の高いthreadingを使ったマルチスレッド処理もお伝えします。それでは早速はじめましょう!
本記事を読む前に、Pythonがどんなプログラミング言語なのかをおさらいしておきたい人は次の記事を参考にしてください。
→ Pythonとは?特徴やできること、活用例をわかりやすく簡単に解説
なお、その他のPythonの記事についてはこちらにまとめています。
timeモジュールの基礎
まずはタイマー作成のキモになるtimeモジュールを基礎から理解しましょう。timeモジュールは時刻に関する様々な関数を提供しています。今回はsleep関数を使って、タイマーの動作を制御していきましょう。
sleep関数は次のように使います。
from time import sleep print("3秒後に星が出ます。") sleep(3) print("ミ☆ミ☆ミ☆")
sleep()は与えられた秒数の間、プログラム(正確にはスレッド)の実行を停止します。今回は3秒間動作を停止させて、その後print()を実行させました。注意点として、引数には秒を取る、ということを覚えておいてください。
言語によっては似たような機能の引数にミリ秒を取ることがあります。そのため、他言語経験者ほど注意が必要ですね。ちなみに、ミリ秒単位まで細かく制御したい場合
sleep(0.001) #1ms = 0.001sec
このようにミリ秒を秒単位に変換してあげればオッケーです。続いて、sleep関数の精度をみていきましょう。
精度はどのくらい?
さっそく精度について解説していきたいところなのですが・・・sleep関数、およびtime関数の精度は環境依存のため、おおよその数値でしか表現できません。
ただ、今回は厳密に時間を測りたいわけではありません。なので、気楽にsleep関数を使いましょう。もし今後、マイクロ秒、ナノ秒オーダーで時間を測る必要が出てきたときに思い出してください。
それでは次の章から実際にタイマーを作っていきましょう!
簡単なタイマーの作り方
まずは、簡単なカウントアップタイマーの作り方からです。
仕様を整える
このタイマーの仕様を考えていきます。一番簡単な仕様策定のやり方は、とにかく必要な機能を列挙していくことです。今回、必要と思われる機能は以下の通りです。
- target_time変数に目標時間を設定
- 関数up_timer()を実行することでタイマーを動かす
- タイマーは1秒ごとにカウントアップする
- 時間の制御はsleep()を使う
- 目標時刻になったら”時間です!”と表示
ちょっとプログラミングの勉強法の話にそれます。プログラミングを勉強し始めた当初は、テキストやサンプルをひたすら写すのがメインになるでしょう。そのため、ある程度学習が進んだ人は、何も考えずにいきなり書き始めてしまうことがままあります。
規模が小さいうちはそれでもどうにかなります。ですが、いずれ限界が訪れます。
どの機能をどう実装していいのかもわからない
そもそも、この関数はなんで作ってたんだっけ?
このように最初に仕様を決めると、ゴールが明確化されるのでこんな悲劇に会わずにすみます。ぜひ、プログラムを書き始める前に、仕様を明確化させる習慣をつけてください。
タイマーの実装
さて、タイマーの実装に戻りましょう。まずはsleep()を使うためのtimeモジュールを導入し、target_time変数を定義します。
from time import sleep target_time = 10
Pythonの慣習でimportは文頭にまとめておくと、読みやすいコードになります。続いて、カウントアップする関数のup_timer()を定義しましょう。
def up_timer(secs): for i in range(0,secs): print(i) sleep(1) print("時間です!")
コードを詳しくみていきます。up_timerは2つの部分からできています。
- for文で経過時間を表示しつつ、1秒待機する部分
- 指定時間後に”時間です!”と表示する部分
1つ目で
- タイマーは1秒ごとにカウントアップする
- 時間の制御はsleep()を使う
の仕様。2つ目で目標時刻になったら「時間です!」と表示するという仕様が満たされているのがわかるかと思います。for文について不安のある方は次の記事を参考にすると良いでしょう。
これで全ての仕様を満たしたプログラムが作れました。実行部分を加えたソースの全体像は下のようになります。
from time import sleep target_time = 10 def up_timer(secs): for i in range(0,secs): print(i) sleep(1) print("時間です!") up_timer(target_time)
ちなみにこのタイマーの精度ですが、筆者の環境では± 3.97 msでした。実行環境はMacBook Pro (15インチ, 2016)。気楽に使うタイマーとしては十分な精度ではないでしょうか?
自分の組んだプログラムの実行時間を測ってみたい方には、次の記事が参考になります。
カウントダウン型に改良
今度はタイマーをカウントダウン型に改造してみましょう。カウントダウン型の場合、これまでと違う点は表示する数はtarget_timeから順に1ずつ減っていくというところです。これを実装できればカウントダウンが実現しますね。
ではどうすればいいでしょうか?これも仕様策定の練習だと思って、少し考えてみましょう。それでは、答えです。
正解はいくつもありますが、現状からの修正が最も少ないのは次の方法です。
def down_timer(secs): # for i in range(0,secs):から変更 for i in range(secs, -1, -1): # 以下同じ・・・
Pythonのfor文は、inの後ろにくるイテラブルオブジェクト(リストなどのこと)の要素を順番に変数に代入する仕様です。そのため、リストの中身を逆にしてあげれば簡単にカウントダウンを表現することができます。
リストの中身を逆順にするにはrange()の第3引数に-1を指定して、スタートに当たる第1引数をsecsにします。また、今回はタイマーの終点で0を表示させたかったので、ゴールに当たる第2引数を-1にしています。
こういったrangeの細かいテクニックは次の記事が参考になるでしょう。
それでは最後に発展的な内容にチャレンジしてみましょう。
threadを使って同時起動に挑戦!
最後に扱うのは関数の同時起動です。実行に時間がかかる関数があるとき、複数の処理を同時に走らせることでプログラム全体の速度が向上します。これをマルチスレッド処理といいます。
詳しくは、PHP向けの記事ですが、こちらが参考になるでしょう。
Pythonは簡単にマルチスレッド処理を実装できるので、ここではタイマーの同時起動に挑戦しましょう。まずはマルチスレッドに必要なthreadingモジュールについて次節で解説します。
threadingモジュールとは?
threadingモジュールは、マルチスレッド処理のための関数やオブジェクトを提供します。その中で今回使うのが、Treadオブジェクトになります。関数をThreadオブジェクトにすることで、マルチスレッド処理ができるようになります。
使い方は下の通りです。
from threading import Thread def test_function1(var): # ・・・ def test_function2(var): # ・・・ # 関数を定義します thread_1 = Thread(target=test_function1,args=(var,)) thread_2 = Thread(target=test_function2,args=(var,)) thread_1.start() thread_2.start()
- マルチスレッド化したい関数を用意する
- Threadオブジェクトに関数と引数を代入する
- target引数には関数の名前、args引数には関数の引数をそれぞれ入れる
- 関数ごとにThreadインスタンスを作る
- Threadインスタンス.start()でスレッドを実行する
注意点が2つあります。1つ目はargsの引数はタプルなので、関数の引数が1つの時は末尾にカンマ,が必要です。
2つ目はThreadオブジェクトのtarget引数はあくまでも関数の名前のみを記入することに注意してください。
うっかりカッコ()をつけたままだと、エラーが出て動きません。お気をつけください。それではthreadingモジュールを使って、タイマーを同時起動させてみましょう。
同時起動できるタイマーに改造してみよう
最後に総まとめとして、「カウントダウンとカウントアップが同時起動するタイマー」に改造しましょう。ソースは次のようになります。
from time import sleep from threading import Thread # Threadオブジェクトをインポート target_time = 10 def up_timer(secs): for i in range(0,secs): print(i) sleep(1) print("カウントアップ終了!") def down_timer(secs): # for i in range(0,secs):から変更 for i in range(secs, -1, -1): # 以下同じ・・・ print(i) sleep(1) print("カウントダウン終了!") # Threadインスタンスをタイマーごとに生成する thread_1 = Thread(target=up_timer,args=(target_time,)) thread_2 = Thread(target=down_timer,args=(target_time,)) # それぞれのスレッドを起動する thread_1.start() thread_2.start()
実行結果は次のようになります。
1 9 # 省略 8 2 91 0カウントアップ終了! カウントダウン終了!
マルチスレッドで動かせるタイマーが完成しましたね!
Pythonをもっと本格的に学びたいあなたへ
今回紹介した記事で、Pythonを使ったタイマーの作り方を理解できたかと思います。ですが、
このままでPythonエンジニアになれるのだろうか…
このような不安を持つ人もいるのではないでしょうか?もし仮に学習方法が間違っているとしたら、かなりの遠回りをするだけなく、途中で挫折してしまう可能性だってあります。
せっかく学習を進めているのに挫折してしまったら、何の意味もなくなってしまいますね。そうならないためにも、学習プランをしっかり決めて学習を進める必要があります。
弊社「侍エンジニア」で行っている無料カウンセリングでは、この学習プランを考えるお手伝いをしています。あなたがPythonを学んで今後どうなりたいのか?という目的からヒアリングして、その目的に合った学習プランを提案いたします。
プログラミングを学んだ先の理想は一人一人違います。完全個別指導で、あなたに合わせた講師とカリキュラムで学習し、オリジナルサービスを開発することによって、転職やフリーランスデビュー、社内昇進など様々な卒業生がキャリアを伸ばすことに成功しています。
- 今の学習方法に少なからず不安がある
- 自分に合った学習プランを知りたい
- 最短でPythonエンジニアを目指したい
以上のいずれかに該当する人は、ぜひ無料カウンセリングを活用してみてください。対面形式(渋谷)はもちろん、オンラインでの利用も可能です。下記のカレンダーから直接予約ができるので、まずはお気軽にご相談ください。
お急ぎの方はこちらからお問い合わせください。
読み込みに失敗しました。
大変お手数ですが、本ページを再度読み込んでください。
再度読み込んでも、読み込み失敗が起こる場合は
こちらからお問い合わせください。
カウンセリングはオンラインにて実施しております。
※予約完了後に、カウンセリングのためのURLやIDなどをメールにてご案内します
1.ご希望の日時を選択してください
2.必須事項を入力してください
ご予約ありがとうございます!
予約が完了しました。ご予約情報とご参加前の準備をご確認ください。
【ご予約情報】○月○日(△) ○○:○○〜
カウンセリング参加に向けてのご準備
※記入いただいたメールアドレスに確認用メールをお送りしておりますのでご確認ください。
※オンラインカウンセリングはGoogle Meetにて実施します。URLが発行したら別途ご案内いたします。
※メールが届かない場合は、SAMURAI ENGINEERサポート(support@sejuku.net)までご連絡ください。
まとめ
いかがでしたでしょうか?今回は以下のことをお伝えしました。
- timeモジュール、特にsleep()の基礎
- 簡単なタイマーの作成
プログラミングは学んでみたものの、何を作ったらいいのかわからない!という方の一助になれば幸いです。ぜひ、自分で悩み、考え、プログラミングを楽しんでください。もしタイマーやthreadingでわからないことがあったら、この記事を振り返ってみてくださいね!
なお、今Pythonを学習している方は以下の記事もどうぞ。
はじめてPythonを使う方でもわかりやすいように、Pythonでできることやその学習法などを中心にまとめています。
復習にも使えると思いますので、ぜひ一度ご覧になってみてくださいね。
【Python 入門完全攻略ガイド】