Pythonでプログラムを書いていると、処理と処理の間に一定時間待機させたい場面が出てきます。APIへのリクエスト間隔の調整、アニメーション的な表示演出、定期実行処理のインターバル設定など、待機処理はPythonプログラミングの実務でよく使われる操作のひとつです。
Pythonではtimeモジュールのtime.sleep()を使うことで、指定した秒数だけプログラムの実行を一時停止できます。整数だけでなく小数点での秒数指定も可能で、ミリ秒単位の細かい待機にも対応しています。
この記事では、Pythonで1秒待つ基本的な書き方から、time.sleep()の応用・非同期処理でのawait asyncio.sleep()との使い分け・実践的なパターンまで、サンプルコードとともにわかりやすく解説していきます。
Pythonで1秒待つにはtime.sleep(1)を使うのが基本
それではまず、Pythonで指定時間だけ待機するtime.sleep()の基本的な使い方について解説していきます。
Pythonで待機処理を実装するには、標準ライブラリのtimeモジュールをインポートしてtime.sleep()に秒数を渡すだけです。引数に渡した秒数だけプログラムの実行が一時停止します。
import time
print("処理開始")
# 1秒待機
time.sleep(1)
print("1秒後に実行されました")
# 実行時間を計測して確認
start = time.time()
time.sleep(1)
elapsed = time.time() - start
print(f"実際の待機時間:{elapsed:.3f}秒")
# 出力結果:処理開始
# 出力結果:1秒後に実行されました
# 出力結果:実際の待機時間:1.001秒(環境により多少変動)
time.sleep(1)と書くだけで1秒間の待機が実現できます。非常にシンプルな構文で、引数には整数だけでなく小数点の値も指定できます。
様々な秒数指定の方法
import time
# 整数で秒数を指定
time.sleep(1) # 1秒
time.sleep(5) # 5秒
time.sleep(60) # 1分
# 小数点で秒数を指定(ミリ秒単位)
time.sleep(0.1) # 100ミリ秒
time.sleep(0.5) # 500ミリ秒
time.sleep(0.01) # 10ミリ秒
# 変数で秒数を指定
wait_seconds = 2
time.sleep(wait_seconds)
print(f"{wait_seconds}秒待機しました。")
# 出力結果:2秒待機しました。
小数点を使うと100ミリ秒・500ミリ秒など細かい単位での待機が実現できます。APIのレート制限対策や画面表示のタイミング調整など、用途に応じて秒数を使い分けましょう。
秒・分・時間を変換して待機する
import time
# 単位を変換してsleepに渡す
def sleep_minutes(minutes):
time.sleep(minutes * 60)
def sleep_hours(hours):
time.sleep(hours * 3600)
# 実際に待機する場合
# sleep_minutes(5) # 5分待機
# sleep_hours(1) # 1時間待機
# 秒数の計算例
print(f"5分 = {5 * 60}秒")
print(f"1時間 = {1 * 3600}秒")
print(f"1.5時間 = {1.5 * 3600}秒")
# 出力結果:5分 = 300秒
# 出力結果:1時間 = 3600秒
# 出力結果:1.5時間 = 5400.0秒
分や時間を秒に変換してsleep()に渡す関数を用意しておくと、長時間の待機処理を書くときにコードが読みやすくなります。
time.sleep()の秒数を動的に変化させる
import time
# 待機時間を徐々に増やすエクスポネンシャルバックオフ
def exponential_backoff(max_retries=4):
for attempt in range(max_retries):
wait_time = 2 ** attempt # 1, 2, 4, 8秒と増加
print(f"試行{attempt + 1}回目:{wait_time}秒待機します...")
time.sleep(0.1) # デモ用に短縮(実際はwait_timeを指定)
print(f"再試行します。")
print("最大試行回数に達しました。")
exponential_backoff()
# 出力結果:試行1回目:1秒待機します...
# 出力結果:再試行します。
# 出力結果:試行2回目:2秒待機します...
# 出力結果:再試行します。
# 出力結果:試行3回目:4秒待機します...
# 出力結果:再試行します。
# 出力結果:試行4回目:8秒待機します...
# 出力結果:再試行します。
# 出力結果:最大試行回数に達しました。
エクスポネンシャルバックオフはAPIのリトライ処理でよく使われるパターンです。試行ごとに待機時間を倍増させることで、サーバーへの負荷を分散しながらリトライできます。
time.sleep()を使った実践的なパターン
続いては、time.sleep()を活用した実践的なプログラムのパターンを確認していきます。
待機処理は単独で使うだけでなく、ループ処理・カウントダウン・プログレス表示・API呼び出しなど様々な処理と組み合わせて活用できます。
カウントダウンタイマーを実装する
import time
def countdown(seconds):
print(f"{seconds}秒のカウントダウンを開始します。")
for i in range(seconds, 0, -1):
print(f"{i}秒...")
time.sleep(0.1) # デモ用に短縮(実際はtime.sleep(1))
print("終了!")
countdown(5)
# 出力結果:5秒のカウントダウンを開始します。
# 出力結果:5秒...
# 出力結果:4秒...
# 出力結果:3秒...
# 出力結果:2秒...
# 出力結果:1秒...
# 出力結果:終了!
range()のstepを-1にすることで逆順にカウントしながらsleep()で1秒ずつ待機するカウントダウンが実現できます。
プログレス表示と組み合わせる
import time
import sys
def show_progress(total_steps):
print("処理中...")
for step in range(1, total_steps + 1):
progress = int((step / total_steps) * 20)
bar = "█" * progress + "░" * (20 - progress)
percent = (step / total_steps) * 100
print(f"\r[{bar}] {percent:.0f}%", end="", flush=True)
time.sleep(0.1)
print("\n完了しました!")
show_progress(10)
# 出力結果:処理中...
# 出力結果:[████████████████████] 100%
# 出力結果:完了しました!
\rで行頭に戻りながらプログレスバーを更新することで、CLIアプリケーションで動きのある進捗表示が実現できます。flush=Trueで即座に出力を反映させる点がポイントです。
APIのレート制限に対応する
import time
# APIのレート制限に対応したリクエスト処理
def simulate_api_request(endpoint):
print(f"APIリクエスト送信:{endpoint}")
time.sleep(0.1) # API処理時間をシミュレート
return {"status": "success", "endpoint": endpoint}
endpoints = [
"/api/avocado",
"/api/salmon",
"/api/dragon_fruit",
"/api/gorilla_tea",
"/api/robacoffee"
]
# 1秒間に2リクエストまでの制限に対応
request_interval = 0.5 # 0.5秒間隔 = 1秒に2回
for i, endpoint in enumerate(endpoints):
result = simulate_api_request(endpoint)
print(f"レスポンス:{result['status']}")
# 最後のリクエスト以外は待機
if i < len(endpoints) - 1:
time.sleep(request_interval)
print(f"{request_interval}秒待機しました。")
# 出力結果:APIリクエスト送信:/api/avocado
# 出力結果:レスポンス:success
# 出力結果:0.5秒待機しました。
# 出力結果:APIリクエスト送信:/api/salmon
# 出力結果:レスポンス:success
# 出力結果:0.5秒待機しました。
# 出力結果:(以下繰り返し)
APIのレート制限に対してsleep()で間隔を開けるパターンはWebスクレイピングや外部API連携で非常によく使われます。
非同期処理でのasyncio.sleep()の使い方
続いては、非同期処理環境でtime.sleep()の代わりに使うasyncio.sleep()の使い方を確認していきます。
time.sleep()はスレッド全体をブロックしてしまうため、async/await構文を使う非同期処理ではasyncio.sleep()を使う必要があります。asyncio.sleep()は待機中に他のタスクを実行できるため、効率的な非同期プログラムが書けます。
asyncio.sleep()の基本的な使い方
import asyncio
async def task(name, wait_time):
print(f"{name}:処理開始")
await asyncio.sleep(wait_time)
print(f"{name}:{wait_time}秒後に完了")
async def main():
# 複数タスクを並行実行
await asyncio.gather(
task("アボカド処理", 1),
task("サーモン処理", 0.5),
task("ドラゴンフルーツ処理", 0.8),
)
asyncio.run(main())
# 出力結果:アボカド処理:処理開始
# 出力結果:サーモン処理:処理開始
# 出力結果:ドラゴンフルーツ処理:処理開始
# 出力結果:サーモン処理:0.5秒後に完了
# 出力結果:ドラゴンフルーツ処理:0.8秒後に完了
# 出力結果:アボカド処理:1秒後に完了
asyncio.sleep()を使うと、待機中に他のタスクが並行して実行されます。time.sleep()で順番に待機した場合は合計2.3秒かかりますが、asyncio.gatherで並行実行すると最大の待機時間(1秒)で完了します。
time.sleepとasyncio.sleepの使い分け
| 関数 | 処理方式 | 待機中の動作 | 使う場面 |
|---|---|---|---|
| time.sleep() | 同期処理 | スレッド全体がブロック | 通常のスクリプト |
| asyncio.sleep() | 非同期処理 | 他タスクが実行可能 | async/await環境 |
非同期処理でのリトライをasyncio.sleepで実装する
import asyncio
import random
async def fetch_with_retry(name, max_retries=3):
for attempt in range(1, max_retries + 1):
# 50%の確率で成功するリクエストをシミュレート
success = random.random() > 0.5
if success:
print(f"{name}:{attempt}回目で成功")
return f"{name}のデータ"
print(f"{name}:{attempt}回目失敗、リトライします...")
await asyncio.sleep(0.1) # リトライ間隔
print(f"{name}:最大リトライ数に達しました。")
return None
async def main():
results = await asyncio.gather(
fetch_with_retry("アボカド"),
fetch_with_retry("サーモン"),
)
print(f"結果:{results}")
asyncio.run(main())
# 出力結果:アボカド:1回目で成功(毎回変わります)
# 出力結果:サーモン:1回目失敗、リトライします...
# 出力結果:サーモン:2回目で成功
# 出力結果:結果:['アボカドのデータ', 'サーモンのデータ']
非同期のリトライ処理でasyncio.sleep()を使うことで、複数のリクエストを並行してリトライできます。同期のtime.sleep()より効率的な処理が実現できます。
time.sleep()に関するよくある疑問と注意点
続いては、time.sleep()を使う際のよくある疑問と注意すべきポイントを確認していきます。
time.sleep()はシンプルな関数ですが、精度・割り込み・マルチスレッドでの動作について理解しておくとより安全に使えます。
sleep()の精度と実際の待機時間
import time
# sleep()の精度を確認する
wait_times = [0.1, 0.5, 1.0]
for target in wait_times:
start = time.perf_counter()
time.sleep(target)
actual = time.perf_counter() - start
diff = actual - target
print(f"目標:{target}秒 / 実際:{actual:.4f}秒 / 差分:{diff:.4f}秒")
# 出力結果:目標:0.1秒 / 実際:0.1012秒 / 差分:0.0012秒
# 出力結果:目標:0.5秒 / 実際:0.5008秒 / 差分:0.0008秒
# 出力結果:目標:1.0秒 / 実際:1.0010秒 / 差分:0.0010秒
time.sleep()はOSのスケジューラに依存するため、指定した時間よりも少し長くなる場合があります。高精度な時間制御が必要な場合はtime.perf_counter()で実際の経過時間を計測しながら処理を調整する方法を検討しましょう。
KeyboardInterruptで待機中断する
import time
# 待機中のKeyboardInterruptを適切に処理する
print("10秒待機します(Ctrl+Cで中断できます)")
try:
for i in range(3): # デモ用に3回に短縮
print(f"待機中:{i + 1}回目")
time.sleep(0.5)
print("待機完了")
except KeyboardInterrupt:
print("\nCtrl+Cで中断されました。")
finally:
print("後処理を実行しました。")
# 出力結果:10秒待機します(Ctrl+Cで中断できます)
# 出力結果:待機中:1回目
# 出力結果:待機中:2回目
# 出力結果:待機中:3回目
# 出力結果:待機完了
# 出力結果:後処理を実行しました。
time.sleep()中にCtrl+Cが押されるとKeyboardInterruptが発生します。try-exceptで捕捉してfinallyで後処理を実行する実装が安全なパターンです。
まとめ
この記事では、Pythonで1秒待つtime.sleep()の使い方について、基本的な秒数指定から応用パターン・asyncio.sleep()との使い分け・注意点まで幅広く解説しました。
Pythonで待機処理を実装するにはtime.sleep()に秒数を渡すだけです。整数・小数点どちらの秒数指定にも対応しており、ミリ秒単位の細かい待機も実現できます。APIのレート制限対応・カウントダウン・定期実行など様々な場面で活躍します。非同期処理環境ではtime.sleep()の代わりにasyncio.sleep()を使い、待機中も他のタスクを並行実行できるようにしましょう。
長時間の待機を伴うプログラムにはKeyboardInterruptの例外処理を実装して、安全に中断できる仕組みも合わせて用意しておくことが大切です。ぜひ実際のプロジェクトで活用してみてください。