آموزش ماژول threading – کلاس Timer

Please login to bookmark Close

کلاس Timer

کلاس Timer یکی از زیرکلاس‌های Thread در ماژول threading است و به شما اجازه می‌دهد یک تابع را نه بلافاصله، بلکه پس از گذشت یک بازه‌ی زمانی مشخص اجرا کنید. به عبارت ساده، Timer مثل یک زنگ هشدار عمل می‌کند: زمان را تنظیم می‌کنید، برنامه به کار خود ادامه می‌دهد، و وقتی زمان تعیین‌شده فرا رسید، تابع موردنظر در یک ترد جداگانه اجرا می‌شود.

مهم‌ترین ویژگی Timer این است که چون یک ترد مستقل است، منتظر ماندنِ آن، جریان اصلی برنامه را متوقف نمی‌کند؛ برنامه‌ی شما بدون وقفه ادامه پیدا می‌کند و تابع در زمان مقرر «در پس‌زمینه» صدا زده می‌شود.

ساختار و پارامترها

امضای این کلاس به شکل Timer(interval, function, args=None, kwargs=None) است:

پارامترتوضیح
intervalمدت تأخیر برحسب ثانیه (می‌تواند اعشاری هم باشد، مثل 0.5).
functionتابعی که بعد از پایان تأخیر اجرا می‌شود.
argsآرگومان‌های موضعی (به‌صورت tuple یا list) که به تابع پاس داده می‌شوند.
kwargsآرگومان‌های کلیدواژه‌ای (به‌صورت dict) که به تابع پاس داده می‌شوند.

و مهم‌ترین متدهای آن: start() برای شروع شمارش تأخیر، و cancel() برای لغو اجرا (تا زمانی که هنوز تابع اجرا نشده باشد).

اجرای تابع با تأخیر

from threading import Timer

def say_hi(name):
    print('hi', name)

# run say_hi after 3 seconds
Timer(3, say_hi, args=('mmreza', )).start()

در تکه‌کد بالا، تابع say_hi پس از ۳ ثانیه اجرا می‌شود. توجه کنید که برنامه بلافاصله از خط Timer(...).start() عبور می‌کند و منتظر نمی‌ماند؛ صرفاً یک ترد زمان‌بندی‌شده ساخته می‌شود که سه ثانیه بعد تابع را صدا می‌زند.

لغو اجرا با cancel()

برای لغو اجرا می‌توانید قبل از فرا رسیدن زمان اجرا از متد cancel استفاده کنید. اگر تابع هنوز اجرا نشده باشد، cancel جلوی اجرای آن را می‌گیرد؛ اما اگر زمان تأخیر تمام شده و تابع شروع به اجرا کرده باشد، دیگر cancel اثری ندارد. به مثال زیر توجه کنید:

from threading import Timer

def say_hi(name):
    print('hi', name)

say_hi_after_3_seconds = Timer(3, say_hi, args=('mmreza', ))
say_hi_after_3_seconds.start()
say_hi_after_3_seconds.cancel()   # cancels before the 3s elapses, so say_hi never runs

در این مثال چون cancel بلافاصله بعد از start و خیلی زودتر از پایان سه ثانیه فراخوانی می‌شود، تابع say_hi هرگز اجرا نمی‌شود و هیچ خروجی‌ای چاپ نمی‌گردد. اگر بین start و cancel بیش از سه ثانیه فاصله می‌افتاد، تابع اجرا شده بود و cancel دیگر کاری نمی‌کرد.

اجرای دوره‌ای (تکرارشونده)

خودِ Timer ذاتاً «یک‌بارمصرف» است و تابع را فقط یک بار اجرا می‌کند. اما با ساختن یک Timer جدید در انتهای همان تابع، می‌توان یک رفتار تکرارشونده ساخت. در مثال زیر تابع tick هر یک ثانیه یک بار و در مجموع سه بار اجرا می‌شود:

from threading import Timer

count = 0

def tick():
    global count, timer
    count += 1
    print('tick', count)
    if count < 3:                 # schedule the next run
        timer = Timer(1, tick)
        timer.start()

timer = Timer(1, tick)
timer.start()

هر بار که tick اجرا می‌شود، اگر هنوز به سقف تعیین‌شده نرسیده باشیم یک Timer تازه برای اجرای بعدی می‌سازد. برای متوقف‌کردن این چرخه کافی است شرط ادامه را برقرار نکنید یا روی آخرین تایمر cancel را صدا بزنید.

موارد استفاده

برخی از کاربردهای رایج Timer عبارت‌اند از:

  1. اجرای وظایف به‌تأخیرافتاده: اجرای یک عملیات بعد از مدت‌زمانی مشخص، مثل ارسال یک یادآوری یا انجام یک عملیات پاک‌سازی.
  2. زمان‌بندی وظایف دوره‌ای: هرچند Timer برای کارهای تک‌باره طراحی شده، با اجرای دوباره‌ی تایمر در انتهای تابع می‌توان یک عملکرد تکرارشونده ساخت.
  3. ارسال اعلان‌ها و یادآوری‌ها: اطلاع‌رسانی به کاربر برای انجام یک کار خاص بعد از گذشت مدت‌زمانی معین.
  4. عملیات با تأخیر در شبکه: در بسیاری از پروتکل‌ها به سازوکارهای timeout و retry نیاز است که با تأخیر زمانی کار می‌کنند.
  5. مدیریت زمان‌بندی در بازی‌ها: اجرای رویدادها، تولید دشمن جدید، یا تغییر امتیاز بازیکن پس از مدت‌زمانی مشخص.
  6. کنترل ربات‌ها و سیستم‌های اتوماسیون: زمان‌بندی دقیق اجرای عملیات و توالی‌های کاری در سیستم‌های صنعتی و رباتیک.

مثال‌های کاربردی

ارسال یادآوری به کاربر

import threading

def send_reminder():
    print("It's time to take a break!")

# send a reminder after 3600 seconds (1 hour)
reminder_timer = threading.Timer(3600, send_reminder)
reminder_timer.start()

زمان‌بندی پاک‌سازی حافظه‌ی موقت

import threading

def cleanup_cache():
    print("Cleaning up cache...")

# clean the cache after 600 seconds (10 minutes)
cache_cleanup_timer = threading.Timer(600, cleanup_cache)
cache_cleanup_timer.start()

اطلاع‌رسانی درباره‌ی وضعیت یک ترد

در این مثال یک وظیفه‌ی زمان‌بر داریم و می‌خواهیم اگر بعد از ۳ ثانیه هنوز تمام نشده بود، به کاربر پیام بدهیم که «هنوز در حال اجراست». اینجا Timer نقش یک ناظر را بازی می‌کند که وضعیت ترد اصلی را با is_alive() بررسی می‌کند:

import time
from threading import Thread, Timer

def task(name):
    print(f'task {name} started')
    time.sleep(5)
    print(f'task {name} finished')

def check_thread_status(thread):
    if thread.is_alive():
        print(f"{thread.name} is still running! please wait ...")

t1 = Thread(target=task, args=(1, ))
timer = Timer(3, check_thread_status, args=(t1, ))

t1.start()
timer.start()

چون task پنج ثانیه طول می‌کشد، سه ثانیه بعد از شروع، تایمر تابع check_thread_status را صدا می‌زند؛ در آن لحظه ترد هنوز زنده است و پیام هشدار چاپ می‌شود. در نهایت پس از پایان پنج ثانیه، پیام «finished» نمایش داده می‌شود.

در هر یک از این مثال‌ها، Timer به شما امکان می‌دهد عملیاتی را بعد از مدت‌زمانی مشخص اجرا کنید، بدون اینکه نیاز به حلقه‌های پیچیده یا مدیریت دستی زمان داشته باشید.

مقایسه Timer با sleep

به‌دلیل شباهت ظاهری Timer و sleep، گاهی ممکن است در انتخاب میان آن‌ها دچار سردرگمی شوید. تفاوت اصلی این است که Timer یک تابع را در یک ترد جداگانه و با تأخیر اجرا می‌کند و جریان برنامه را متوقف نمی‌کند؛ اما sleep صرفاً همان تردی را که در آن فراخوانی شده، برای مدتی متوقف (بلاک) می‌کند.

ویژگیTimersleep
کارکرداجرای یک تابع با تأخیرایجاد وقفه در اجرای ترد فعلی
مسدودکردن جریان برنامهخیر (در ترد جدا اجرا می‌شود)بله (ترد فعلی را متوقف می‌کند)
قابل لغو بودنبله، با cancel() پیش از اجراخیر، به‌راحتی قابل لغو نیست
مناسب برایزمان‌بندی یک کار برای آیندهمکث ساده در همین جریان اجرا

به‌طور خلاصه، اجرای تردی که با Timer به‌تأخیر افتاده را می‌توان پیش از اجرا شدنش لغو کرد، اما وقفه‌ای که با sleep ایجاد شده به‌سادگی قابل لغو نیست.

خلاصه

  • Timer زیرکلاسی از Thread است که یک تابع را پس از تأخیری مشخص، در یک ترد جداگانه اجرا می‌کند.
  • با start() شمارش آغاز می‌شود و با cancel() می‌توان اجرا را — تنها پیش از فرا رسیدن زمان — لغو کرد.
  • برای اجرای دوره‌ای، در انتهای تابع یک Timer جدید بسازید.
  • برخلاف sleep که ترد فعلی را بلاک می‌کند، Timer جریان اصلی برنامه را متوقف نمی‌کند و قابل لغو است.
Please login to bookmark Close
پیشرفت شما در «دوره آموزش کانکارنسی در پایتون» (17%)
نظرات

دیدگاهتان را بنویسید

17%
پیشرفت

سرفصل دوره

فهرست مطالب

سرفصل دوره

تمرین

این قسمت تمرین ندارد!

پاسخ تمرین ها

هنوز برای تمرین‌های این قسمت پاسخی ثبت نشده است!

اشتراک گذاری

چرا بهتره از فیلترشکن استفاده کنید؟

من همه ویدئو ها و پادکست های کُدباز رو توی یوتیوب و ساندکلود و پلتفرم هایی آپلود می‌کنم که اغلب فیلتر هستند.

اغلب آموزش‌ها ویدئو و پادکست دارند. پس اگر می‌خواهید از محتوای سایت بیشترین استفاده رو ببرید نیاز به فیلتر شکن دارید.

توجه داشته باشید که برای خرید از فروشگاه بهتره فیلتر شکن رو خاموش کنید.

تنظیمات

انتخاب زبان
تغییر تم