प्रतिनिधि इंटरव्यू विषय

कोडिंग इंटरव्यू: Python 3.13 asyncio.Queue को कैसे शट डाउन करना चाहिए?

कोडिंगकठिन
Offer.cc संपादकीय टीमप्रकाशित अपडेट किया गया

प्रश्न

ग्रेसफुल और आपातकालीन शटडाउन के साथ एक Python asyncio वर्कर पूल डिज़ाइन करें। Queue.shutdown(immediate=False/True), QueueShutDown, task_done, join, रद्दीकरण (cancellation), संस्करण संगतता और परीक्षणों की व्याख्या करें।

प्रॉम्प्ट और संदर्भ

एक asyncio.Queue कई वर्कर्स को कार्य वितरित करता है। परिनियोजन (deployment) के दौरान, निर्माताओं (producers) को नया कार्य स्वीकार करना बंद करना होगा, मौजूदा आइटम समाप्त होने चाहिए, और फिर वर्कर्स को बाहर निकलना चाहिए। किसी गंभीर विफलता के दौरान, ब्लॉक किए गए प्रोड्यूसर्स और उपभोक्ताओं (consumers) को तुरंत जागना चाहिए। Python 3.13 Queue.shutdown() के साथ दोनों पथ डिज़ाइन करें।

Python दस्तावेज़ कहता है कि डिफ़ॉल्ट shutdown(immediate=False) नए puts के लिए कतार को बंद कर देता है जबकि उपभोक्ताओं को मौजूदा आइटम निकालने (drain करने) की अनुमति देता है। immediate=True इसे ड्रेन करता है और सामान्य join() इनवेरिएंट का उल्लंघन कर सकता है। QueueShutDown दोनों पक्षों के लिए जीवनचक्र संकेत है।

साक्षात्कारकर्ता क्या परीक्षण कर रहा है

मजबूत उम्मीदवार उत्पादन रोकने को उपभोग रद्द करने से अलग करते हैं, प्रत्येक सफल get() को ठीक एक task_done() के साथ जोड़ते हैं, और बताते हैं कि तत्काल शटडाउन का अर्थ सफल प्रसंस्करण क्यों नहीं हो सकता। वे Python 3.12 फ़ॉलबैक और बाहरी I/O रद्दीकरण को भी कवर करते हैं।

पहले पूछने योग्य स्पष्टीकरण प्रश्न

  • क्या ग्रेसफुल शटडाउन को प्रत्येक स्वीकृत आइटम को समाप्त करना होगा?
  • क्या आपातकालीन शटडाउन कतारबद्ध कार्य को छोड़ (discard) सकता है, या टिकाऊ मुआवज़ा (durable compensation) आवश्यक है?
  • क्या प्रोड्यूसर्स एक इवेंट लूप में हैं, या थ्रेड्स/प्रोसेस में फैले हैं?
  • क्या वर्कर्स बाहरी I/O, पुनः प्रयास (retries), या इडेम्पोटेंट संचालन करते हैं?
  • उत्पादन में न्यूनतम Python संस्करण क्या है?

30-सेकंड उत्तर ढांचा

"ग्रेसफुल शटडाउन पहले अपस्ट्रीम इंटेक को रोकता है, फिर डिफ़ॉल्ट मोड के साथ queue.shutdown() को कॉल करता है। नए put कॉल्स QueueShutDown प्राप्त करते हैं; वर्कर्स मौजूदा आइटम्स को ड्रेन करते हैं और finally में task_done को कॉल करते हैं; समन्वयक (coordinator) queue.join() की प्रतीक्षा करता है और फिर निष्क्रिय वर्कर्स को रद्द करता है। आपातकालीन शटडाउन immediate=True का उपयोग करता है, यह स्वीकार करता है कि कतारबद्ध आइटम छोड़ दिए जाते हैं, और शुरुआती join वेक-अप को कभी भी सफलता के रूप में नहीं मानता है। प्रोड्यूसर्स और कंज्यूमर्स दोनों QueueShutDown को संभालते हैं। पुराने Python संस्करणों को एक सेंटिनल या एक क्लोजिंग रैपर की आवश्यकता होती है।"

चरण-दर-चरण गहन विश्लेषण

चरण 1: कतार इनवेरिएंट को परिभाषित करें

एक सीमित (bounded) कतार maxsize के साथ बैकप्रेशर लागू करती है। प्रत्येक सफल put अधूरे काउंट को बढ़ाता है, और प्रत्येक पूर्ण आइटम के लिए एक task_done की आवश्यकता होती है। join() का अर्थ है कि काउंट शून्य तक पहुँच गया; इसका अर्थ यह नहीं है कि वर्कर्स बाहर निकल गए हैं।

python
queue = asyncio.Queue(maxsize=100)
await queue.put(job)
job = await queue.get()
try:
    await process(job)
finally:
    queue.task_done()

चरण 2: उत्पादन को शालीनता से बंद करें

समन्वयक अपस्ट्रीम रीड्स को रोकता है, फिर shutdown(immediate=False) को कॉल करता है। भविष्य के puts, जिनमें क्षमता के लिए ब्लॉक किए गए प्रोड्यूसर्स शामिल हैं, QueueShutDown प्राप्त करते हैं। मौजूदा आइटम तब तक उपलब्ध रहते हैं जब तक कि कतार खाली न हो जाए, जिसके बाद get भी अपवाद उठाता है।

चरण 3: वर्कर्स को सही तरीके से बाहर निकालें

एक वर्कर QueueShutDown को एक सामान्य जीवनचक्र निकास मानता है। व्यावसायिक विफलताओं को task_done को छोड़ना नहीं चाहिए। कनेक्शन, लीज़ और अस्थायी फ़ाइलों को रिलीज़ करने के लिए finally का उपयोग करें।

python
async def worker(queue):
    while True:
        try:
            job = await queue.get()
        except asyncio.QueueShutDown:
            return
        try:
            await process(job)
        finally:
            queue.task_done()

चरण 4: वर्कर्स को ड्रेन करें और रोकें

queue.join() की प्रतीक्षा करें ताकि प्रत्येक स्वीकृत आइटम का लेखा-जोखा पूरा हो जाए, फिर उन वर्कर्स को रद्द करें जो get पर निष्क्रिय हैं। Task को रद्द करना यह गारंटी नहीं देता कि डेटाबेस या HTTP ऑपरेशन रुक जाएगा; ड्राइवर को अभी भी एक समय सीमा (deadline) या रद्दीकरण तंत्र की आवश्यकता होती है।

चरण 5: तत्काल शटडाउन को समझें

shutdown(immediate=True) कतार को ड्रेन करता है, ब्लॉक किए गए get और put कॉलर्स को जगाता है, और कार्य चलने से पहले join को रिलीज़ कर सकता है। इसका उपयोग केवल तभी करें जब कतारबद्ध आइटम छोड़ना स्वीकार्य हो या टिकाऊ मुआवज़ा पहले से मौजूद हो, सामान्य परिनियोजन के लिए नहीं।

चरण 6: कॉलर रद्दीकरण से कतार शटडाउन को अलग करें

QueueShutDown का अर्थ है कतार जीवनचक्र समाप्त हो गया; CancelledError का अर्थ है कॉलर ने कार्य रद्द कर दिया। दोनों लूप को रोकते हैं, लेकिन उन्हें लॉग और मेट्रिक्स में अलग-अलग कारणों की आवश्यकता होती है। BaseException को पकड़कर रद्दीकरण को न निगलें, और सफलतापूर्वक प्राप्त आइटम के लिए task_done से पहले कभी भी वापस न लौटें।

चरण 7: संस्करणों और सीमाओं को संभालें

shutdown और QueueShutDown को Python 3.13 में जोड़ा गया था। एक बहु-संस्करण सेवा स्टार्टअप पर समर्थन का पता लगा सकती है या क्लोजिंग रैपर का उपयोग कर सकती है। asyncio.Queue एक इवेंट लूप के लिए है; क्रॉस-थ्रेड कार्य के लिए थ्रेड-सुरक्षित कतार या मैसेजिंग सिस्टम की आवश्यकता होती है।

चरण 8: शटडाउन सिमेंटिक्स का परीक्षण करें

खाली और भरी हुई कतारों, अवरुद्ध उत्पादकों और उपभोक्ताओं, ग्रेसफुल ड्रेन, तत्काल ड्रेन, बार-बार शटडाउन, वर्कर त्रुटियों, कॉलर रद्दीकरण और प्रक्रिया समय सीमाओं का परीक्षण करें। प्रत्येक सफल get के लिए ठीक एक task_done का दावा (assert) करें, और तत्काल शटडाउन द्वारा खोए गए आइटम के लिए एक स्पष्ट डिस्कार्ड या मुआवज़ा परिणाम रिकॉर्ड करें।

मॉडल उच्च गुणवत्ता वाला उत्तर

"मैं ग्रेसफुल ड्रेन को आपातकालीन समाप्ति से अलग करता हूँ। ग्रेसफुल पथ अपस्ट्रीम इंटेक को रोकता है, डिफ़ॉल्ट शटडाउन को कॉल करता है, वर्कर्स को finally में task_done के साथ मौजूदा आइटम पूरा करने देता है, join की प्रतीक्षा करता है, फिर निष्क्रिय वर्कर्स को रद्द करता है। आपातकालीन पथ immediate=True का उपयोग करता है, कतारबद्ध-आइटम हानि को स्पष्ट रूप से स्वीकार करता है, और शुरुआती join सफलता को कॉल नहीं करता है। मैं Python संस्करण की जांच करता हूँ और पुराने रनटाइम के लिए एक सेंटिनल या रैपर फ़ॉलबैक रखता हूँ।"

सामान्य गलतियाँ

  • केवल एक स्टॉप्ड बूलियन सेट करना → ब्लॉक किए गए put/get कॉल्स कभी नहीं जागते → शटडाउन या एक स्पष्ट वेक-अप प्रोटोकॉल का उपयोग करें।
  • तत्काल शटडाउन प्लस join को सफलता मानना → छोड़े गए कार्य को पूर्ण रिपोर्ट किया जाता है → डिस्कार्ड और कारण को अलग से रिकॉर्ड करें।
  • task_done को भूल जाना → ग्रेसफुल join हमेशा के लिए हैंग हो जाता है → finally ब्लॉक में प्रत्येक get को पेयर करें।
  • उत्पादन बंद करने से पहले वर्कर्स को रद्द करना → नया काम आता रहता है → पहले अपस्ट्रीम को रोकें।
  • QueueShutDown और CancelledError को निगल जाना → वर्कर्स मज़बूती से बाहर नहीं निकल सकते → प्रत्येक जीवनचक्र कारण रिकॉर्ड करें और वापस लौटें।
  • थ्रेड्स में asyncio.Queue साझा करना → इवेंट-लूप सुरक्षा खो जाती है → एक थ्रेड-सुरक्षित कतार या मैसेजिंग सिस्टम का उपयोग करें।

अनुवर्ती प्रश्न और सशक्त उत्तर

अनुवर्ती 1: क्या आप ग्रेसफुल शटडाउन के बाद भी आइटम प्राप्त कर सकते हैं?

हाँ। मौजूदा आइटम प्राप्त किए जा सकते हैं; कतार खाली होने के बाद, बाद के get कॉल्स QueueShutDown उठाते हैं।

अनुवर्ती 2: तत्काल मोड join इनवेरिएंट का उल्लंघन क्यों करता है?

यह कतार को ड्रेन करता है और अधूरे लेखांकन को समायोजित करता है, इसलिए कार्य संसाधित होने से पहले join जाग सकता है। यह केवल उसी पथ से संबंधित है जो स्पष्ट रूप से हानि स्वीकार करता है या जिसके पास मुआवज़ा है।

अनुवर्ती 3: वर्तमान में संसाधित किए जा रहे आइटम का क्या होता है?

ग्रेसफुल शटडाउन इसके लिए प्रतीक्षा करता है। आपातकालीन शटडाउन वर्कर को रद्द कर देता है; डाउनस्ट्रीम संचालन को समय सीमा, रद्दीकरण और इडेम्पोटेंट मुआवजे का समर्थन करना चाहिए।

अनुवर्ती 4: आप Python 3.12 का समर्थन कैसे करते हैं?

कतार को एक क्लोज्ड स्थिति के साथ रैप करें, नए puts को अस्वीकार करें, सेंटिनल्स के साथ उपभोक्ताओं को जगाएं, और अवरुद्ध उत्पादकों को ट्रैक करें। समान अनुबंध परीक्षणों को रखते हुए अपग्रेड करने के बाद मूल API पर स्विच करें।

अनुवर्ती 5: क्या बार-बार शटडाउन सुरक्षित है?

रैपर को क्लोजिंग को इडेम्पोटेंट बनाना चाहिए और आइटमों को दोबारा प्रोसेस करने से बचना चाहिए। फिर भी उपयोग में आने वाले सटीक Python रनटाइम पर उत्पादक और उपभोक्ता वेक-अप व्यवहार का परीक्षण करें।

सार्वजनिक स्रोत

संबंधित प्रश्न

संबंधित इंटरव्यू टूल

कोडिंग प्रॉम्प्ट के लिए स्क्रीनशॉट का उपयोग करें

समस्या को कैप्चर करें, फिर क्रम से प्रतिबंधों (constraints), समाधान, कोड, एज केस और जटिलता पर काम करें।

टूल देखें