دليل المبتدئين لأمر Sleep في بايثون

هل مررت يوماً بيوم تشعر فيه أن الكود الخاص بك ينطلق في سباق؟ يمر النص بسرعة خاطفة قبل أن تقرأه، أو أن خطواتك المرتبة والمتسلسلة بعناية تنهار باستمرار دون سبب وجيه.

بصفتنا مطورين، فإننا نركز عادةً على تسريع الأمور، ولكن في هذه الحالة نريد إبطاءها حتى يعمل الكود الخاص بنا بشكل صحيح.

والخبر السار هو أن لغة بايثون تحتوي بالفعل على دالة بسيطة تقوم بذلك نيابة عنا.

المشكلة بالطبع تكمن في معرفة كيفية استخدامه بشكل صحيح. لذا تابع معي، وسأشرح لك بالتفصيل ما يفعله وكيف يعمل، بالإضافة إلى الأخطاء الشائعة وكيفية تجنبها.

ما هو أمر sleep في لغة بايثون؟

في جوهرها، تُعدّ دالة ()time.sleep في لغة بايثون وسيلةً لإيقاف أي عمليةٍ تقوم بها مؤقتًا. تُعطيها رقمًا، وينتظر برنامجك هذا العدد من الثواني قبل المتابعة.

يشبه الأمر الضغط على زر الإيقاف المؤقت في نتفليكس أثناء ذهابك لجلب طلبك من أوبر إيتس. الفيلم لم يتوقف ولم يعد إلى البداية، بل هو معلق مؤقتًا حتى ترغب في استئناف تشغيله.

مفهوم بسيط بما فيه الكفاية، ولكن لماذا نرغب في القيام بذلك؟

لأنّ الكود، بدون فترات توقف، غالباً ما يعمل بسرعة كبيرة تجعله غير مفيد. قد تظهر المخرجات بسرعة خاطفة قبل أن تتمكن من قراءتها، أو قد تتعطل العمليات لأنها لم تمنح الأنظمة الأخرى الوقت الكافي للاستجابة.

أسهل طريقة لفهم كل هذا هي رؤيته عملياً.

كيفية استخدام أمر sleep في بايثون

للوهلة الأولى، تبدو دالة ()time.sleep بسيطة للغاية:

  • يمكنك استيراد وحدة الوقت
  • امنحه بضع ثوانٍ للتوقف مؤقتًا
  • ثم يتوقف برنامجك مؤقتًا لعدد الثواني المذكور قبل المتابعة.

لكن القيمة الحقيقية تكمن في رؤية كيف تغير تلك التوقفات إحساسك بالبرنامج.

إضافة وقفات درامية

على سبيل المثال

تخيل أن لدينا سطرًا نصيًا بسيطًا: “مرحبًا، هل يوجد أحد هنا؟”

import time

print("Hello")
time.sleep(2)
print("...is anyone there?")

بترك فاصل زمني لمدة ثانيتين بين التحية والسؤال، يخلق ذلك توتراً وقليلاً من التشويق. تشعر وكأن أحدهم يكتب إليك.

كن صادقاً الآن. لو رأيت ذلك يظهر في بيئة التطوير المتكاملة الخاصة بك، لكنت ستصاب بالذعر، أليس كذلك؟

إضافة تأثيرات الآلة الكاتبة

يمكننا أيضاً استخدام التوقيت لأغراض جمالية أكثر.

على سبيل المثال

من الاستخدامات الكلاسيكية للدالة ()time.sleep إنشاء تأثير يشبه صوت الآلة الكاتبة:

import time

message = "Typing this out..."
for char in message:
    print(char, end="", flush=True)
    time.sleep(0.1)  # short pause between each character

بدلاً من طباعة الجملة كاملةً دفعةً واحدة، يطبع هذا البرنامج حرفاً حرفاً، مع توقف قصير جداً (عُشر ثانية). وهذا يُعطي شعوراً بمشاهدة شخص يكتب شيئاً ما بعناية على لوحة المفاتيح.

إذا كانت السرعة عالية جدًا، يختفي التأثير، وإذا كانت بطيئة جدًا، يصبح الأمر محبطًا. أما إذا كانت السرعة متوسطة، فستحصل على شعور رائع أشبه بالكتابة على الشاشة، مما يجعل الناتج أكثر جاذبية.

جعل الحلقات تبدو حقيقية

يمكن أن تساعد فترات التوقف أيضًا في جعل الحلقات تبدو أكثر واقعية.

على سبيل المثال

تخيل أنك قمت بإنشاء تطبيق يحاكي مستشعر درجة الحرارة:

import time
import random

for i in range(5):
    print("Temperature:", random.randint(20, 30))
    time.sleep(1)  # wait one second between readings

بدون التوقف، سترى خمس قراءات تومض فوراً. ولكن بإضافة تأخير لمدة ثانية واحدة، تشعر وكأن درجة الحرارة ترتفع ببطء.

التعامل مع عمليات إعادة المحاولة بشكل أكثر سلاسة

يساعد استخدام ()time.sleep أيضًا عندما تسوء الأمور.

على سبيل المثال

لنفترض أنك تقوم بجلب بيانات من الإنترنت وفشل الطلب. لن يفيد إعادة المحاولة فوراً لأن الخادم لم يستعد وضعه بعد.

import time
import requests

for attempt in range(3):
    try:
        response = requests.get("https://example.com")
        print("Success:", response.status_code)
        break
    except:
        print("Request failed, retrying...")
        time.sleep(2)  # wait 2 seconds before trying again

لذا، بإضافة فترة توقف لمدة ثانيتين، فإنك تمنح الاتصال فرصة لإعادة الضبط.

مفيد، أليس كذلك؟

الالتزام بحدود الأسعار

ثم هناك مسألة تحديد معدل النقل.

تسمح العديد من واجهات برمجة التطبيقات (APIs) بعدد محدود من الطلبات في الدقيقة، مما يعني أن إرسال عدد كبير جدًا من الطلبات بسرعة كبيرة قد يؤدي إلى حظر حسابك. مع ذلك، يُعد التوقف المؤقت بين الطلبات وسيلة فعّالة للحفاظ على أمان حسابك.

على سبيل المثال

لنفترض أن لدينا خادمًا يسمح بـ 100 طلب في الدقيقة – أي طلب واحد كل 0.6 ثانية تقريبًا. لتجنب الوقوع في “قائمة المخالفين” الخاصة بواجهة برمجة التطبيقات، يمكنك ببساطة اختيار تأخير أعلى بقليل من هذا الحد.

import time
import requests

urls = ["https://example.com/page1", "https://example.com/page2"]

for url in urls:
    response = requests.get(url)
    print("Fetched:", url)
    time.sleep(1)  # pause between requests to stay under the limit

هنا قمنا بضبطه على فترة توقف لمدة ثانية واحدة بين الطلبات.

كما ترون، يمكن أن تكون دالة ()time.sleep مفيدة للغاية. ولكن مع ذلك، هناك بعض الأمور التي قد تُسبب بعض المشاكل عند استخدامها.

الأخطاء الشائعة وأفضل الممارسات عند استخدام أمر sleep في بايثون

على الرغم من أن دالة ()time.sleep بسيطة من حيث المبدأ، إلا أنها من الدوال التي يسهل إساءة استخدامها. إليك ثلاثة أخطاء يقع فيها المبتدئون، وكيفية تجنبها.

الخطأ الأول: نسيان أن sleep يحجب كل شيء

من الأمور التي قد يغفل عنها البعض عند استخدام دالة ()time.sleep هو أن البرنامج بأكمله يتوقف أثناء انتظارها. هذا يعني أن بايثون لا تقوم بأي عمل خفي في الخلفية، بل تبقى في مكانها تنتظر انتهاء المؤقت.

هذا جيد بالنسبة للبرامج النصية الصغيرة، ولكنه قد يسبب مشاكل في البرامج الأكبر حجماً.

على سبيل المثال

تخيل روبوت محادثة يفترض أن يستجيب للمستخدمين فورًا. إذا أضفتَ أمر time.sleep(5) في منتصف الكود الخاص به، فإن هذا التوقف لمدة خمس ثوانٍ سيؤخر كل شيء. وبالتالي، سيبدو الروبوت غير مستجيب، وسيعتقد المستخدم أنه معطل.

import time

def greet():
    print("Hi there!")
    time.sleep(5)  # program frozen for 5 seconds
    print("How are you?")

print("Starting...")
greet()
print("Done")

عند تشغيل هذا، لا يحدث شيء لمدة خمس ثوانٍ بعد عبارة “مرحباً!”. يبدو الأمر كما لو أن البرنامج قد توقف، ولكنه في الحقيقة متوقف بسبب دالة ()sleep.

أفضل الممارسات هنا هي استخدام ()time.sleep للبرامج النصية البسيطة أو العروض التوضيحية أو المهام التي يتم التحكم فيها – بشكل أساسي، السيناريوهات التي قد يكون فيها التوقف التام منطقيًا.

لكن إذا كنتَ بحاجة، من جهة أخرى، إلى إدارة التوقيت في برنامج يتطلب معالجة مهام متعددة في آنٍ واحد، فستحتاج إلى أسلوب غير متزامن. في لغة بايثون الحديثة، يعني هذا عادةً استخدام البرمجة غير المتزامنة (async).

على سبيل المثال

إليك نفس الفكرة باستخدام asyncio.sleep، والتي تسمح للمهام الأخرى بالاستمرار في العمل أثناء فترة التوقف:

import asyncio

async def greet():
    print("Hi there!")
    await asyncio.sleep(5)  # program can do other work while waiting
    print("How are you?")

async def main():
    await asyncio.gather(greet(), greet())

asyncio.run(main())

الآن يتم تشغيل كلا التحيتين في نفس الوقت، لأن التوقف المؤقت لا يعيق البرنامج بأكمله.

الخلاصة: يُعدّ استخدام ()time.sleep مفيدًا عندما تريد إيقاف كل شيء للحظة. ولكن إذا كان برنامجك بحاجة إلى أن يظل سريع الاستجابة، فهو ليس الأداة المناسبة.

سنتناول asyncio.sleep بمزيد من التفصيل في منشور آخر.

الخطأ الثاني: استخدام sleep بدلاً من المنطق السليم

ومن الأخطاء الشائعة الأخرى التعامل مع ()time.sleep كشريط لاصق ولصقه في كل مكان لتغطية المشاكل.

قد يبدو من الأسهل إضافة وقفة مؤقتة و”الأمل في أن تكون الأمور جاهزة” بدلاً من التحقق منها فعلياً. لكن هذا النهج قد يفشل عند تشغيل البرنامج في بيئة واقعية.

على سبيل المثال

لنفترض أنك تنتظر إنشاء ملف:

import time
import os

# Bad approach
time.sleep(5)  # just hoping 5 seconds is enough
print("File found:", os.path.exists("output.txt"))

إذا ظهر الملف خلال 5 ثوانٍ، فلا مشكلة. أما إذا استغرق 6 ثوانٍ؟ فسيفشل برنامجك، حتى وإن ظهر الملف في النهاية. وإذا كان جاهزًا فورًا، فقد أضعت 5 ثوانٍ دون فائدة.

الأسلوب الأمثل هو التحقق فعلياً من صحة الشرط، والتكرار حتى يتحقق. بهذه الطريقة، يتكيف برنامجك مع الواقع بدلاً من التخمين.

import time
import os

# Better approach
while not os.path.exists("output.txt"):
    print("Waiting for file...")
    time.sleep(1)

print("File found!")

الآن ينتظر برنامجك المدة اللازمة. إذا ظهر الملف فورًا، ينتقل البرنامج إلى الملف التالي مباشرةً. أما إذا استغرق الأمر وقتًا أطول، فيستمر البرنامج في البحث حتى يظهر الملف.

لا يقتصر هذا الخطأ على الملفات فحسب. يستخدم المبتدئون أحيانًا خاصية “sleep” لانتظار تحميل مواقع الويب، أو استجابة قواعد البيانات، أو وصول مدخلات المستخدم. قد يبدو الأمر “ناجحًا” أثناء الاختبار، ولكنه هش وغير موثوق.

أفضل الممارسات هي استخدام خاصية “sleep” لتنظيم سرعة البرنامج، بدلاً من التخمين. إذا كنت تنتظر شيئًا خارجيًا، فتحقق من حالته الفعلية. بهذه الطريقة، يبقى برنامجك سريعًا عندما يكون ذلك ممكنًا، وبطيئًا عندما يتطلب الأمر ذلك.

الخطأ الثالث: الشعور بالحيرة عندما لا تتصرف المقاطعات كما هو متوقع

من مميزات دالة ()time.sleep أنها، أثناء توقف البرنامج مؤقتًا، لا تستجيب لأي شيء آخر. وهذا يشمل محاولتك إيقافه!

على سبيل المثال

لنفترض أنك قمت بتشغيل هذا الكود ثم ضغطت على Ctrl+C مباشرة بعد ظهور عبارة “بدء التشغيل…”:

import time

print("Starting...")
time.sleep(10)  # program is stuck here
print("Done")

قد تتوقع أن يتوقف البرنامج فورًا. لكن بدلًا من ذلك، من المرجح أن يبقى معلقًا طوال الثواني العشر المتبقية قبل أن يُصدر المقاطعة أخيرًا، وهو ما قد يُشعرك بالإحباط وكأن البرنامج يتجاهلك.

يحدث هذا لأن دالة ()time.sleep تُعطّل بايثون على مستوى منخفض. فهي لا تتحقق بنشاط من الإشارات أثناء فترة السكون، لذا يجب أن ينتظر المقاطعة حتى تنتهي فترة السكون.

في أغلب الأحيان، لا يُعدّ هذا الأمر مشكلة كبيرة، لكن من المهم الانتباه إليه. إذا وجدت نفسك تنتظر وقتًا طويلاً لإيقاف البرنامج النصي، فحاول استخدام فترات انتظار أقصر في حلقة تكرارية بدلاً من فترة انتظار واحدة طويلة.

import time

print("Starting...")
for _ in range(10):  # 10 smaller pauses
    time.sleep(1)
print("Done")

الآن إذا ضغطت على Ctrl+C، فإن البرنامج يتحقق من ذلك كل ثانية، لذا يمكنك الخروج بشكل أسرع بكثير.

أفضل طريقة هنا بسيطة: عندما تحتاج إلى فترات انتظار طويلة، قسّمها إلى أجزاء أصغر. هذا يمنحك مزيدًا من التحكم ويجعل برنامجك يبدو أقل عرضة للتوقف.

حان الوقت لتجربة هذا بنفسك!

كما ترون، على الرغم من أن ()time.sleep قد تكون واحدة من أبسط وظائف بايثون، إلا أنها أيضًا واحدة من أكثرها فائدة.

ومع ذلك، وكما هو الحال مع معظم الأدوات، سواء كانت بسيطة أم معقدة، فمن السهل إساءة استخدامها. استخدمها للتحكم في وتيرة العمل – وليس للتخمين – وانتبه إلى أنها تُعطّل كل شيء أثناء تشغيلها. وعندما تحتاج إلى فترات انتظار أطول، لا تتردد في تقسيمها إلى أجزاء أصغر حتى يظل برنامجك سريع الاستجابة.

بمجرد إتقان الأساسيات هنا، ستواجه حتماً حالات ترغب فيها بإضافة وقفة مؤقتة دون تجميد البرنامج بالكامل. هنا يأتي دور أدوات البرمجة غير المتزامنة مثل asyncio.sleep أو مكتبات الجدولة، لكن هذا موضوع لدليل آخر.

أفضل طريقة لإتقان الأساسيات، بالطبع، هي استخدام دالة sleep في برنامجك الخاص. لذا، تفضل باختيار أحد مشاريع بايثون الخاصة بك وجرّبها بنفسك.


اكتشاف المزيد من بايثون العربي

اشترك للحصول على أحدث التدوينات المرسلة إلى بريدك الإلكتروني.

اترك تعليقاً

لن يتم نشر عنوان بريدك الإلكتروني. الحقول الإلزامية مشار إليها بـ *

Scroll to Top

اكتشاف المزيد من بايثون العربي

اشترك الآن للاستمرار في القراءة والحصول على حق الوصول إلى الأرشيف الكامل.

Continue reading