2025, Oct 17 11:31

Jupyter में asyncio.run() क्यों फेल होता है और क्या करें

Jupyter Notebook में asyncio को सही ढंग से चलाना सीखें: asyncio.run() क्यों RuntimeError देता है, और top-level await से मौजूदा event loop पर सुरक्षित चलाएँ.

Jupyter Notebook के भीतर asyncio कोड चलाना अक्सर लोगों को उलझा देता है। साधारण Python स्क्रिप्ट्स में आम तौर पर इस्तेमाल होने वाला पैटर्न—asyncio.run() कॉल करना—नोटबुक में RuntimeError फेंक देता है। वजह सीधी है, और समाधान भी, लेकिन इवेंट लूप से टकराव से बचने के लिए नोटबुक का सही तरीक़े से इस्तेमाल ज़रूरी है।

समस्या को दोहराना

नीचे दिया गया स्निपेट एक स्वतंत्र .py स्क्रिप्ट में चलता है, लेकिन नोटबुक की सेल में त्रुटि पैदा करता है:

import asyncio
async def do_job():
    await asyncio.sleep(1)
    return "Done"
asyncio.run(do_job())

Jupyter परिवेश में, यह आमतौर पर इस त्रुटि के साथ विफल होता है:

RuntimeError: Event loop is closed

असल में हो क्या रहा है

Jupyter के भीतर पहले से ही एक इवेंट लूप चल रहा होता है। asyncio.run() शुरू से नया इवेंट लूप बनाने और संभालने की कोशिश करता है। जब कोई लूप पहले से सक्रिय हो, तो नया लूप शुरू करना मुमकिन नहीं होता, और यही टकराव उस त्रुटि का कारण बनता है जिसे आप देखते हैं। एक सामान्य .py स्क्रिप्ट में तब तक कोई लूप नहीं चलता जब तक आप उसे शुरू न करें, इसलिए asyncio.run() बिना किसी टकराव के लूप को बनाकर खत्म कर सकता है।

Jupyter में async कोड चलाने का सही तरीका

नया लूप शुरू न करें। बस सेल में सीधे coroutine पर await करें। Jupyter top-level await को सपोर्ट करता है, इसलिए आप अपनी async फ़ंक्शनों को asyncio.run() में लपेटे बिना बुला सकते हैं।

import asyncio
async def do_job():
    await asyncio.sleep(1)
    return "Done"
await do_job()

यह नोटबुक के मौजूदा इवेंट लूप का उपयोग करता है और टकराव को पूरी तरह टाल देता है।

यह क्यों मायने रखता है

रनटाइम वातावरण के हिसाब से async कोड का व्यवहार बदल जाता है। .py स्क्रिप्ट में asyncio.run() उपयुक्त है, क्योंकि जब तक आप लूप शुरू नहीं करते, कोई सक्रिय लूप मौजूद नहीं होता। Jupyter Notebook में लूप पहले से चलता है, और asyncio.run() के साथ एक और लूप लाने की कोशिश असफल होगी। आप किस वातावरण में हैं, यह जानना उलझाने वाली त्रुटियों से बचाता है और ऐसा async कोड लिखने में मदद करता है जो अनुमानित रूप से चले।

निष्कर्ष

अगर आप नोटबुक में हैं, तो top-level await पर भरोसा करें और अपने coroutine को सीधे कॉल करें। अगर आप सामान्य स्क्रिप्ट में हैं, तो इवेंट लूप प्रबंधित करने के लिए asyncio.run() का उपयोग करें। यही छोटा-सा अंतर दोनों परिवेशों में आपके async वर्कफ़्लो को सहज रखेगा।

यह लेख StackOverflow के एक प्रश्न (लेखक: Salika Ansari) और Yokozuna के उत्तर पर आधारित है।