آموزش ماژول threading – ویژگی daemon

Please login to bookmark Close

ویژگی daemon

برای اجرای یک ترد در پس‌زمینه می‌توان آن را به صورت daemon تعریف کرد. ترد ها به صورت پیش‌فرض daemon نیستند. استفاده از ترد های daemon برای توسعه سناریو های فرعی کمک کننده است.

سناریوی فرعی، سناریویی است که حذف کردن آن خللی در اجرا ایجاد نکند و برنامه بتواند متناسب با هدفی که برای آن توسعه یافته است همچنان خروجی بدهد. موارد زیر نمونه هایی از سناریو های فرعی هستند.

  • مانیتورینگ منابع هنگام اجرا
  • ارسال گزارش هنگام اجرا
  • ارسال اعلانات یا هشدار هایی هنگام اجرا
  • پاکسازی حافظه یا کش هنگام اجرا
  • ذخیره سازی خودکار یا پشتیبان گیری خودکار هنگام اجرا

مثال – اطلاع رسانی به کاربر

یک برنامه داریم که اجرای آن مدت زمان قابل توجهی طول خواهد کشید. در این هنگام ممکن است کاربر تصور کند که اجرای برنامه با مشکل مواجه شده و کل برنامه را متوقف کند. برای اینکه به کاربر اطلاع دهیم که همه چیز در حالت طبیعی در حال اجراست باید کاربر را از پیشرفت برنامه مطلع سازیم.

بدین منظور check_thread_status را توسعه داده ایم که یک ترد میگیرد و اگر اجرایش بیش از سه ثانیه طول بکشد، با نمایش یک پیام از کاربر میخواهد که بیشتر صبر کند.

import time
from threading import Thread

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

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

t1 = Thread(target=task, args=(1, ))
t2 = Thread(target=check_thread_status, args=(t1, ))

t1.start()
t2.start()

توضیح کد بالا:

  • خط ۴ تا ۷: تابع task را تعریف کرده‌ایم که اجرایش یک ثانیه طول می‌کشد.
  • خط ۹ تا ۱۲: تابع check_thread_status را داریم که یک ترد می‌گیرد و پس از سه ثانیه اگر ترد هنوز در حال اجرا باشد یک پیام به کاربر نمایش می‌دهد و او را از وضعیت اجرای ترد مطلع می‌سازد.
  • خط ۱۴: یک thread به نام t1 می‌سازیم که تابع task را اجرا می‌کند.
  • خط ۱۵: یک thread به نام t2 می‌سازیم که تابع check_thread_status را اجرا می‌کند.

مشکل کد بالا این است که تسک اصلی در یک ثانیه به صورت کامل اجرا می‌شود ولی چون check_thread_status سه ثانیه صبر می‌کند، اجرای کل برنامه سه ثانیه زمان می‌برد.

اکنون با اصلاح کد بالا به شکل زیر، check_thread_status را وادار می‌کنیم در پس‌زمینه اجرا شود.

import time
from threading import Thread

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

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

t1 = Thread(target=task, args=(1, ))
t2 = Thread(target=check_thread_status, args=(t1, ), daemon=True)

t1.start()
t2.start()

انواع حالات تعریف daemon

دو روش برای تعریف یک ترد به صورت daemon وجود دارد.

۱. روش اول – هنگام تعریف ترد

t2 = Thread(target=check_thread_status, args=(t1, ), daemon=True)

۲. روش دوم – پس از تعریف ترد

t2 = Thread(target=check_thread_status, args=(t1, ))
t2.daemon = True

متد های کاربردی daemon

isDaemon

مقدار ویژگی daemon یک ترد را برمی‌گرداند.

setDaemon

یک ورودی از نوع boolean می‌گیرد و براساس آن مقدار daemon یک ترد را تنظیم می‌کند.

نکته مهم در مورد متدها

این متدها منسوخ شده‌اند و پیشنهاد می‌شود به صورت مستقیم با ویژگی daemon کار کنید. به مثال زیر توجه کنید.

import time
from threading import Thread

def say_hi(name):
    time.sleep(1)
    print('hi', name)

t1 = Thread(target=say_hi, args=('Ali', ))
t2 = Thread(target=say_hi, args=('Firooze', ))
t3 = Thread(target=say_hi, args=('Hamid', ), daemon=True)
t4 = Thread(target=say_hi, args=('Saeed', ))

t4.daemon = True  # روش خوب
t4.setDaemon(True)  # روش منسوخ شده

t1.start()
t2.start()
t3.start()
t4.start()

print('t1', t1.daemon)  # روش خوب
print('t1', t1.isDaemon())  # روش منسوخ شده
print('t2', t2.daemon)  # روش خوب
print('t2', t2.isDaemon())  # روش منسوخ شده
print('t3', t3.daemon)  # روش خوب
print('t3', t3.isDaemon())  # روش منسوخ شده
print('t4', t4.daemon)  # روش خوب
print('t4', t4.isDaemon())  # روش منسوخ شده

نکته مهم در مورد تنظیم daemon

اگر بخواهید مقدار daemon را پس از فراخوانی متد start تغییر دهید با خطای RuntimeError مواجه خواهید شد.

به مثال زیر توجه کنید. این کد خطای RuntimeError دارد.

import time
from threading import Thread

def say_hi(name):
    time.sleep(1)
    print('hi', name)

t1 = Thread(target=say_hi, args=('mmreza', ))
t1.start()
t1.daemon = True  # نباید بعد start تنظیم شود

خلاصه

ویژگیdaemon Falsedaemon True
پیشفرض
اجرا در پس‌زمینه
پایان زندگیاجازه می‌دهد تا پایان زندگی برنامه اصلی (main thread) باقی بماند.اگر تمام ترد های غیر دیمون خاتمه یابند، به طور خودکار بسته می‌شود.
جدول مقایسه thread ها بر اساس ویژگی daemon
Please login to bookmark Close
پیشرفت شما در «دوره آموزش کانکارنسی در پایتون» (23%)
نظرات

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

23%
پیشرفت
فهرست مطالب

تمرین

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

پاسخ تمرین ها

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

اشتراک گذاری

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

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

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

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

تنظیمات

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