asyncio की सहकारी कंकरेंसी समझें: आलसी कोरूटीन, निलंबन बिंदु, gather, TaskGroup और ब्लॉकिंग कॉल के जाल।
इस पाठ को Kodokon में खोलेंasyncio एक ही थ्रेड पर सहकारी कंकरेंसी लागू करता है: एक इवेंट लूप उन कोरूटीन का संचालन करता है जो हर await पर स्वेच्छा से नियंत्रण छोड़ देते हैं। एक बुनियादी बिंदु, जिसे अक्सर गलत समझा जाता है: किसी async def फ़ंक्शन को कॉल करने से कुछ नहीं चलता। यह एक निष्क्रिय कोरूटीन ऑब्जेक्ट बनाता है जिसका शरीर तभी आगे बढ़ता है जब उसे await से प्रतीक्षित किया जाए या लूप पर टास्क के रूप में शेड्यूल किया जाए।
import asyncio
async def greet() -> str:
return "hello"
coro = greet()
print(type(coro).__name__)
async def main() -> None:
print(await coro)
asyncio.run(main())await एक निलंबन बिंदु चिह्नित करता है: कोरूटीन वहीं जम जाता है, लूप नियंत्रण वापस ले लेता है और किसी दूसरे तैयार टास्क को आगे बढ़ाता है। दो await के बीच, आपका कोड बिना किसी व्यवधान के चलता है - अधिकांश संरचनाओं के लिए किसी लॉक की ज़रूरत नहीं। कई कोरूटीन को समानांतर (I/O के अर्थ में) चलाने के लिए, उन्हें asyncio.gather में लपेटें: एक-एक सेकंड की तीन प्रतीक्षाएँ कुल एक सेकंड में पूरी होती हैं, तीन में नहीं।
import asyncio
import time
async def fetch(name: str, delay: float) -> str:
await asyncio.sleep(delay)
return f"{name} done"
async def main() -> None:
start = time.perf_counter()
results = await asyncio.gather(
fetch("a", 1.0),
fetch("b", 1.0),
fetch("c", 1.0),
)
elapsed = time.perf_counter() - start
print(results)
print(f"total: {elapsed:.1f} s")
asyncio.run(main())डिफ़ॉल्ट रूप से, gather उठाए गए पहले अपवाद को आगे बढ़ाता है, लेकिन बाकी टास्क को पृष्ठभूमि में चलता छोड़ देता है - जो शायद ही कभी आप चाहते हैं। return_exceptions=True के साथ, अपवाद परिणाम के रूप में लौटाए जाते हैं, जिन्हें बाद में छाँटना होता है। Python 3.11 से, asyncio.TaskGroup को प्राथमिकता दें: पहली त्रुटि पर, सभी सहोदर टास्क साफ़-सुथरे ढंग से रद्द कर दिए जाते हैं, और एक से अधिक अपवाद एक ExceptionGroup में समूहित होकर ऊपर आते हैं, जिन्हें except* से पकड़ा जाता है।
import asyncio
import time
def blocking_io() -> str:
time.sleep(1)
return "report written"
async def main() -> None:
results = await asyncio.gather(
asyncio.to_thread(blocking_io),
asyncio.sleep(1, result="tick"),
)
print(results)
asyncio.run(main())fetch('a', 1.0), बिना किसी await या create_task के, क्या उत्पन्न करती है?asyncio.gather के ज़रिए एक साथ चलाए गए तीन asyncio.sleep(1): कुल कितना समय?time.sleep(2) क्यों वर्जित है?