HOWTO · Python

Pythonで5秒待つ方法

Pythonで5秒待つ方法を、同期処理・スレッド・非同期処理の違いとあわせて解説します。

このページの内容

通常の同期処理で約5秒待つには、time.sleep(5) を呼び出して現在のスレッドを一時停止します。別のスレッドから早く起こされる可能性がある場合は threading.Event、遅延後にコールバックを実行する場合は threading.Timer、コルーチン内では asyncio.sleep()、複数のイベントを時刻指定で管理する場合は sched を使います。

Python で time.sleep() 関数を使用して 5 秒間待機する

time.sleep() は秒単位の時間を受け取り、呼び出したスレッドを停止します。0.5 のような小数も指定できます。ただし、5秒は正確な時刻に再開する保証ではなく、指定した時間以上の待機を求めるものです。実際の再開はオペレーティングシステムのスケジューリングによって遅れることがあります。

次の単体スクリプトは、待機の前後にメッセージを表示します。

import time

print("Waiting")
time.sleep(5)
print("Finished")
Waiting
Finished

この方法は、単純な同期スクリプトで使えます。スレッドがスリープしている間、そのスレッドは別の処理を行えません。通常のキーボード割り込み(Ctrl+C)で待機を中断できますが、この用途で独自のシグナル処理を用意する必要はほとんどありません。

Python で threading.Event を使用して 5 秒間待機する

threading.Event はスレッド間の連携に使う仕組みです。wait(5) を呼ぶと、呼び出したスレッドは最大5秒間待機し、先に別のスレッドがイベントをセットするとその時点で戻ります。シグナルを受け取るか、タイムアウトするまでワーカーを待たせたい場合に便利です。

import threading

ready = threading.Event()
print("Waiting")
ready.wait(5)
print("Finished")
Waiting
Finished

この例では別のスレッドが ready をセットしないため、タイムアウトまで待ちます。連携するプログラムでは、別のスレッドから ready.set() を呼び出して待機を終わらせられます。イベントがタイムアウト前にセットされたかどうかで後続処理を変える場合は、wait() の戻り値を確認してください。

Python で threading.Timer を使用して 5 秒後に処理を実行する

threading.Timer は、別のスレッドを開始して、指定した遅延の後にコールバックを呼び出すクラスです。タイマーを開始したスレッド自体を一時停止するものではありません。短いスクリプトでコールバックの完了を待つには join() を使います。コールバックの開始前に不要になったタイマーは cancel() で取り消せます。

from threading import Timer


def report():
    print("Callback ran")


print("Timer started")
timer = Timer(5, report)
timer.start()
timer.join()
print("Main thread finished")
Timer started
Callback ran
Main thread finished

コールバックはタイマーのスレッドで実行され、join() によってメインスレッドはそのスレッドの終了を待ちます。タイマーが予約するのは1回のコールバックです。繰り返し実行する場合や複数のイベントを扱う場合は、ループまたはスケジューラーを使います。

Python の非同期コードで asyncio.sleep() を使用して 5 秒間待機する

非同期コード内で await asyncio.sleep(5) を実行すると、現在のコルーチンを中断している間にイベントループがほかのタスクを実行できます。time.sleep(5) のようにイベントループのスレッドをブロックすることはありません。

import asyncio


async def main():
    print("Waiting")
    await asyncio.sleep(5)
    print("Finished")


asyncio.run(main())
Waiting
Finished

単体スクリプトでは asyncio.run(main()) を使って実行します。すでにイベントループが動いているアプリケーションでは、asyncio.run() で別のループを起動せず、そのループ内でコルーチンを呼び出すか、タスクとして登録してください。

Python で sched モジュールを使用して 5 秒後のイベントを実行する

sched モジュールは汎用のイベントスケジューラーを提供します。遅延時間、優先度、コールバック、必要に応じて引数を指定してイベントを登録し、run() を呼び出すとキューを処理します。次のイベントが未来に予定されている場合、run() は実行時刻まで待ちます。予定イベントの管理には便利ですが、一度だけ待つ用途には少し大がかりです。

import sched
import time


def report():
    print("Scheduled event ran")


scheduler = sched.scheduler(time.monotonic, time.sleep)
print("Scheduler started")
scheduler.enter(5, 1, report)
scheduler.run()
print("Scheduler finished")
Scheduler started
Scheduled event ran
Scheduler finished

このスケジューラーは単調増加時計を使うため、経過時間による予定が壁時計の調整に左右されません。遅延関数には time.sleep を指定しており、run() はキューにあるイベントが実行されるまで戻りません。

まとめ

単純な同期処理を一時停止するなら time.sleep(5) を使います。別スレッドから待機中のスレッドに合図を送る場合は threading.Event.wait(5)、遅れて1回だけコールバックを実行する場合は threading.Timer、ほかのタスクも進めながらコルーチンを待機させる場合は asyncio.sleep(5) が適しています。時刻指定のイベントを1つまたは複数管理するなら sched を選びます。どの方法でも、待機中のコードが再開する時刻はオペレーティングシステムやイベントループに左右されるため、指定時間は概算です。