JavaScript ನಿಂದ Python ಗೆ ಬದಲಾಗುವುದು ಒಂದೇ ರೀತಿಯ ರಸ್ತೆ ಚಿಹ್ನೆಗಳನ್ನು ಹೊಂದಿರುವ ಆದರೆ ವಿಭಿನ್ನ ಸಂಚಾರ ನಿಯಮಗಳನ್ನು ಹೊಂದಿರುವ ನಗರಕ್ಕೆ ಸ್ಥಳಾಂತರಗೊಂಡಂತೆ ಭಾಸವಾಗುತ್ತದೆ. ಇದರ syntax ಸ್ನೇಹಪರ ಮತ್ತು ಪರಿಚಿತವಾಗಿ ಕಾಣುತ್ತದೆ. ವ್ಯಾಕರಣದಲ್ಲಿಯೇ async ಮತ್ತು await ಇರುವುದನ್ನು ನೀವು ನೋಡುತ್ತೀರಿ, ಆದ್ದರಿಂದ ನಿಮ್ಮ ಮಾನಸಿಕ ಮಾದರಿ (mental model) ಸುಲಭವಾಗಿ ವರ್ಗಾವಣೆಯಾಗುತ್ತದೆ ಎಂದು ನೀವು ಭಾವಿಸುತ್ತೀರಿ. ಆದರೆ ಅದು ಹಾಗಲ್ಲ. JavaScript ನ ಒಂದು ಅಭ್ಯಾಸದ ಮಾದರಿಯು ಯಾವುದೇ ಕ್ರ್ಯಾಶ್ ಆಗದೆ, ಯಾವುದೇ ಎರರ್ ಲಾಗ್ ಮಾಡದೆ ಮತ್ತು ಕ್ವಿಕ್ ಕೋಡ್ ರಿವ್ಯೂನಲ್ಲಿ ಕಂಡುಬರದೆ ನಿಮ್ಮ Python ಕಾರ್ಯಕ್ಷಮತೆಯನ್ನು (performance) ಮೌನವಾಗಿ ಕುಸಿಯುವಂತೆ ಮಾಡುತ್ತದೆ.
JavaScript ನಿಮಗೆ ಹೇಗೆ 'ಪ್ರಾರಂಭಿಸಿ ಮರೆಯಲು' ಕಲಿಸುತ್ತದೆ
JavaScript ನಲ್ಲಿ, ಒಂದು async function call ತಕ್ಷಣವೇ ಕಾರ್ಯಪ್ರವೃತ್ತವಾಗುತ್ತದೆ (eager). ನೀವು ಅದನ್ನು ಇನ್ವೋಕ್ ಮಾಡಿದ ಕ್ಷಣವೇ, ಎಂಜಿನ್ ಒಂದು Promise ಅನ್ನು ರಚಿಸುತ್ತದೆ ಮತ್ತು ಕೆಲಸ ತಕ್ಷಣವೇ ಪ್ರಾರಂಭವಾಗುತ್ತದೆ. Event loop ಈಗಾಗಲೇ ಕೆಲಸದಲ್ಲಿ ತೊಡಗಿಸಿಕೊಳ್ಳುತ್ತದೆ. ಅದಕ್ಕಾಗಿಯೇ JavaScript ಡೆವಲಪರ್ಗಳು ಸಹಜವಾಗಿ ಈ ರೀತಿ ಕೋಡ್ ಬರೆಯುತ್ತಾರೆ:
const userPromise = fetchUser(id);
const ordersPromise = fetchOrders(id);
const user = await userPromise;
const orders = await ordersPromise;
ಯಾವುದೇ await ತಲುಪುವ ಮೊದಲೇ ಎರಡೂ ನೆಟ್ವರ್ಕ್ ರಿಕ್ವೆಸ್ಟ್ಗಳು ಕಾರ್ಯಪ್ರವೃತ್ತವಾಗಿರುತ್ತವೆ. ಮೊದಲ await fetchUser ಪರಿಹರಿಸುವವರೆಗೆ (resolves) ಪ್ರಸ್ತುತ ಫಂಕ್ಷನ್ ಅನ್ನು ಸ್ಥಗಿತಗೊಳಿಸುತ್ತದೆ, ಆದರೆ fetchOrders ಹಿಂದಿನ ಸಾಲಿನಿಂದಲೇ ಹಿನ್ನೆಲೆಯಲ್ಲಿ ಕಾರ್ಯನಿರ್ವಹಿಸುತ್ತಿರುತ್ತದೆ. ನಿಮಗೆ orders ವೇರಿಯೇಬಲ್ ಅಗತ್ಯವಿರುವ ಹೊತ್ತಿಗೆ, ಎರಡನೇ ರಿಕ್ವೆಸ್ಟ್ ಈಗಾಗಲೇ ಮುಗಿದಿರಬಹುದು. ಈ ಮಾದರಿಯು JavaScript ನಲ್ಲಿ ಎಷ್ಟು ಸಹಜವಾಗಿ ಕಾಣುತ್ತದೆ ಎಂದರೆ, ಅನೇಕ ಡೆವಲಪರ್ಗಳು ಇದನ್ನು ಕನ್ಕರನ್ಸಿ ಟ್ರಿಕ್ (concurrency trick) ಎಂದು ಭಾವಿಸುವುದೇ ಇಲ್ಲ. ಇದು ಕೇವಲ async ಕೆಲಸ ಮಾಡುವ ವಿಧಾನವಾಗಿದೆ.
Python ನ ಅಚ್ಚರಿ: ಒಂದು ಕೋಲ್ಡ್ ಕೊರೂಟಿನ್ (Cold Coroutine)
Python ವಿಭಿನ್ನ ನಿಯಮಗಳನ್ನು ಬಳಸುತ್ತದೆ. Python ನಲ್ಲಿ ನೀವು async def ಫಂಕ್ಷನ್ ಅನ್ನು ಕರೆ ಮಾಡಿದಾಗ, ನೀವು ಯಾವುದೇ ಕೆಲಸವನ್ನು ಪ್ರಾರಂಭಿಸುವುದಿಲ್ಲ. ನೀವು ಕೇವಲ ಒಂದು coroutine ಆಬ್ಜೆಕ್ಟ್ ಅನ್ನು ಪಡೆಯುತ್ತೀರಿ. ಇದನ್ನು ಕಾಗದದ ಮೇಲೆ ಬರೆದ ರೆಸಿಪಿ ಎಂದು ಭಾವಿಸಿ. ಪದಾರ್ಥಗಳ ಪಟ್ಟಿ ಇದೆ, ಹಂತಗಳು ಸ್ಪಷ್ಟವಾಗಿವೆ, ಆದರೆ ಓವನ್ನಲ್ಲಿ ಏನೂ ತಯಾರಾಗುತ್ತಿಲ್ಲ. ಯಾವುದಾದರೂ ಒಂದು ಅಂಶವು ಆ coroutine ಅನ್ನು explicitly event loop ಮೂಲಕ ನಡೆಸುವವರೆಗೆ, ಅದು ನಿಷ್ಕ್ರಿಯವಾಗಿಯೇ ಇರುತ್ತದೆ.
ಇಲ್ಲಿದೆ ಬಲೆ. ಬಳಕೆದಾರ ಮತ್ತು ಅವರ ಆರ್ಡರ್ಗಳನ್ನು ಬಯಸುವ JavaScript ಇಂಜಿನಿಯರ್ Python ನಲ್ಲಿ ಹೀಗೆ ಬರೆಯಬಹುದು:
user_coro = fetch_user(id)
orders_coro = fetch_orders(id)
user = await user_coro
orders = await orders_coro
ಇದು ಕನ್ಕರೆಂಟ್ ಆಗಿ ಕಾಣುತ್ತದೆ. ಕನ್ಕರೆಂಟ್ ಆಗಿರುವಂತೆ ಭಾಸವಾಗುತ್ತದೆ. ಆದರೆ ಇದು ಸಂಪೂರ್ಣವಾಗಿ ಸೀಕ್ವೆನ್ಷಿಯಲ್ (sequential).
ಮೊದಲ ಸಾಲು ನಿಷ್ಕ್ರಿಯವಾದ (dormant) coroutine ಅನ್ನು user_coro ಗೆ ನಿಯೋಜಿಸುತ್ತದೆ. ಎರಡನೇ ಸಾಲು ಮತ್ತೊಂದು ನಿಷ್ಕ್ರಿಯವಾದ coroutine ಅನ್ನು orders_coro ಗೆ ನಿಯೋಜಿಸುತ್ತದೆ. ಎಕ್ಸಿಕ್ಯೂಷನ್ await user_coro ಗೆ ಬಂದಾಗ, Python ಅಂತಿಮವಾಗಿ ಮೊದಲ ಕಾರ್ಯವನ್ನು ಪ್ರಾರಂಭಿಸುತ್ತದೆ ಮತ್ತು ಅದನ್ನು ಪೂರ್ಣಗೊಳಿಸುತ್ತದೆ. fetch_user ಮುಗಿದ ನಂತರವಷ್ಟೇ ಇಂಟರ್ಪ್ರೆಟರ್ await orders_coro ಗೆ ತಲುಪಿ ಎರಡನೇ ಕಾರ್ಯವನ್ನು ಪ್ರಾರಂಭಿಸುತ್ತದೆ. ನಿಮ್ಮ ಒಟ್ಟು ಎಕ್ಸಿಕ್ಯೂಷನ್ ಸಮಯವು ಎರಡೂ I/O ಆಪರೇಷನ್ಗಳ ಮೊತ್ತವಾಗಿರುತ್ತದೆ, ಅತಿ ಉದ್ದದ ಆಪರೇಷನ್ ಸಮಯವಲ್ಲ. ನೀವು ಅವುಗಳನ್ನು ಪ್ಯಾರಲಲ್ ಆಗಿ ನಡೆಸಲಿಲ್ಲ. ನೀವು ಅವುಗಳನ್ನು ಒಂದರ ನಂತರ ಒಂದರಂತೆ ಹೆಚ್ಚಿನ ಹಂತಗಳೊಂದಿಗೆ ನಡೆಸಿದ್ದೀರಿ.
ಈ ಬಗ್ ಏಕೆ ಅದೃಶ್ಯವಾಗಿರುತ್ತದೆ
ಇದು ತಿಂಗಳುಗಟ್ಟಲೆ ಉಳಿಯುವಂತಹ ಪರ್ಫಾರ್ಮೆನ್ಸ್ ರಿಗ್ರೆಷನ್ (performance regression) ವಿಧವಾಗಿದೆ. ಕೋಡ್ ಸರಿಯಾದ Python ಆಗಿದೆ. ಇದು type checkers ಮೂಲಕ ಪಾಸಾಗುತ್ತದೆ. ಇದು ಸರಿಯಾದ ಫಲಿತಾಂಶಗಳನ್ನು ನೀಡುತ್ತದೆ. ಆದರೆ ಇದು ಕೇವಲ ಅರ್ಧ ವೇಗದಲ್ಲಿ ಅಥವಾ ಅದಕ್ಕಿಂತ ಕೆಟ್ಟದಾಗಿ ಚಲಿಸುತ್ತದೆ. ಯಾವುದೇ stack trace ಅಥವಾ ಎಚ್ಚರಿಕೆ ಇಲ್ಲದ ಕಾರಣ, ಇಂಜಿನಿಯರಿಂಗ್ ತಂಡಗಳು ಹೆಚ್ಚಾಗಿ ಬೇರೆ ಎಲ್ಲೋ ಹುಡುಕುತ್ತಾರೆ. ಅವರು Redis ಕ್ಯಾಶೆಗಳನ್ನು ಸೇರಿಸುತ್ತಾರೆ, ಡೇಟಾಬೇಸ್ ಹಂತಗಳನ್ನು ಅಪ್ಗ್ರೇಡ್ ಮಾಡುತ್ತಾರೆ ಅಥವಾ ಹೋಸ್ಟಿಂಗ್ ಪ್ರದೇಶಗಳನ್ನು ಬದಲಾಯಿಸುತ್ತಾರೆ. ಆದರೆ ನಿಜವಾದ ಕಾರಣ await ವಾಸ್ತವವಾಗಿ ಏನು ಮಾಡುತ್ತದೆ ಎಂಬ ನಿರೀಕ್ಷೆಯಲ್ಲಿರುವ ಸೂಕ್ಷ್ಮ ವ್ಯತ್ಯಾಸವಾಗಿದೆ.
Python ಅನ್ನು ನಿಜವಾಗಿಯೂ ಕನ್ಕರೆಂಟ್ ಆಗಿ ನಡೆಸಲು ಮೂರು ಮಾರ್ಗಗಳು
ಇದನ್ನು ಸರಿಪಡಿಸಲು, ನೀವು Python ನ event loop ಗೆ ಕೆಲಸವನ್ನು ತಕ್ಷಣವೇ ಶೆಡ್ಯೂಲ್ ಮಾಡಲು ತಿಳಿಸಬೇಕು. ನಿಮಗೆ ಕೇವಲ ಒಂದು raw coroutine ಗಿಂತ ಹೆಚ್ಚು ಸಕ್ರಿಯವಾದದ್ದು ಬೇಕು. ನಿಮಗೆ ಒಂದು Task ಬೇಕು.
1. asyncio.create_task
JavaScript ಮಾದರಿಯ ನೇರ ಅನುವಾದವೆಂದರೆ ನಿಮ್ಮ coroutine ಅನ್ನು Task ನಲ್ಲಿ ಸುತ್ತುವುದು (wrap). ನೀವು Task ಅನ್ನು ರಚಿಸಿದ ತಕ್ಷಣ ಅದು event loop ನಲ್ಲಿ ಶೆಡ್ಯೂಲ್ ಆಗುತ್ತದೆ. ಇದು ಚಲನೆಯಲ್ಲಿರುವ JavaScript Promise ಗೆ ಅತ್ಯಂತ ಹತ್ತಿರದ Python ಸಮಾನಾರ್ಥಕವಾಗಿದೆ.
user_task = asyncio.create_task(fetch_user(id))
orders_task = asyncio.create_task(fetch_orders(id))
user = await user_task
orders = await_orders_task
ಈಗ ಮೊದಲ await ತಲುಪುವ ಮೊದಲೇ fetch_user ಮತ್ತು fetch_orders ಎರಡೂ ಕಾರ್ಯಪ್ರವೃತ್ತವಾಗಿರುತ್ತವೆ. ನೀವು await user_task ಗೆ ಬಂದಾಗ, ಆ ನಿರ್ದಿಷ್ಟ Task ಪೂರ್ಣಗೊಳ್ಳುವವರೆಗೆ ಮಾತ್ರ ನೀವು ವಿರಾಮ ತೆಗೆದುಕೊಳ್ಳುತ್ತೀರಿ, ಆದರೆ ಇನ್ನೊಂದು Task ಚಾಲನೆಯಲ್ಲಿರುತ್ತದೆ. ಒಂದು ವೇಳೆ fetch_orders ಮೊದಲು ಮುಗಿದರೆ, ಅದರ ಫಲಿತಾಂಶವು ನೀವು ಕೇಳುವವರೆಗೆ orders_task ಒಳಗೆ ಕಾಯುತ್ತಿರುತ್ತದೆ.
ಆದರೆ ಎಚ್ಚರವಿರಲಿ. ನೀವು ಒಂದು Task ಅನ್ನು ರಚಿಸಿ ಅದನ್ನು ಎಂದಿಗೂ await ಮಾಡದಿದ್ದರೆ, Python 'destroyed pending task' ಬಗ್ಗೆ ಎರರ್ ನೀಡುತ್ತದೆ. ನೀವು ನಿಮ್ಮ ಫಲಿತಾಂಶಗಳನ್ನು ಸಂಗ್ರಹಿಸುವುದನ್ನು ಮರೆಯಬಾರದು.
2. asyncio.gather
ನೀವು ಮುಂದಕ್ಕೆ ಹೋಗುವ ಮೊದಲು ಹಲವಾರು coroutines ಮುಗಿಯಬೇಕಿದ್ದರೆ, asyncio.gather ನಿಮಗಾಗಿ ಬಾಯ್ಲರ್ ಪ್ಲೇಟ್ (boilerplate) ಕೆಲಸವನ್ನು ನಿರ್ವಹಿಸುತ್ತದೆ. ಇದು ಪ್ರತಿಯೊಂದು coroutine ಅನ್ನು ಆಂತರಿಕವಾಗಿ Task ಆಗಿ ಶೆಡ್ಯೂಲ್ ಮಾಡುತ್ತದೆ ಮತ್ತು ಅವುಗಳನ್ನು ಒಟ್ಟಿಗೆ await ಮಾಡುತ್ತದೆ.
user, orders = await asyncio.gather(fetch_user(id), fetch_orders(id))
ಇದು ಸಂಕ್ಷಿಪ್ತ ಮತ್ತು ಓದಲು ಸುಲಭವಾಗಿದೆ. ಕಾರ್ಯಾಚರಣೆಗಳು ಸ್ವತಂತ್ರವಾಗಿದ್ದಾಗ ಮತ್ತು "ಇವೆಲ್ಲವನ್ನೂ ಚಲಾಯಿಸಿ, ನಂತರ ನನಗೆ ಪ್ರತಿ ಫಲಿತಾಂಶವನ್ನು ನೀಡಿ" ಎಂದು ಹೇಳುವ ಒಂದೇ ಸಾಲು ಬೇಕಾದಾಗ ಇದು ಅತ್ಯುತ್ತಮವಾಗಿ ಕೆಲಸ ಮಾಡುತ್ತದೆ. ಅಡಿಯಲ್ಲಿರುವ ಕಾರ್ಯಗಳು ಬೇರೆ ಕ್ರಮದಲ್ಲಿ ಪೂರ್ಣಗೊಂಡರೂ ಸಹ, ಇದು ಹಿಂದಿರುಗುವ ಲಿಸ್ಟ್ ಅಥವಾ ಟ್ಯೂಪಲ್ನಲ್ಲಿ ಆರ್ಗ್ಯುಮೆಂಟ್ಗಳ ಕ್ರಮವನ್ನು ಉಳಿಸಿಕೊಳ್ಳುತ್ತದೆ.
3. asyncio.TaskGroup
Python 3.11 TaskGroup ಅನ್ನು ಪರಿಚಯಿಸಿತು, ಇದು ಸ್ಟ್ಯಾಂಡರ್ಡ್ ಲೈಬ್ರರಿಗೆ (standard library) structured concurrency ಅನ್ನು ತರುತ್ತದೆ. ಕೈಯಾರೆ ಟಾಸ್ಕ್ಗಳನ್ನು (tasks) ರಚಿಸುವ ಬದಲು, ನೀವು context manager ಅನ್ನು ಬಳಸುತ್ತೀರಿ, ಇದು ಪ್ರತಿಯೊಂದು ಸೃಷ್ಟಿಸಿದ ಟಾಸ್ಕ್ ಸರಿಯಾಗಿ ಮುಕ್ತಾಯವಾಗುವುದನ್ನು ಖಚಿತಪಡಿಸುತ್ತದೆ. ಒಂದು ಟಾಸ್ಕ್ exception ಅನ್ನು ಉಂಟುಮಾಡಿದರೆ, ಉಳಿದವುಗಳು ಸ್ವಯಂಚಾಲಿತವಾಗಿ ರದ್ದಾಗುತ್ತವೆ (cancelled).
async with asyncio.TaskGroup() as tg:
user_task = tg.create_task(fetch_user(id))
orders_task = tg.create_task(fetch_orders(id))
user = user_task.result()
orders = orders_task.result()
ಈ ಮಾದರಿಯು (pattern) ಸಂಕೀರ್ಣ ಕೆಲಸದ ಹರಿವುಗಳಿಗೆ (complex workflows) ಅತ್ಯುತ್ತಮವಾಗಿದೆ. ಇದು Task ಅನ್ನು ಅನಾಥವಾಗಿ ಬಿಡುವ (orphaning) ಅಪಾಯವನ್ನು ತಪ್ಪಿಸುತ್ತದೆ ಮತ್ತು ಸಂಬಂಧಿತ ಕಾರ್ಯಾಚರಣೆಗಳ ಜೀವನಚಕ್ರವನ್ನು (lifecycle) ಒಂದೇ ತಾರ್ಕಿಕ ಅಡಿಯಲ್ಲಿ ಗುಂಪು ಮಾಡುತ್ತದೆ. ನಿಮ್ಮ codebase Python 3.11 ಅಥವಾ ಅದಕ್ಕಿಂತ ಹೊಸದರಲ್ಲಿ ಚಾಲನೆಯಲ್ಲಿದ್ದರೆ, fan-out concurrency ಗಾಗಿ ಇದು ಅತ್ಯಂತ ಸ್ವಚ್ಛವಾದ ಆರ್ಕಿಟೆಕ್ಚರ್ ಆಗಿದೆ.
ಮಾನಸಿಕ ಮಾದರಿ (Mental Model): await ಎಂದರೆ "ಇದನ್ನು ಈಗಲೇ ಚಲಾಯಿಸು" ಎಂದರ್ಥ
ಇದರ ಮೂಲ ಪಾಠವು ಭಾಷಾ ಸಂಬಂಧಿತವಾಗಿದೆ. JavaScript ನಲ್ಲಿ, ನೀವು await ಅನ್ನು "ಅಷ್ಟರಲ್ಲಿ" (meanwhile) ಎಂದು ಓದಬಹುದು. ನೀವು ಕೆಲಸವನ್ನು ಪ್ರಾರಂಭಿಸುತ್ತೀರಿ, ಇತರ ಕೆಲಸಗಳನ್ನು ಮಾಡುತ್ತೀರಿ ಮತ್ತು ಮೌಲ್ಯದ ಅಗತ್ಯವಿದ್ದಾಗ ಮಾತ್ರ ವಿರಾಮ ತೆಗೆದುಕೊಳ್ಳುತ್ತೀರಿ. Python ನಲ್ಲಿ, await ಎಂದರೆ "ಈ coroutine ಅನ್ನು ಅದರ ಮುಂದಿನ suspension point ಅಥವಾ ಪೂರ್ಣಗೊಳಿಸುವಿಕೆಯವರೆಗೆ ಚಲಾಯಿಸು" ಎಂದರ್ಥ. ಒಂದು ವೇಳೆ coroutine ಇನ್ನೂ schedule ಆಗದಿದ್ದರೆ, await ಅದನ್ನು schedule ಮಾಡುತ್ತದೆ. ಅದಕ್ಕಾಗಿಯೇ ನೀವು ಎರಡು raw coroutines ಅನ್ನು ಪ್ರಾರಂಭಿಸಿ ನಂತರ ಅವುಗಳನ್ನು await ಮಾಡಲು ಸಾಧ್ಯವಿಲ್ಲ. ಅಷ್ಟರಲ್ಲಿ ನೀವು event loop ಗೆ ಮಾಡಲು ಏನನ್ನೂ ನೀಡಿರುವುದಿಲ್ಲ.
Python coroutines ಗಳನ್ನು generator functions ನಂತೆ ಭಾವಿಸಿ. Generator ಅನ್ನು ಕರೆಯುವುದು ಅದನ್ನು iterate ಮಾಡುವುದಿಲ್ಲ. ನೀವು ಅದರ ಮೇಲೆ loop ಮಾಡಬೇಕು, next() ಅನ್ನು ಕರೆಯಬೇಕು ಅಥವಾ ಅದನ್ನು consumer ಗೆ ನೀಡಬೇಕು. Async ಕೂಡ ಅದೇ ರೀತಿಯಲ್ಲಿ ಕೆಲಸ ಮಾಡುತ್ತದೆ. asyncio.create_task ಎಂಬುದು "ಇದನ್ನು ಈಗಲೇ event loop ಮೇಲೆ ಇರಿಸು" ಎಂದು ಹೇಳುವ consumer ಆಗಿದೆ. ನಂತರದ await ಕೇವಲ ಕೆಲಸ ಮುಗಿದಿರುವ ಸಂಕೇತಕ್ಕಾಗಿ ಕಾಯುತ್ತದೆ.
ಸಹಾಯ ಮಾಡುವ ಒಂದು ನಿರ್ದಿಷ್ಟ ಅಭ್ಯಾಸವೆಂದರೆ: ನೀವು ಯಾವಾಗಲಾದರೂ await ಇಲ್ಲದೆ ಒಂದು async function call ಅನ್ನು variable ಗೆ ನಿಯೋಜಿಸಿದಾಗ, ನೀವು ಅದನ್ನು schedule ಮಾಡಿದ್ದೀರಾ ಎಂದು ನಿಮ್ಮನ್ನೇ ಕೇಳಿಕೊಳ್ಳಿ. ಬಲಬದಿಯ ಭಾಗವು (right-hand side) create_task, gather, ಅಥವಾ TaskGroup ನಲ್ಲಿ ಸುತ್ತುವರಿಯದಿದ್ದರೆ (wrapped), ಅದು ಚಾಲನೆಯಲ್ಲಿಲ್ಲ ಎಂದರ್ಥ. ಅದು ಕೇವಲ ಕೌಂಟರ್ ಮೇಲೆ ಇಟ್ಟಿರುವ ಒಂದು ರೆಸಿಪಿ ಇದ್ದಂತೆ.
ಸಾರಾಂಶ (Takeaway)
Python ನ async runtime ಶಕ್ತಿಯುತವಾಗಿದೆ, ಆದರೆ ಅದು ಸ್ಪಷ್ಟವಾದ ಉದ್ದೇಶವನ್ನು (explicit intent) ಬಯಸುತ್ತದೆ. ನೀವು ಕೇವಲ ಒಂದು function ಅನ್ನು ಕರೆದಿದ್ದಕ್ಕಾಗಿ ಭಾಷೆಯು background ಕೆಲಸವನ್ನು ಪ್ರಾರಂಭಿಸುವುದಿಲ್ಲ. ನೀವು JavaScript ನಿಂದ ಬರುತ್ತಿದ್ದರೆ, ನೀವು ಎಲ್ಲಿಯಾದರೂ coroutine ಅನ್ನು variable ನಲ್ಲಿ ಸಂಗ್ರಹಿಸಿ ನಂತರ ಅದನ್ನು await ಮಾಡುತ್ತಿದ್ದರೆ, ಆ ಎಲ್ಲಾ ಸ್ಥಳಗಳನ್ನು ಪರಿಶೀಲಿಸಿ (audit). ನೀವು ಅದನ್ನು ಮೊದಲು Task ಗೆ ಏರಿಸದ ಹೊರತು, ನೀವು async ಉಡುಪನ್ನು ಧರಿಸಿದ sequential code ಅನ್ನು ಬರೆದಿದ್ದೀರಿ ಎಂದರ್ಥ. ಕೆಲಸವನ್ನು Task ಮೂಲಕ ಪ್ರಾರಂಭಿಸಿ, ನಂತರ ಫಲಿತಾಂಶಗಳಿಗಾಗಿ ಕಾಯಿರಿ. ಈ ಮೂಲಕ ನೀವು Python async ಅನ್ನು ಮೌನವಾದ bottleneck ನಿಂದ ನಿಜವಾದ concurrency tool ಆಗಿ ಬದಲಾಯಿಸಬಹುದು.
