از طریق منوی جستجو مطلب مورد نظر خود در وبلاگ را به سرعت پیدا کنید
پایتون: تاخیر زمانی (خواب) برای اجرای کد ایجاد کنید
سرفصلهای مطلب
معرفی
تاخیر کد (همچنین به عنوان شناخته شده است خوابیدن) دقیقاً همان چیزی است که از نام آن پیداست، تاخیر در اجرای کد برای مدتی. رایجترین نیاز به تأخیر کد زمانی است که ما منتظر کد دیگری هستیم process به پایان برسد، تا بتوانیم با نتیجه آن کار کنیم process. در سیستمهای چند رشتهای، ممکن است یک نخ بخواهد برای پایان دادن به یک عملیات، برای ادامه کار با آن نتیجه، صبر کند تا رشتهای دیگر صبر کند.
مثال دیگر می تواند کاهش فشار باشد روی سروری که با آن کار می کنیم. به عنوان مثال، در حین خراش دادن وب (از لحاظ اخلاقی)، و پیروی از ToS وب سایت مورد نظر، پیروی از robots.txt
فایل – ممکن است بخواهید اجرای هر درخواست را به تعویق بیندازید تا منابع سرور را تحت الشعاع قرار ندهید.
بسته به درخواستهای زیادی که بهسرعت انجام میشوند، میتوانند روی سرور مورد نظر را به سرعت در اختیار بگیرید همه از اتصالات رایگان و به طور موثر تبدیل به یک حمله DoS. برای ایجاد فضای تنفسی و همچنین اطمینان از اینکه تأثیر منفی بر کاربران وب سایت یا خود وب سایت نمی گذاریم – تعداد درخواست های ارسالی را با تأخیر در هر یک محدود می کنیم.
دانش آموزی که منتظر نتایج امتحان است ممکن است با عصبانیت وب سایت مدرسه خود را تازه کند و منتظر اخبار باشد. از طرف دیگر، آنها ممکن است یک اسکریپت بنویسند که بررسی کند آیا وب سایت چیز جدیدی دارد یا خیر روی آی تی. به یک معنا، تاخیر کد می تواند از نظر فنی تبدیل شود زمان بندی کد با یک حلقه معتبر و شرط پایان – با فرض اینکه مکانیسم تاخیر موجود نیست مسدود کردن.
در این مقاله نگاهی خواهیم داشت روش به تاخیر انداختن اجرای کد در پایتون – همچنین به عنوان شناخته شده است خوابیدن.
تأخیر کد با time.sleep()
یکی از رایج ترین راه حل ها برای حل این مشکل است sleep()
عملکرد داخلی time
مدول. تعداد ثانیه هایی که شما می خواهید را می پذیرد process برای خوابیدن – بر خلاف بسیاری از زبان های دیگر که در آنها مستقر هستند میلی ثانیه:
import datetime
import time
print(datetime.datetime.now().time())
time.sleep(5)
print(datetime.datetime.now().time())
این نتیجه در:
14:33:55.282626
14:34:00.287661
کاملاً واضح است که ما می توانیم تاخیر 5s بین این دو را مشاهده کنیم print()
اظهارات، با دقت نسبتاً بالا – تا رقم دوم اعشار. اگر دوست دارید کمتر از آن بخوابید 1 دوم، شما به راحتی می توانید اعداد غیر کامل را نیز ارسال کنید:
print(datetime.datetime.now().time())
time.sleep(0.25)
print(datetime.datetime.now().time())
14:46:16.198404
14:46:16.448840
print(datetime.datetime.now().time())
time.sleep(1.28)
print(datetime.datetime.now().time())
14:46:16.448911
14:46:17.730291
با این حال، به خاطر داشته باشید که با 2 رقم اعشار، مدت زمان خواب ممکن است نباشد دقیقا روی نقطه، به ویژه از آنجایی که آزمایش آن سخت است، با توجه به این واقعیت که print()
اجرای دستورات نیز به زمان (متغیر) نیاز دارد.
با این حال، یک نقطه ضعف عمده در آن وجود دارد time.sleep()
عملکرد، در محیط های چند رشته ای بسیار قابل توجه است.
time.sleep() است مسدود کردن.
این موضوع را تصرف می کند روی و آن را برای مدت زمان مسدود می کند خواب. این باعث میشود که برای زمانهای انتظار طولانیتر نامناسب باشد، زیرا رشتههای پردازنده را در آن دوره زمانی مسدود میکند. علاوه بر این، این آن را برای آن نامناسب می کند برنامه های ناهمزمان و واکنشی، که اغلب به داده ها و بازخورد بلادرنگ نیاز دارند.
نکته دیگری که باید به آن توجه کرد time.sleep()
این واقعیت است که شما نمی توانید آن را متوقف کنید. پس از شروع، نمیتوانید بدون پایان کل برنامه آن را لغو کنید یا اگر شما باعث sleep()
خود روش برای پرتاب یک استثنا، که آن را متوقف می کند.
برنامه نویسی ناهمزمان و واکنشی
برنامه نویسی ناهمزمان حول اجرای موازی می چرخد - جایی که یک کار می تواند مستقل از جریان اصلی اجرا و تمام شود.
در برنامه نویسی همزمان – اگر الف تابع A تماس می گیرد تابع B، اجرا را متوقف می کند تا زمانی که تابع B اجرا را به پایان می رساند، پس از آن تابع A می تواند از سر گرفته شود.
در برنامه نویسی ناهمزمان – اگر الف تابع A تماس می گیرد تابع B، صرف نظر از وابستگی آن به نتیجه از تابع B، هر دو می توانند همزمان اجرا شوند و در صورت نیاز، صبر کن برای اینکه دیگری تمام کند تا از نتایج یکدیگر استفاده کند.
برنامه نویسی واکنشی زیر مجموعه ای از برنامه نویسی ناهمزمان، که باعث اجرای کد می شود به صورت واکنشی، هنگامی که داده ها ارائه می شوند، صرف نظر از اینکه آیا تابع قرار است باشد process در حال حاضر شلوغ است. برنامه نویسی واکنشی به شدت متکی است روی معماری های پیام محور (جایی که الف پیام به طور معمول یک است رویداد یا الف فرمان).
هر دو برنامه های Asynchronous و Reactive آنهایی هستند که به شدت از آنها رنج می برند کد مسدود کننده – بنابراین با استفاده از چیزی شبیه به time.sleep()
برای آنها مناسب نیست بیایید نگاهی به برخی بیاندازیم تأخیر کد غیر مسدود کننده گزینه ها.
تأخیر کد با asyncio.sleep()
بی پروا یک کتابخانه پایتون است که به نوشتن اختصاص یافته است هم زمان کد ، و استفاده می کند async
/await
نحو، که ممکن است برای توسعه دهندگانی که از آن در زبان های دیگر استفاده کرده اند آشنا باشد.
بیایید ماژول را از طریق نصب کنیم pip
:
$ pip install asyncio
پس از نصب ، می توانیم import
آن را در اسکریپت ما بازنویسی کرده و عملکرد ما را بازنویسی کنید:
import asyncio
async def main():
print(datetime.datetime.now().time())
await asyncio.sleep(5)
print(datetime.datetime.now().time())
asyncio.run(main())
هنگام کار با asyncio
، توابعی که به صورت ناهمزمان اجرا می شوند را علامت گذاری می کنیم async
، و await
نتایج عملیاتی مانند asyncio.sleep()
که در مقطعی در آینده به پایان خواهد رسید.
مشابه مثال قبلی، این خواهد شد print دو بار به فاصله 5 ثانیه:
17:23:33.708372
17:23:38.716501
اگرچه، این واقعاً مزیت استفاده را نشان نمی دهد asyncio.sleep()
. بیایید مثال را بازنویسی کنیم تا چند کار را به صورت موازی اجرا کنیم، جایی که این تمایز بسیار واضح تر است:
import asyncio
import datetime
async def intense_task(id):
await asyncio.sleep(5)
print(id, 'Running some labor-intensive task at ', datetime.datetime.now().time())
async def main():
await asyncio.gather(
asyncio.create_task(intense_task(1)),
asyncio.create_task(intense_task(2)),
asyncio.create_task(intense_task(3))
)
asyncio.run(main())
در اینجا، ما یک async
عملکرد، که یک کار فشرده را شبیه سازی می کند که 5 ثانیه طول می کشد تا به پایان برسد. سپس، با استفاده از asyncio
، چندتایی ایجاد می کنیم وظایف. هر یک وظیفه می تواند به صورت ناهمزمان اجرا شود، هرچند، تنها در صورتی که ما با آن ها تماس بگیر به صورت ناهمزمان اگر بخواهیم آنها را به صورت متوالی اجرا کنیم، آنها نیز به صورت متوالی اجرا می شوند.
برای فراخوانی موازی آنها، از عبارت استفاده می کنیم gather()
تابع، که خوب، وظایف را جمع آوری و اجرا می کند:
1 Running some labor-intensive task at 17:35:21.068469
2 Running some labor-intensive task at 17:35:21.068469
3 Running some labor-intensive task at 17:35:21.068469
اینها هستند همه اجرا شدند در همان زمان، و زمان انتظار برای این سه نفر 15 ثانیه نیست – 5 است.
از سوی دیگر، اگر بخواهیم این کد را بهینه کنیم تا از آن استفاده کنیم time.sleep()
بجای:
import asyncio
import datetime
import time
async def intense_task(id):
time.sleep(5)
print(id, 'Running some labor-intensive task at ', datetime.datetime.now().time())
async def main():
await asyncio.gather(
asyncio.create_task(intense_task(1)),
asyncio.create_task(intense_task(2)),
asyncio.create_task(intense_task(3))
)
asyncio.run(main())
ما بین هر کدام 5 ثانیه صبر می کنیم print()
بیانیه:
1 Running some labor-intensive task at 17:39:00.766275
2 Running some labor-intensive task at 17:39:05.773471
3 Running some labor-intensive task at 17:39:10.784743
تاخیر کد با تایمر
این Timer
کلاس یک است Thread
، که می تواند عملیات را تنها پس از سپری شدن یک دوره زمانی خاص اجرا و اجرا کند. این رفتار دقیقاً همان چیزی است که ما به دنبال آن هستیم، هرچند، استفاده از آن کمی بیش از حد است Thread
اگر قبلاً با یک سیستم چند رشته ای کار نمی کنید، کد را به تأخیر بیندازید.
این Timer
کلاس نیاز دارد start()
، و می توان از طریق متوقف شود cancel()
. سازنده آن یک عدد صحیح را می پذیرد که نشان دهنده تعداد ثانیه های انتظار قبل از اجرای پارامتر دوم – یک تابع است.
بیایید یک تابع بسازیم و از طریق a اجرا کنیم Timer
:
from threading import Timer
import datetime
def f():
print("Code to be executed after a delay at:", datetime.datetime.now().time())
print("Code to be executed immediately at:", datetime.datetime.now().time())
timer = Timer(3, f)
timer.start()
این نتیجه در:
Code to be executed immediately at: 19:47:20.032525
Code to be executed after a delay at: 19:47:23.036206
این cancel()
اگر چندین تابع در حال اجرا داشته باشیم و بخواهیم اجرای یک تابع را لغو کنیم، روش واقعاً مفید است. روی نتایج دیگری، یا روی یک شرط دیگر
بیایید یک تابع بنویسیم f()
، که تماس می گیرد روی هر دو f2()
و f3()
. f2()
As-is نامیده می شود – و یک عدد صحیح تصادفی بین 1 تا 10 را برمی گرداند و زمان اجرای آن تابع را شبیه سازی می کند.
f3()
از طریق الف فراخوانی می شود Timer
و اگر نتیجه از f2()
بزرگتر است از 5
، f3()
لغو می شود، در حالی که اگر f2()
در زمان “مورد انتظار” کمتر از 5
– f3()
پس از پایان تایمر اجرا می شود:
from threading import Timer
import datetime
import random
def f():
print("Executing f1 at", datetime.datetime.now().time())
result = f2()
timer = Timer(5, f3)
timer.start()
if (result > 5):
print("Canceling f3 since f2 resulted in", result)
timer.cancel()
def f2():
print("Executing f2 at", datetime.datetime.now().time())
return random.randint(1, 10)
def f3():
print("Executing f3 at", datetime.datetime.now().time())
f()
اجرای چندین بار این کد چیزی شبیه به موارد زیر به نظر می رسد:
Executing f1 at 20:29:10.709578
Executing f2 at 20:29:10.709578
Canceling f3 since f2 resulted in 9
Executing f1 at 20:29:14.178362
Executing f2 at 20:29:14.178362
Executing f3 at 20:29:19.182505
تأخیر کد با رویداد
این Event
کلاس می تواند برای تولید رویدادها استفاده شود. یک رویداد واحد را می توان توسط چندین رشته “گوش داد”. این Event.wait()
تابع بلوک ها موضوع آن است روی، مگر اینکه Event.isSet()
. یک بار شما set()
یک رویداد، تمام رشته هایی که منتظر بودند بیدار می شوند و Event.wait()
تبدیل می شود غیر مسدود کردن.
این می تواند برای همگام سازی رشته ها استفاده شود – همه آنها روی هم انباشته می شوند و wait()
تا زمانی که یک رویداد خاص تنظیم شود، پس از آن، آنها می توانند جریان خود را دیکته کنند.
بیایید یک را ایجاد کنیم waiter
روش و چندین بار اجرا کنید روی رشته های مختلف هر پیشخدمت در یک زمان خاص شروع به کار می کند و بررسی می کند که آیا هنوز کار می کند یا خیر روی ساعت در هر ثانیه، درست قبل از اینکه آنها سفارشی را بگیرند، که انجام آن یک ثانیه طول می کشد. آنها تا زمانی که رویداد تنظیم شود – یا بهتر است بگوییم، زمان کار آنها تمام شود، کار خواهند کرد.
هر پیشخدمت رشته مخصوص به خود را خواهد داشت، در حالی که مدیریت در موضوع اصلی قرار دارد و زمانی که همه می توانند با خانه تماس بگیرند، تماس می گیرند. از آنجایی که امروز احساس سخاوت بیشتری میکنند، زمان کار را کاهش میدهند و به پیشخدمتها اجازه میدهند بعد از 4 ثانیه کار به خانه بروند:
import threading
import time
import datetime
def waiter(event, id):
print(id, "Waiter started working at", datetime.datetime.now().time())
event_flag = end_of_work.wait(1)
while not end_of_work.isSet():
print(id, "Waiter is taking order at", datetime.datetime.now().time())
event.wait(1)
if event_flag:
print(id, "Waiter is going home at", datetime.datetime.now().time())
end_of_work = threading.Event()
for id in range(1, 3):
thread = threading.Thread(target=waiter, args=(end_of_work, id))
thread.start()
end_of_work.wait(4)
end_of_work.set()
print("Some time passed, management was nice and cut the working hours short. It is now", datetime.datetime.now().time())
اجرای این کد نتیجه می دهد:
1 Waiter started working at 23:20:34.294844
2 Waiter started working at 23:20:34.295844
1 Waiter is taking order at 23:20:35.307072
2 Waiter is taking order at 23:20:35.307072
1 Waiter is taking order at 23:20:36.320314
2 Waiter is taking order at 23:20:36.320314
1 Waiter is taking order at 23:20:37.327528
2 Waiter is taking order at 23:20:37.327528
Some time passed, management was nice and cut the working hours short. It is now 23:20:38.310763
این end_of_work
رویداد در اینجا برای همگامسازی دو رشته و کنترل زمانی که کار میکنند و زمانی که کار نمیکنند، استفاده میشود و اجرای کد را با زمان مشخصی بین بررسیها به تأخیر میاندازد.
نتیجه
در این راهنما، ما نگاهی به چندین روش برای به تاخیر انداختن اجرای کد در پایتون انداختهایم – که هر کدام در زمینه و نیاز متفاوتی قابل استفاده هستند.
معمولی time.sleep()
این روش برای اکثر برنامهها بسیار مفید است، اگرچه برای زمانهای انتظار طولانی واقعاً بهینه نیست، معمولاً برای زمانبندی ساده استفاده نمیشود و مسدود میشود.
استفاده کردن asyncio
، ما یک نسخه ناهمزمان از آن داریم time.sleep()
که ما می توانیم await
.
این Timer
کلاس اجرای کد را به تاخیر می اندازد و در صورت لزوم می توان آن را لغو کرد.
این Event
کلاس رویدادهایی را تولید می کند که چندین رشته می توانند به آن گوش دهند و بر اساس آن پاسخ دهند، و اجرای کد را تا زمانی که رویداد خاصی تنظیم شود به تاخیر می اندازد.
(برچسبها به ترجمه)# python
منتشر شده در 1403-01-10 23:05:05