పైథాన్లో కంకరెంట్ ప్రోగ్రామింగ్ శక్తిని అన్లాక్ చేయండి. అధిక-పనితీరు గల, స్కేలబుల్ అప్లికేషన్లను రూపొందించడానికి అసింకియో టాస్క్లను ఎలా సృష్టించాలో, నిర్వహించాలో మరియు రద్దు చేయాలో తెలుసుకోండి.
పైథాన్ అసింకియో మాస్టరింగ్: టాస్క్ క్రియేషన్ మరియు మేనేజ్మెంట్పై లోతైన అధ్యయనం
ఆధునిక సాఫ్ట్వేర్ డెవలప్మెంట్ ప్రపంచంలో, పనితీరు అత్యంత ముఖ్యం. అప్లికేషన్లు రెస్పాన్సివ్గా ఉంటాయని, వేలాది కంకరెంట్ నెట్వర్క్ కనెక్షన్లు, డేటాబేస్ క్వెరీలు మరియు API కాల్లను ఎటువంటి ఆటంకం లేకుండా నిర్వహించగలవని ఆశించబడుతుంది. I/O-బౌండ్ కార్యకలాపాల కోసం—ఇక్కడ ప్రోగ్రామ్ నెట్వర్క్ లేదా డిస్క్ వంటి బాహ్య వనరుల కోసం వేచి ఉండటంలో ఎక్కువ సమయం గడుపుతుంది—సాంప్రదాయ సింక్రోనస్ కోడ్ ఒక ముఖ్యమైన అవరోధంగా మారవచ్చు. ఇక్కడే అసింక్రోనస్ ప్రోగ్రామింగ్ ప్రకాశిస్తుంది, మరియు పైథాన్ యొక్క asyncio
లైబ్రరీ ఈ శక్తిని అన్లాక్ చేయడానికి కీలకం.
asyncio
యొక్క కంకరెన్సీ మోడల్ యొక్క ప్రధాన అంశం ఒక సరళమైన ఇంకా శక్తివంతమైన భావన: Task. కొరూటిన్లు ఏమి చేయాలో నిర్వచిస్తే, Tasks వాస్తవంగా పనులను పూర్తి చేస్తాయి. అవి కంకరెంట్ ఎగ్జిక్యూషన్ యొక్క ప్రాథమిక యూనిట్, మీ పైథాన్ ప్రోగ్రామ్లు బహుళ కార్యకలాపాలను ఏకకాలంలో నిర్వహించడానికి అనుమతిస్తుంది, తద్వారా త్రూపుట్ మరియు రెస్పాన్సివ్నెస్ను గణనీయంగా మెరుగుపరుస్తుంది.
ఈ సమగ్ర గైడ్ మిమ్మల్ని asyncio.Task
లోకి లోతైన అధ్యయనానికి తీసుకెళ్తుంది. క్రియేషన్ యొక్క బేసిక్స్ నుండి అధునాతన మేనేజ్మెంట్ ప్యాటర్న్లు, క్యాన్సిలేషన్ మరియు బెస్ట్ ప్రాక్టీసెస్ వరకు ప్రతిదానిని మేము అన్వేషిస్తాము. మీరు అధిక-ట్రాఫిక్ వెబ్ సర్వీస్, డేటా స్క్రాపింగ్ టూల్ లేదా రియల్-టైమ్ అప్లికేషన్ను రూపొందిస్తున్నా, Tasks ను మాస్టర్ చేయడం అనేది ఏదైనా ఆధునిక పైథాన్ డెవలపర్కు అవసరమైన నైపుణ్యం.
కొరూటిన్ అంటే ఏమిటి? త్వరిత రిఫ్రెషర్
పరిగెత్తడానికి ముందు, మనం నడవాలి. మరియు asyncio
ప్రపంచంలో, నడక అంటే కొరూటిన్లను అర్థం చేసుకోవడం. కొరూటిన్ అనేది async def
తో నిర్వచించబడిన ఒక ప్రత్యేక రకమైన ఫంక్షన్.
మీరు రెగ్యులర్ పైథాన్ ఫంక్షన్ను పిలిచినప్పుడు, అది ప్రారంభం నుండి ముగింపు వరకు అమలు అవుతుంది. అయితే, మీరు కొరూటిన్ ఫంక్షన్ను పిలిచినప్పుడు, అది వెంటనే అమలు కాదు. బదులుగా, అది ఒక కొరూటిన్ ఆబ్జెక్ట్ను తిరిగి ఇస్తుంది. ఈ ఆబ్జెక్ట్ చేయవలసిన పనికి ఒక బ్లూప్రింట్, కానీ అది స్వయంగా నిష్క్రియంగా ఉంటుంది. ఇది పాజ్ చేయబడిన గణన, దీనిని ప్రారంభించవచ్చు, నిలిపివేయవచ్చు మరియు పునఃప్రారంభించవచ్చు.
import asyncio
async def say_hello(name: str):
print(f"Preparing to greet {name}...")
await asyncio.sleep(1) # Simulate a non-blocking I/O operation
print(f"Hello, {name}!")
# Calling the function doesn't run it, it creates a coroutine object
coro = say_hello("World")
print(f"Created a coroutine object: {coro}")
# To actually run it, you need to use an entry point like asyncio.run()
# asyncio.run(coro)
మ్యాజిక్ కీవర్డ్ await
. ఇది ఈవెంట్ లూప్కు చెబుతుంది, "ఈ ఆపరేషన్ కొంత సమయం పట్టవచ్చు, కాబట్టి నన్ను ఇక్కడ పాజ్ చేసి వేరే పనిని చేసుకోనివ్వండి. ఈ ఆపరేషన్ పూర్తయినప్పుడు నన్ను మేల్కొలపండి." విరామం తీసుకుని సందర్భాలను మార్చగల ఈ సామర్థ్యం కంకరెన్సీని ఎనేబుల్ చేస్తుంది.
కంకరెన్సీ యొక్క హృదయం: asyncio.Taskను అర్థం చేసుకోవడం
కాబట్టి, కొరూటిన్ ఒక బ్లూప్రింట్. వంటగదిని (ఈవెంట్ లూప్) వంట ప్రారంభించమని ఎలా చెప్పాలి? ఇక్కడే asyncio.Task
వస్తుంది.
asyncio.Task
అనేది ఒక కొరూటిన్ను చుట్టి, దానిని asyncio ఈవెంట్ లూప్లో అమలు చేయడానికి షెడ్యూల్ చేసే ఒక ఆబ్జెక్ట్. దీన్ని ఇలా ఆలోచించండి:
- Coroutine (
async def
): ఒక వంటకం కోసం వివరణాత్మక రెసిపీ. - Event Loop: అన్ని వంటలు జరిగే కేంద్ర వంటగది.
await my_coro()
: మీరు వంటగదిలో నిలబడి, రెసిపీని దశలవారీగా అనుసరిస్తారు. వంటకం పూర్తయ్యే వరకు మీరు మరేమీ చేయలేరు. ఇది సీక్వెన్షియల్ ఎగ్జిక్యూషన్.asyncio.create_task(my_coro())
: మీరు రెసిపీని వంటగదిలోని చెఫ్కు (Task) అందించి, "దీనిపై పనిచేయడం ప్రారంభించండి" అని చెబుతారు. చెఫ్ వెంటనే ప్రారంభిస్తాడు, మరియు మీరు మరిన్ని రెసిపీలను అందించడం వంటి ఇతర పనులను చేయడానికి స్వేచ్ఛగా ఉంటారు. ఇది కంకరెంట్ ఎగ్జిక్యూషన్.
ప్రధాన తేడా ఏమిటంటే asyncio.create_task()
కొరూటిన్ను "బ్యాక్గ్రౌండ్లో" అమలు చేయడానికి షెడ్యూల్ చేస్తుంది మరియు వెంటనే మీ కోడ్కు నియంత్రణను తిరిగి ఇస్తుంది. మీరు Task
ఆబ్జెక్ట్ను తిరిగి పొందుతారు, ఇది ఈ కొనసాగుతున్న ఆపరేషన్కు హ్యాండిల్గా పనిచేస్తుంది. మీరు దాని స్థితిని తనిఖీ చేయడానికి, దానిని రద్దు చేయడానికి లేదా దాని ఫలితం కోసం తరువాత వేచి ఉండటానికి ఈ హ్యాండిల్ను ఉపయోగించవచ్చు.
మీ మొదటి Tasks ను సృష్టించడం: `asyncio.create_task()` ఫంక్షన్
Task ను సృష్టించడానికి ప్రాథమిక మార్గం asyncio.create_task()
ఫంక్షన్. ఇది కొరూటిన్ ఆబ్జెక్ట్ను దాని ఆర్గ్యుమెంట్గా తీసుకుంటుంది మరియు అమలు కోసం షెడ్యూల్ చేస్తుంది.
బేసిక్ సింటాక్స్
వాడకం చాలా సులభం:
import asyncio
async def my_background_work():
print("Starting background work...")
await asyncio.sleep(2)
print("Background work finished.")
return "Success"
async def main():
print("Main function started.")
# Schedule my_background_work to run concurrently
task = asyncio.create_task(my_background_work())
# While the task runs, we can do other things
print("Task created. Main function continues to run.")
await asyncio.sleep(1)
print("Main function did some other work.")
# Now, wait for the task to complete and get its result
result = await task
print(f"Task completed with result: {result}")
asyncio.run(main())
Task ను సృష్టించిన వెంటనే `main` ఫంక్షన్ దాని ఎగ్జిక్యూషన్ను కొనసాగించడాన్ని అవుట్పుట్ ఎలా చూపుతుందో గమనించండి. ఇది బ్లాక్ చేయదు. చివరిలో మనం స్పష్టంగా `await task` చేసినప్పుడు మాత్రమే ఇది విరామం తీసుకుంటుంది.
ఒక ప్రాక్టికల్ ఉదాహరణ: కంకరెంట్ వెబ్ రిక్వెస్ట్లు
బహుళ URLల నుండి డేటాను పొందడం వంటి ఒక సాధారణ సందర్భంలో Tasks యొక్క నిజమైన శక్తిని చూద్దాం. దీని కోసం, మేము ప్రసిద్ధ `aiohttp` లైబ్రరీని ఉపయోగిస్తాము, దీనిని మీరు `pip install aiohttp` తో ఇన్స్టాల్ చేయవచ్చు.
ముందుగా, సీక్వెన్షియల్ (నెమ్మదిగా) మార్గాన్ని చూద్దాం:
import asyncio
import aiohttp
import time
async def fetch_status(session, url):
async with session.get(url) as response:
return response.status
async def main_sequential():
urls = [
"https://www.python.org",
"https://www.google.com",
"https://www.github.com",
"https://www.microsoft.com"
]
start_time = time.time()
async with aiohttp.ClientSession() as session:
for url in urls:
status = await fetch_status(session, url)
print(f"Status for {url}: {status}")
end_time = time.time()
print(f"Sequential execution took {end_time - start_time:.2f} seconds")
# To run this, you would use: asyncio.run(main_sequential())
ప్రతి అభ్యర్థన సుమారు 0.5 సెకన్లు పడితే, మొత్తం సమయం సుమారు 2 సెకన్లు అవుతుంది, ఎందుకంటే ప్రతి `await` ఆ సింగిల్ అభ్యర్థన పూర్తయ్యే వరకు లూప్ను బ్లాక్ చేస్తుంది.
ఇప్పుడు, Tasks తో కంకరెన్సీ శక్తిని విడుదల చేద్దాం:
import asyncio
import aiohttp
import time
# fetch_status coroutine remains the same
async def fetch_status(session, url):
async with session.get(url) as response:
return response.status
async def main_concurrent():
urls = [
"https://www.python.org",
"https://www.google.com",
"https://www.github.com",
"https://www.microsoft.com"
]
start_time = time.time()
async with aiohttp.ClientSession() as session:
# Create a list of tasks, but don't await them yet
tasks = [asyncio.create_task(fetch_status(session, url)) for url in urls]
# Now, wait for all tasks to complete
statuses = await asyncio.gather(*tasks)
for url, status in zip(urls, statuses):
print(f"Status for {url}: {status}")
end_time = time.time()
print(f"Concurrent execution took {end_time - start_time:.2f} seconds")
asyncio.run(main_concurrent())
మీరు కంకరెంట్ వెర్షన్ను అమలు చేసినప్పుడు, మీరు నాటకీయ వ్యత్యాసాన్ని చూస్తారు. మొత్తం సమయం అన్ని అభ్యర్థనల మొత్తం కాకుండా, అత్యంత పొడవైన సింగిల్ అభ్యర్థన సమయం అవుతుంది. ఎందుకంటే మొదటి `fetch_status` కొరూటిన్ దాని `await session.get(url)` ను తాకిన వెంటనే, ఈవెంట్ లూప్ దానిని పాజ్ చేసి వెంటనే తదుపరిదాన్ని ప్రారంభిస్తుంది. అన్ని నెట్వర్క్ అభ్యర్థనలు ప్రభావవంతంగా ఏకకాలంలో జరుగుతాయి.
ఒక గ్రూప్ of Tasks ను నిర్వహించడం: అవసరమైన ప్యాటర్న్లు
వ్యక్తిగత పనులను సృష్టించడం గొప్పది, కానీ నిజ-ప్రపంచ అప్లికేషన్లలో, మీరు తరచుగా వాటిని ప్రారంభించడం, నిర్వహించడం మరియు సమకాలీకరించడం అవసరం. `asyncio` దీని కోసం అనేక శక్తివంతమైన సాధనాలను అందిస్తుంది.
ఆధునిక విధానం (Python 3.11+): `asyncio.TaskGroup`
Python 3.11 లో ప్రవేశపెట్టబడిన `TaskGroup` అనేది సంబంధిత పనుల సమూహాన్ని నిర్వహించడానికి కొత్త, సిఫార్సు చేయబడిన మరియు సురక్షితమైన మార్గం. ఇది స్ట్రక్చర్డ్ కంకరెన్సీ అని పిలువబడేదాన్ని అందిస్తుంది.
`TaskGroup` యొక్క ముఖ్య లక్షణాలు:
- గ్యారంటీడ్ క్లీనప్:
async with
బ్లాక్ అందులో సృష్టించబడిన అన్ని పనులు పూర్తయ్యే వరకు నిష్క్రమించదు. - బలమైన ఎర్రర్ హ్యాండ్లింగ్: గ్రూప్లోని ఏదైనా టాస్క్ మినహాయింపును పెంచితే, గ్రూప్లోని మిగిలిన అన్ని టాస్క్లు స్వయంచాలకంగా రద్దు చేయబడతాయి మరియు
async with
బ్లాక్ నుండి నిష్క్రమించినప్పుడు మినహాయింపు (లేదాExceptionGroup
) మళ్ళీ పెంచబడుతుంది. ఇది అనాథ టాస్క్లను నివారిస్తుంది మరియు ఊహించదగిన స్థితిని నిర్ధారిస్తుంది.
దీనిని ఎలా ఉపయోగించాలో ఇక్కడ ఉంది:
import asyncio
async def worker(delay):
print(f"Worker starting, will sleep for {delay}s")
await asyncio.sleep(delay)
# This worker will fail
if delay == 2:
raise ValueError("Something went wrong in worker 2")
print(f"Worker with delay {delay} finished")
return f"Result from {delay}s"
async def main():
print("Starting main with TaskGroup...")
try:
async with asyncio.TaskGroup() as tg:
task1 = tg.create_task(worker(1))
task2 = tg.create_task(worker(2)) # This one will fail
task3 = tg.create_task(worker(3))
print("Tasks created in the group.")
# This part of the code will NOT be reached if an exception occurs
# The results would be accessed via task1.result(), etc.
print("All tasks completed successfully.")
except* ValueError as eg: # Note the `except*` for ExceptionGroup
print(f"Caught an exception group with {len(eg.exceptions)} exceptions.")
for exc in eg.exceptions:
print(f" - {exc}")
print("Main function finished.")
asyncio.run(main())
మీరు దీనిని అమలు చేసినప్పుడు, `worker(2)` ఒక లోపాన్ని పెంచుతుందని మీరు చూస్తారు. `TaskGroup` దీనిని క్యాచ్ చేస్తుంది, ఇతర రన్నింగ్ టాస్క్లను ( `worker(3)` వంటివి) రద్దు చేస్తుంది, ఆపై `ValueError` ను కలిగి ఉన్న `ExceptionGroup` ను పెంచుతుంది. నమ్మదగిన సిస్టమ్లను రూపొందించడానికి ఈ ప్యాటర్న్ అద్భుతంగా బలమైనది.
క్లాసిక్ వర్క్హార్స్: `asyncio.gather()`
`TaskGroup` కంటే ముందు, `asyncio.gather()` అనేది బహుళ awaitables ను ఏకకాలంలో అమలు చేయడానికి మరియు అవన్నీ పూర్తి అయ్యే వరకు వేచి ఉండటానికి అత్యంత సాధారణ మార్గం.
`gather()` కొరూటిన్లు లేదా Tasks యొక్క సీక్వెన్స్ను తీసుకుంటుంది, వాటన్నింటినీ అమలు చేస్తుంది మరియు ఇన్పుట్ల వలె అదే క్రమంలో వాటి ఫలితాల జాబితాను తిరిగి ఇస్తుంది. ఇది "ఈ పనులన్నింటినీ అమలు చేయండి మరియు నాకు అన్ని ఫలితాలను ఇవ్వండి" అనే సాధారణ సందర్భానికి ఇది ఒక హై-లెవల్, అనుకూలమైన ఫంక్షన్.
import asyncio
async def fetch_data(source, delay):
print(f"Fetching from {source}...")
await asyncio.sleep(delay)
return {"source": source, "data": f"some data from {source}"}
async def main():
# gather can take coroutines directly
results = await asyncio.gather(
fetch_data("API", 2),
fetch_data("Database", 3),
fetch_data("Cache", 1)
)
print(results)
asyncio.run(main())
`gather()` తో ఎర్రర్ హ్యాండ్లింగ్: డిఫాల్ట్గా, `gather()` కు పాస్ చేయబడిన awaitables లో ఏదైనా ఒక మినహాయింపును పెంచితే, `gather()` వెంటనే ఆ మినహాయింపును ప్రచారం చేస్తుంది మరియు ఇతర రన్నింగ్ టాస్క్లు రద్దు చేయబడతాయి. మీరు `return_exceptions=True` తో ఈ ప్రవర్తనను మార్చవచ్చు. ఈ మోడ్లో, మినహాయింపును పెంచడానికి బదులుగా, అది సంబంధిత స్థానంలో ఫలితాల జాబితాలో ఉంచబడుతుంది.
# ... inside main()
results = await asyncio.gather(
fetch_data("API", 2),
asyncio.create_task(worker(1)), # This will raise a ValueError
fetch_data("Cache", 1),
return_exceptions=True
)
# results will contain a mix of successful results and exception objects
print(results)
సూక్ష్మ-స్థాయి నియంత్రణ: `asyncio.wait()`
`asyncio.wait()` అనేది పనుల సమూహంపై మరింత వివరణాత్మక నియంత్రణను అందించే ఒక తక్కువ-స్థాయి ఫంక్షన్. `gather()` వలె కాకుండా, ఇది నేరుగా ఫలితాలను తిరిగి ఇవ్వదు. బదులుగా, ఇది రెండు టాస్క్ల సెట్లను తిరిగి ఇస్తుంది: `done` మరియు `pending`.
దాని అత్యంత శక్తివంతమైన లక్షణం `return_when` పారామీటర్, ఇది ఇలా ఉండవచ్చు:
asyncio.ALL_COMPLETED
(default): అన్ని పనులు పూర్తయినప్పుడు తిరిగి వస్తుంది.asyncio.FIRST_COMPLETED
: కనీసం ఒక టాస్క్ పూర్తయిన వెంటనే తిరిగి వస్తుంది.asyncio.FIRST_EXCEPTION
: ఒక టాస్క్ మినహాయింపును పెంచినప్పుడు తిరిగి వస్తుంది. ఏ టాస్క్ మినహాయింపును పెంచకపోతే, అది `ALL_COMPLETED` కు సమానం.
ప్రతిస్పందించే మొదటిదాన్ని ఉపయోగించడం ద్వారా బహుళ అనవసరమైన డేటా మూలాలను ప్రశ్నించడం వంటి దృశ్యాలకు ఇది చాలా ఉపయోగకరంగా ఉంటుంది:
import asyncio
async def query_source(name, delay):
await asyncio.sleep(delay)
return f"Result from {name}"
async def main():
tasks = [
asyncio.create_task(query_source("Fast Mirror", 0.5)),
asyncio.create_task(query_source("Slow Main DB", 2.0)),
asyncio.create_task(query_source("Geographic Replica", 0.8))
]
done, pending = await asyncio.wait(tasks, return_when=asyncio.FIRST_COMPLETED)
# Get the result from the completed task
first_result = done.pop().result()
print(f"Got first result: {first_result}")
# We now have pending tasks that are still running. It's crucial to clean them up!
print(f"Cancelling {len(pending)} pending tasks...")
for task in pending:
task.cancel()
# Await the cancelled tasks to allow them to process the cancellation
await asyncio.gather(*pending, return_exceptions=True)
print("Cleanup complete.")
asyncio.run(main())
TaskGroup vs. gather() vs. wait(): ఏది ఎప్పుడు ఉపయోగించాలి?
- `asyncio.TaskGroup` (Python 3.11+) ను ఉపయోగించండి మీ డిఫాల్ట్ ఎంపికగా. దాని స్ట్రక్చర్డ్ కంకరెన్సీ మోడల్ ఒకే లాజికల్ ఆపరేషన్కు చెందిన పనుల సమూహాన్ని నిర్వహించడానికి సురక్షితమైనది, శుభ్రమైనది మరియు తక్కువ లోపభూయిష్టమైనది.
- `asyncio.gather()` ను ఉపయోగించండి స్వతంత్ర పనుల సమూహాన్ని అమలు చేయాలనుకున్నప్పుడు మరియు ఫలితాల జాబితాను కోరుకున్నప్పుడు. ఇది సాధారణ సందర్భాలలో, ముఖ్యంగా 3.11 కన్నా మునుపటి పైథాన్ వెర్షన్లలో ఇప్పటికీ చాలా ఉపయోగకరంగా ఉంటుంది మరియు కొంచెం సంక్షిప్తంగా ఉంటుంది.
- `asyncio.wait()` ను ఉపయోగించండి పూర్తి పరిస్థితులపై (ఉదా., మొదటి ఫలితం కోసం వేచి ఉండటం) సూక్ష్మ-స్థాయి నియంత్రణ అవసరమైన అధునాతన దృశ్యాల కోసం మరియు మిగిలిన పెండింగ్ పనులను మాన్యువల్గా నిర్వహించడానికి సిద్ధంగా ఉన్నప్పుడు.
Task Lifecycle మరియు మేనేజ్మెంట్
ఒక Task సృష్టించబడిన తర్వాత, మీరు Task ఆబ్జెక్ట్పై పద్ధతులను ఉపయోగించి దానితో సంభాషించవచ్చు.
Task Status ను తనిఖీ చేయడం
task.done()
: టాస్క్ పూర్తయితే (విజయవంతంగా, మినహాయింపుతో, లేదా రద్దుతో) `True` ను తిరిగి ఇస్తుంది.task.cancelled()
: టాస్క్ రద్దు చేయబడితే `True` ను తిరిగి ఇస్తుంది.task.exception()
: టాస్క్ మినహాయింపును పెంచితే, ఇది మినహాయింపు ఆబ్జెక్ట్ను తిరిగి ఇస్తుంది. లేకపోతే, అది `None` ను తిరిగి ఇస్తుంది. టాస్క్ `done()` అయిన తర్వాత మాత్రమే మీరు దీనిని కాల్ చేయవచ్చు.
ఫలితాలను పొందడం
ఒక టాస్క్ యొక్క ఫలితాన్ని పొందడానికి ప్రధాన మార్గం దానిని `await` చేయడం. టాస్క్ విజయవంతంగా పూర్తయితే, ఇది విలువను తిరిగి ఇస్తుంది. అది మినహాయింపును పెంచితే, `await task` ఆ మినహాయింపును మళ్ళీ పెంచుతుంది. అది రద్దు చేయబడితే, `await task` ఒక `CancelledError` ను పెంచుతుంది.
ప్రత్యామ్నాయంగా, ఒక టాస్క్ `done()` అని మీకు తెలిస్తే, మీరు `task.result()` ను కాల్ చేయవచ్చు. ఇది విలువలను తిరిగి ఇవ్వడం లేదా మినహాయింపులను పెంచడం పరంగా `await task` వలెనే ప్రవర్తిస్తుంది.
రద్దు కళ
సుదీర్ఘ-కాల ఆపరేషన్లను సున్నితంగా రద్దు చేయగల సామర్థ్యం నమ్మదగిన అప్లికేషన్లను రూపొందించడానికి చాలా కీలకం. మీరు టైమ్అవుట్, యూజర్ రిక్వెస్ట్ లేదా సిస్టమ్లోని వేరే చోట లోపం కారణంగా టాస్క్ను రద్దు చేయవలసి ఉంటుంది.
మీరు `task.cancel()` పద్ధతిని కాల్ చేయడం ద్వారా ఒక టాస్క్ను రద్దు చేస్తారు. అయితే, ఇది టాస్క్ను వెంటనే ఆపదు. బదులుగా, ఇది తదుపరి await
పాయింట్ వద్ద కొరూటిన్ లోపల `CancelledError` మినహాయింపును విసరడానికి షెడ్యూల్ చేస్తుంది. ఇది ఒక ముఖ్యమైన వివరాలు. ఇది నిష్క్రమించే ముందు క్లీనప్ చేయడానికి కొరూటిన్కు ఒక అవకాశాన్ని ఇస్తుంది.
బాగా ప్రవర్తించే కొరూటిన్ ఈ `CancelledError` ను సున్నితంగా హ్యాండిల్ చేయాలి, సాధారణంగా ఫైల్ హ్యాండిల్స్ లేదా డేటాబేస్ కనెక్షన్లు వంటి వనరులు మూసివేయబడతాయని నిర్ధారించడానికి `try...finally` బ్లాక్ను ఉపయోగించి.
import asyncio
async def resource_intensive_task():
print("Acquiring resource (e.g., opening a connection)...")
try:
for i in range(10):
print(f"Working... step {i+1}")
await asyncio.sleep(1) # This is an await point where CancelledError can be injected
except asyncio.CancelledError:
print("Task was cancelled! Cleaning up...")
raise # It's good practice to re-raise CancelledError
finally:
print("Releasing resource (e.g., closing connection). This always runs.")
async def main():
task = asyncio.create_task(resource_intensive_task())
# Let it run for a bit
await asyncio.sleep(2.5)
print("Main decides to cancel the task.")
task.cancel()
try:
await task
except asyncio.CancelledError:
print("Main has confirmed the task was cancelled.")
asyncio.run(main())
finally
బ్లాక్ అమలు అవుతుందని గ్యారంటీ ఉంది, ఇది క్లీనప్ లాజిక్ కోసం సరైన స్థానం.
టైమ్అవుట్లతో టైమ్అవుట్లను జోడించడం: `asyncio.timeout()` మరియు `asyncio.wait_for()`
మాన్యువల్గా స్లీప్ చేయడం మరియు రద్దు చేయడం విసుగు చెందిస్తుంది. `asyncio` ఈ సాధారణ ప్యాటర్న్ కోసం సహాయకులను అందిస్తుంది.
Python 3.11+ లో, `asyncio.timeout()` కాంటెక్స్ట్ మేనేజర్ ప్రాధాన్యత మార్గం:
async def long_running_operation():
await asyncio.sleep(10)
print("Operation finished")
async def main():
try:
async with asyncio.timeout(2): # Set a 2-second timeout
await long_running_operation()
except TimeoutError:
print("The operation timed out!")
asyncio.run(main())
పాత పైథాన్ వెర్షన్ల కోసం, మీరు `asyncio.wait_for()` ను ఉపయోగించవచ్చు. ఇది awaitable ను ఫంక్షన్ కాల్గా చుట్టి, ఇలాగే పనిచేస్తుంది:
async def main_legacy():
try:
await asyncio.wait_for(long_running_operation(), timeout=2)
except asyncio.TimeoutError:
print("The operation timed out!")
asyncio.run(main_legacy())
రెండు సాధనాలు టైమ్అవుట్ చేరుకున్నప్పుడు అంతర్గత టాస్క్ను రద్దు చేయడం ద్వారా పనిచేస్తాయి, `TimeoutError` (ఇది `CancelledError` యొక్క సబ్క్లాస్) ను పెంచుతాయి.
సాధారణ అపార్థాలు మరియు ఉత్తమ పద్ధతులు
Tasks తో పని చేయడం శక్తివంతమైనది, కానీ కొన్ని సాధారణ ఉచ్చులు ఉన్నాయి.
- అపార్థం: "ఫైర్ అండ్ ఫర్గెట్" తప్పు. `create_task` తో ఒక టాస్క్ను సృష్టించి, దానిని ఎప్పుడూ `await` చేయకపోవడం (లేదా `TaskGroup` వంటి మేనేజర్) ప్రమాదకరం. ఆ టాస్క్ మినహాయింపును పెంచితే, మినహాయింపు నిశ్శబ్దంగా కోల్పోవచ్చు మరియు టాస్క్ దాని పనిని పూర్తి చేయడానికి ముందే మీ ప్రోగ్రామ్ నిష్క్రమించవచ్చు. ఫలితాన్ని `await` చేయడానికి బాధ్యత వహించే ప్రతి టాస్క్కు ఎల్లప్పుడూ ఒక స్పష్టమైన యజమాని ఉండాలి.
- అపార్థం: `asyncio.run()` మరియు `create_task()` ను కలపడం. `asyncio.run(my_coro())` అనేది `asyncio` ప్రోగ్రామ్ను ప్రారంభించడానికి ప్రధాన ఎంట్రీ పాయింట్. ఇది కొత్త ఈవెంట్ లూప్ను సృష్టిస్తుంది మరియు ఇచ్చిన కొరూటిన్ పూర్తయ్యే వరకు అమలు చేస్తుంది. `asyncio.create_task(my_coro())` అనేది ఇప్పటికే రన్ అవుతున్న అసింక్ ఫంక్షన్లో కంకరెంట్ ఎగ్జిక్యూషన్ను షెడ్యూల్ చేయడానికి ఉపయోగించబడుతుంది.
- ఉత్తమ పద్ధతి: ఆధునిక పైథాన్ కోసం `TaskGroup` ను ఉపయోగించండి. దాని డిజైన్ మర్చిపోయిన టాస్క్లు మరియు హ్యాండిల్ చేయని మినహాయింపులు వంటి అనేక సాధారణ లోపాలను నిరోధిస్తుంది. మీరు పైథాన్ 3.11 లేదా అంతకంటే ఎక్కువ వెర్షన్లో ఉంటే, దానిని మీ డిఫాల్ట్ ఎంపికగా చేయండి.
- ఉత్తమ పద్ధతి: మీ టాస్క్లకు పేరు పెట్టండి. టాస్క్ను సృష్టించేటప్పుడు, `name` పారామీటర్ను ఉపయోగించండి: `asyncio.create_task(my_coro(), name='DataProcessor-123')`. డీబగ్గింగ్ కోసం ఇది అమూల్యమైనది. మీరు రన్ అవుతున్న అన్ని టాస్క్లను జాబితా చేసినప్పుడు, అర్థవంతమైన పేర్లను కలిగి ఉండటం మీ ప్రోగ్రామ్ ఏమి చేస్తుందో అర్థం చేసుకోవడానికి మీకు సహాయపడుతుంది.
- ఉత్తమ పద్ధతి: సున్నితమైన షట్డౌన్ను నిర్ధారించండి. మీ అప్లికేషన్ షట్ డౌన్ అవ్వాల్సిన అవసరం వచ్చినప్పుడు, రన్ అవుతున్న అన్ని బ్యాక్గ్రౌండ్ టాస్క్లను రద్దు చేయడానికి మరియు అవి సరిగ్గా శుభ్రం అయ్యే వరకు వేచి ఉండటానికి ఒక యంత్రాంగాన్ని కలిగి ఉన్నారని నిర్ధారించుకోండి.
అధునాతన భావనలు: గ్లింప్స్ బియాండ్
డీబగ్గింగ్ మరియు ఇంట్రోస్పెక్షన్ కోసం, `asyncio` రెండు ఉపయోగకరమైన ఫంక్షన్లను అందిస్తుంది:
asyncio.current_task()
: ప్రస్తుతం అమలు అవుతున్న కోడ్ కోసం `Task` ఆబ్జెక్ట్ను తిరిగి ఇస్తుంది.asyncio.all_tasks()
: ఈవెంట్ లూప్ ద్వారా ప్రస్తుతం నిర్వహించబడుతున్న అన్ని `Task` ఆబ్జెక్ట్ల సెట్ను తిరిగి ఇస్తుంది. ఇది మీ ప్రోగ్రామ్ ఏమి చేస్తుందో చూడటానికి డీబగ్గింగ్ కోసం గొప్పది.
మీరు `task.add_done_callback()` ఉపయోగించి టాస్క్లకు పూర్తయ్యే కాల్బ్యాక్లను కూడా అటాచ్ చేయవచ్చు. ఇది ఉపయోగకరంగా ఉన్నప్పటికీ, ఇది తరచుగా మరింత సంక్లిష్టమైన, కాల్బ్యాక్-శైలి కోడ్ నిర్మాణానికి దారితీస్తుంది. `await`, `TaskGroup`, లేదా `gather` ను ఉపయోగించే ఆధునిక పద్ధతులు సాధారణంగా రీడబిలిటీ మరియు మెయింటెనబిలిటీ కోసం ప్రాధాన్యత ఇవ్వబడతాయి.
ముగింపు
asyncio.Task
అనేది ఆధునిక పైథాన్లో కంకరెన్సీ యొక్క ఇంజిన్. Tasks యొక్క లైఫ్సైకిల్ను సృష్టించడం, నిర్వహించడం మరియు సున్నితంగా హ్యాండిల్ చేయడం ఎలాగో అర్థం చేసుకోవడం ద్వారా, మీరు మీ I/O-బౌండ్ అప్లికేషన్లను నెమ్మదిగా, సీక్వెన్షియల్ ప్రాసెస్ల నుండి అత్యంత సమర్థవంతమైన, స్కేలబుల్ మరియు రెస్పాన్సివ్ సిస్టమ్లుగా మార్చవచ్చు.
మేము `create_task()` తో కొరూటిన్ను షెడ్యూల్ చేసే ప్రాథమిక భావన నుండి `TaskGroup`, `gather()`, మరియు `wait()` లతో సంక్లిష్టమైన వర్క్ఫ్లోలను ఆర్కెస్ట్రేట్ చేయడం వరకు ప్రయాణాన్ని కవర్ చేసాము. నమ్మదగిన సాఫ్ట్వేర్ను రూపొందించడానికి మేము బలమైన ఎర్రర్ హ్యాండ్లింగ్, క్యాన్సిలేషన్ మరియు టైమ్అవుట్ల యొక్క క్లిష్టమైన ప్రాముఖ్యతను కూడా అన్వేషించాము.
అసింక్రోనస్ ప్రోగ్రామింగ్ ప్రపంచం చాలా విశాలమైనది, కానీ Tasks ను మాస్టర్ చేయడం అనేది మీరు తీసుకోగల అత్యంత ముఖ్యమైన అడుగు. ప్రయోగాలు చేయడం ప్రారంభించండి. మీ అప్లికేషన్ యొక్క సీక్వెన్షియల్, I/O-బౌండ్ భాగాన్ని కంకరెంట్ టాస్క్లను ఉపయోగించడానికి మార్చండి మరియు పనితీరు పెరుగుదలను మీ స్వంతంగా చూడండి. కంకరెన్సీ యొక్క శక్తిని స్వీకరించండి, మరియు మీరు తదుపరి తరం అధిక-పనితీరు గల పైథాన్ అప్లికేషన్లను రూపొందించడానికి బాగా సన్నద్ధులవుతారు.