1. ما هو طابور Python؟

المفهوم الأساسي للطابور

الطابور (Queue) هو أحد هياكل البيانات، ويتبع طريقة تُسمى «FIFO (First In, First Out)». بمعنى أن العنصر المضاف أولاً يُستخرج أولاً وفق ترتيب المعالجة. يُستخدم هذا النظام في العديد من مجالات علوم الحاسوب والبرمجة، وهو أداة لا غنى عنها لمعالجة البيانات بكفاءة. على سبيل المثال، تُستخدم الطوابير في الحالات التالية.
  • جدولة المهام: تنفيذ المهام التي بدأت أولاً بترتيب.
  • التخزين المؤقت: تخزين كمية معينة من بيانات التدفق في الطابور ومعالجتها بالتتابع.
  • الاتصال بين الخيوط المتعددة: عند معالجة البيانات بواسطة عدة خيوط في آنٍ واحد، يمكن استخدام الطابور لإدارة ترتيب البيانات.
الوحدة queue المتوفرة في مكتبة بايثون القياسية هي أداة قوية تسمح بإجراء عمليات الطابور بسهولة. تحتوي هذه الوحدة على آلية قفل داخلية لتضمن نقل البيانات بأمان بين الخيوط.

2. استخدامات الطابور في بايثون

الاستخدامات العامة للطابور

هناك العديد من الحالات التي يتم فيها استخدام الطابور في بايثون. خاصةً، يكون الطابور مفيدًا في السيناريوهات التالية.
  • جدولة المهام: عند معالجة مهام متعددة بالتتابع، تُعد واحدة من أفضل الطرق. على سبيل المثال، عندما يتلقى خادم الويب عددًا كبيرًا من الطلبات، من خلال إضافة هذه الطلبات إلى الطابور بشكل متسلسل ومعالجتها بالترتيب، يتم استخدام الموارد بكفاءة.
  • تخزين البيانات المؤقت: يعمل كذاكرة مؤقتة لتخزين البيانات مؤقتًا أثناء معالجة التدفق، مما يسمح بالانتظار حتى تلحق المعالجة بالبيانات. على سبيل المثال، يكون مفيدًا في بث الفيديو ومعالجة البيانات في الوقت الحقيقي.
  • مشاركة البيانات بين الخيوط المتعددة: يمكن استخدام الطابور كأداة لتبادل البيانات بأمان بين الخيوط المختلفة. في برامج متعددة الخيوط، يمكن استخدام الطابور لتوزيع المهام بين الخيوط.
年収訴求

3. queue نظرة عامة على الوحدة

وصف الفئات

في وحدة queue الخاصة بـ Python، توجد ثلاث فئات رئيسية. سنقدم أدناه ميزات كل منها وكيفية استخدامها.
  1. Queue (طابور FIFO)
    • هو أبسط طابور، حيث يتم استخراج العنصر الذي أُضيف أولاً أولاً. يستخدم طريقة FIFO (First In, First Out).
    • مثال على الاستخدام:
    import queue q = queue.Queue() q.put("task1") q.put("task2") print(q.get()) ## "task1" يتم طباعتها
  2. LifoQueue (طابور LIFO)
    • مثل المكدس، يتم استخراج العنصر الذي أُضيف آخرًا أولاً. يستخدم طريقة LIFO (Last In, First Out).
    • مثال على الاستخدام:
    import queue q = queue.LifoQueue() q.put("task1") q.put("task2") print(q.get()) ## "task2" يتم طباعتها
  3. PriorityQueue (طابور أولوية)
    • يتم استخراج العناصر بناءً على الأولوية. القيم الأقل تُعامل كأولوية أعلى.
    • مثال على الاستخدام: import queue q = queue.PriorityQueue() q.put((1, "task1")) q.put((3, "task3")) q.put((2, "task2")) print(q.get()) ## "(1, 'task1')" يتم طباعتها
من المهم اختيار الفئة المناسبة وفقًا للظروف المختلفة.

4. طريقة تنفيذ طابور FIFO

طريقة الاستخدام الأساسية

طابور FIFO هو الشكل الأكثر شيوعًا للطابور. يمكن تنفيذه بسهولة باستخدام queue.Queue. فيما يلي مثال أساسي على عمليات طابور FIFO في بايثون.
import queue

## إنشاء طابور FIFO
q = queue.Queue()

## إضافة عناصر إلى الطابور
q.put("apple")
q.put("banana")
q.put("cherry")

## استخراج عناصر من الطابور
while not q.empty():
    print(q.get())
في هذا الكود، يتم استخراج العناصر بالترتيب "apple", "banana", "cherry"، وتُعرض كل منها. يتم استخدام طريقة empty() لتكرار العملية حتى يصبح الطابور فارغًا.

مثال على الاستخدام الفعلي

على سبيل المثال، عند معالجة الطلبات التي يتلقاها خادم الويب، يتم إضافة كل طلب إلى الطابور ومعالجته بالترتيب. في مثل هذه الحالات، يعمل طابور FIFO بفعالية.
RUNTEQ(ランテック)|超実戦型エンジニア育成スクール

5. عمليات متقدمة على الطابور

دوال الطابور

يحتوي وحدة queue في بايثون على العديد من الدوال المفيدة للتعامل مع الطابور بكفاءة. من خلال الاستفادة منها، يمكنك إجراء عمليات أكثر تقدماً. سنستعرض بعض الدوال الرئيسية.
  1. qsize()
    • تُعيد عدد العناصر المخزنة في الطابور. مفيدة للتحقق مما إذا كان الطابور فارغاً.
    • مثال على الاستخدام:
    q = queue.Queue() q.put("task1") print(q.qsize()) ## يتم طباعة 1
  2. empty()
    • تتحقق مما إذا كان الطابور فارغاً. تُعيد True أو False.
    • مثال على الاستخدام:
    q = queue.Queue() print(q.empty()) ## يتم طباعة True
  3. full()
    • تتحقق مما إذا كان الطابور ممتلئاً. يكون ذلك فعالاً عندما يتم تعيين maxsize.
    • مثال على الاستخدام:
    q = queue.Queue(maxsize=2) q.put("task1") q.put("task2") print(q.full()) ## يتم طباعة True
  4. put(item)
    • يضيف عنصرًا إلى الطابور. يتم تعيين block=True كقيمة افتراضية، وقد يحدث حجب. يمكن أيضًا تحديد مهلة لتقييد العملية.
    • مثال على الاستخدام:
    q = queue.Queue() q.put("task1")
  5. get()
    • يستخرج عنصرًا من الطابور. إذا لم يكن هناك عنصر، وفي حالة block=True، ينتظر حتى يتم إضافة عنصر.
    • مثال على الاستخدام: q = queue.Queue() q.put("task1") task = q.get() print(task) ## يتم طباعة "task1"
من خلال الاستفادة من هذه الدوال، يمكنك التعامل مع الطابور بكفاءة وإدارة بيانات أكثر تعقيدًا.

6. معالجة الاستثناءات في الطابور

معالجة الاستثناءات في الطابور

queue في الوحدة، يتم توفير استثناءات لمعالجة الأخطاء التي تحدث عند استخراج العناصر بكفاءة. هذا يتيح التعامل المناسب مع سلوك البرنامج عند حدوث الأخطاء.
  1. queue.Full
    • يحدث عندما يتم استدعاء put() بينما يكون الطابور ممتلئًا.
    • مثال على معالجة الاستثناء:
    try: q.put("task", block=False) except queue.Full: print("الطابور ممتلئ")
  2. queue.Empty
    • يحدث عندما يتم استدعاء get() بينما يكون الطابور فارغًا.
    • مثال على معالجة الاستثناء: try: task = q.get(block=False) except queue.Empty: print("الطابور فارغ")
هذه الاستثناءات مهمة بشكل خاص عند تنفيذ عمليات حظر. يُنصح بتنفيذ معالجة أخطاء مناسبة لضمان عدم توقف البرنامج بسبب الأخطاء.

7. استخدام الطابور في تعدد الخيوط في بايثون

إدارة المهام في تعدد الخيوط

وحدة queue في بايثون مفيدة بشكل خاص في بيئات تعدد الخيوط. باستخدام الطابور، يمكنك مشاركة البيانات بأمان بين الخيوط وتوزيع المهام بفعالية. فيما يلي مثال بسيط.
import queue
import threading

## إنشاء الطابور
q = queue.Queue()

## تعريف خيط العامل
def worker():
    while True:
        item = q.get()
        print(f"معالجة: {item}")
        q.task_done()

## تشغيل الخيط
threading.Thread(target=worker, daemon=True).start()

## إضافة المهام إلى الطابور
for item in range(5):
    q.put(item)

## انتظار إكمال جميع المهام
q.join()
print("اكتملت جميع المهام")
في هذا البرنامج، تقوم عدة خيوط بسحب المهام من الطابور ومعالجتها في آنٍ واحد، وتنتظر حتى تنتهي جميع المهام. باستخدام الطابور، يمكن تجنب تعارض البيانات بين الخيوط وإجراء المعالجة المتوازية بفعالية.

8. استخدام قائمة انتظار محدودة (Bounded Queue)

ما هي قائمة الانتظار المحدودة؟

قائمة الانتظار المحدودة (Bounded Queue) هي قائمة انتظار ذات سعة قصوى محددة. يساعد هذا النوع من قوائم الانتظار على منع إهدار الموارد تحت ظروف معينة. على سبيل المثال، عند معالجة خادم الويب لعدد كبير من الطلبات، يمكن وضع حدود لتجنب التحميل الزائد على النظام. للقائمة الانتظار المحدودة الميزات الرئيسية التالية.
  1. سلوك عندما لا يمكن إضافة عنصر عند محاولة إضافة عنصر جديد إلى قائمة الانتظار وهي ممتلئة، يتم تنفيذ سلوك وفقًا لسعة القائمة. السلوكان الشائعان هما التاليان.
  • رفض العنصر الجديد:عندما تمتلئ القائمة، لا تقبل أي عناصر إضافية، ويتم رفض إضافة العنصر الجديد.
  • استبدال العنصر القديم:يتم حذف أقدم عنصر في القائمة وإضافة العنصر الجديد في مكانه.
  1. إدارة الموارد تُستخدم قوائم الانتظار المحدودة لإدارة الموارد (مثل الذاكرة أو وحدة المعالجة المركزية) بكفاءة. تساعد على تجنب إهدار الموارد وتكون مفيدة عند معالجة المهام ضمن نطاق محدود.

مثال على الاستخدام

فيما يلي مثال على تنفيذ قائمة انتظار محدودة باستخدام Python.
import queue

## إنشاء قائمة انتظار محدودة
q = queue.Queue(maxsize=3)

## إضافة عناصر إلى القائمة
q.put("task1")
q.put("task2")
q.put("task3")

## محاولة إضافة عنصر آخر سيؤدي إلى حظر أو استثناء
try:
    q.put_nowait("task4")
except queue.Full:
    print("القائمة ممتلئة")
في هذا المثال، تم ضبط الحد الأقصى لحجم القائمة على 3، وعند محاولة إضافة العنصر الرابع يحدث استثناء queue.Full. بهذه الطريقة، تكون قائمة الانتظار المحدودة فعّالة لمنع التحميل الزائد على النظام.

9. الخلاصة

وحدة queue في Python تدير البيانات بكفاءة، وتعد أداة مفيدة للغاية في مختلف السيناريوهات مثل المعالجة المتوازية والاتصالات بين الخيوط. خصوصًا، باستخدام قوائم FIFO وLIFO وقوائم الأولوية، يمكن تحقيق إدارة مرنة للبيانات تتناسب مع مختلف السيناريوهات. علاوة على ذلك، من خلال إدخال معالجة الاستثناءات والقوائم المحدودة، يتم تعزيز التعامل مع الأخطاء وإدارة الموارد بكفاءة أكبر. عند التعامل مع معالجة بيانات معقدة في Python، يرجى الاستفادة من هذه الميزات.