পাইথনেরasyncioলাইব্রেরি হল 2026-এ প্রতিটি হাই-থ্রুপুট পাইথন পরিষেবা শিপিংয়ের মেরুদণ্ড — ফাস্টএপিআই এপিআই থেকে শুরু করে ডিসকর্ড বট পর্যন্ত ওয়েব স্ক্র্যাপাররা প্রতি মিনিটে হাজার হাজার পৃষ্ঠা টেনে আনে। এই নির্দেশিকাটি সম্পূর্ণ মানসিক মডেলের মধ্য দিয়ে চলে: ইভেন্ট লুপ, কোরোটিন, কাজ, স্ট্রাকচার্ড কনকারেন্সিTaskGroup, এবং ভুলের মুষ্টিমেয় যে চুপচাপ ট্যাংক উত্পাদন কর্মক্ষমতা.
📋 Table of Contents
- সূচিপত্র
- অ্যাসিনসিও আসলে কি সমাধান করে
- ইভেন্ট লুপ, ব্যাখ্যা করা হয়েছে
- Coroutines বনাম টাস্ক
- gather() বনাম টাস্কগ্রুপ
- একযোগে কাজ জুড়ে ভাগ করা পরিবর্তনযোগ্য অবস্থার এখনও সুরক্ষা প্রয়োজন, এমনকি একটি একক থ্রেডেও, কারণ একটি
- এটি "মাই অ্যাসিনসিও অ্যাপ স্লো" বাগ রিপোর্টের একক বৃহত্তম উত্স। ইভেন্ট লুপ একক-থ্রেডেড। যেকোনো সিঙ্ক্রোনাস কল যা ব্লক করে —
- প্রতিটি বাহ্যিক কলে উৎপাদন কোডের সময়সীমা প্রয়োজন। Python 3.11 যোগ করা হয়েছে
- ব্যবহার করে কাঠামোগত ত্রুটি পরিচালনা করা .
- ফাংশন ছাড়া
- অনেক সমসাময়িক সংযোগ (নেটওয়ার্ক কল, ডাটাবেস প্রশ্ন, ফাইল I/O) সহ I/O-বাউন্ড কাজের জন্য asyncio ব্যবহার করুন। অ্যাসিঙ্ক সমর্থন করে না এমন তৃতীয় পক্ষের লাইব্রেরিগুলিকে ব্লক করার জন্য থ্রেডিং ব্যবহার করুন৷ সিপিইউ-বাউন্ড কাজের জন্য মাল্টিপ্রসেসিং ব্যবহার করুন যেহেতু asyncio GIL-কে বাইপাস করে না।
- বিল্ডিং রাখুন
- Keep Building
অ্যাসিনসিও আসলে কি সমাধান করে
asyncio একটি কাজের জন্য বিদ্যমান: থ্রেড বা প্রক্রিয়ার ওভারহেড ছাড়াই একটি একক থ্রেডে একসাথে অনেকগুলি I/O-বাউন্ড অপারেশন চালানো। যখন আপনার প্রোগ্রামটি তার বেশিরভাগ সময় অপেক্ষা করে – একটি ডাটাবেস প্রতিক্রিয়ার জন্য, একটি HTTP উত্তরের জন্য, একটি ফাইল রিড করার জন্য – asyncio এটিকে নিষ্ক্রিয় বসে থাকার পরিবর্তে সেই অপেক্ষার সময় অন্য কাজে স্যুইচ করতে দেয়।
এটি CPU- আবদ্ধ সমান্তরাল থেকে মৌলিকভাবে ভিন্ন। asyncio আপনাকে বেশি CPU কোর দেয় না; এটি আপনাকে I/O-তে অপেক্ষা করার সময় একটি একক কোরের আরও ভাল ব্যবহার দেয়। CPU- ভারী কাজের জন্য (চিত্র প্রক্রিয়াকরণ, নম্বর ক্রাঞ্চিং), আপনি এখনও চানmultiprocessingবা একটি নেটিভ এক্সটেনশন।
ইভেন্ট লুপ, ব্যাখ্যা করা হয়েছে
প্রতিটি অ্যাসিঙ্কিও প্রোগ্রামের কেন্দ্রে থাকে ইভেন্ট লুপ — একটি একক-থ্রেডেড শিডিয়ুলার যা কোরোটিন চালায়, যখন কেউ কিছুর জন্য অপেক্ষা করে তখন নিয়ন্ত্রণ বন্ধ করে দেয় এবং প্রতীক্ষিত ফলাফল প্রস্তুত হলে তা পুনরায় শুরু করে।
import asyncio
async def say_hello():
print("start")
await asyncio.sleep(1)
print("end")
asyncio.run(say_hello())
asyncio.run()একটি তাজা ইভেন্ট লুপ তৈরি করে, করুটিনকে সম্পূর্ণ করার জন্য চালায়, তারপর লুপটি বন্ধ করে। যেকোন অ্যাসিনসিও স্ক্রিপ্টের জন্য এটি সঠিক শীর্ষ-স্তরের এন্ট্রি পয়েন্ট – পুরানোগুলি এড়িয়ে চলুনget_event_loop().run_until_complete()প্যাটার্ন যদি না আপনার কাছে ম্যানুয়ালি লুপ পরিচালনা করার একটি নির্দিষ্ট কারণ থাকে।
Coroutines বনাম টাস্ক
একটি কোরোটিন অবজেক্ট (একটিasync defফাংশন কল করে তৈরি) নিজে থেকে কিছুই করে না – এটি একটি বিরতি জেনারেটরের মতো বস্তু চালিত হওয়ার জন্য অপেক্ষা করে৷ অপেক্ষা করছে এটি ইনলাইন, ক্রমানুসারে চালায়। কটাস্কএকটি করুটিন মোড়ানো এবং অবিলম্বে ইভেন্ট লুপে একই সাথে চালানোর জন্য সময়সূচী করে।
import asyncio
import time
async def fetch(n):
await asyncio.sleep(1)
return n * 2
async def sequential():
start = time.perf_counter()
results = [await fetch(i) for i in range(5)]
print("sequential:", time.perf_counter() - start)
return results
async def concurrent():
start = time.perf_counter()
tasks = [asyncio.create_task(fetch(i)) for i in range(5)]
results = await asyncio.gather(*tasks)
print("concurrent:", time.perf_counter() - start)
return results
asyncio.run(sequential()) # ~5 seconds
asyncio.run(concurrent()) # ~1 second
ক্রমিক সংস্করণটি একবারে প্রতিটি কলের জন্য অপেক্ষা করে, তাই পাঁচটি এক-সেকেন্ডের ঘুম পাঁচ সেকেন্ড পর্যন্ত যোগ করে। সমসাময়িক সংস্করণটি সমস্ত পাঁচটি কাজকে সামনের দিকে নির্ধারণ করে, তাই তারা সবাই সমান্তরালভাবে ঘুমায় এবং পুরো জিনিসটি প্রায় এক সেকেন্ডে শেষ হয়।
gather() বনাম টাস্কগ্রুপ
asyncio.gather()পাইথন 3.4 থেকে একসাথে একাধিক কোরোটিন চালানোর আদর্শ উপায় হয়েছে, কিন্তু এটির একটি তীক্ষ্ণ প্রান্ত রয়েছে: যদি একটি টাস্ক বাড়ে, অন্যগুলি পটভূমিতে চলতে থাকে যতক্ষণ না আপনি পাস করেনreturn_exceptions=Trueএবং ম্যানুয়ালি ত্রুটিগুলি পরিচালনা করুন। এটি অনাথ কাজগুলির একটি সাধারণ উত্স এবং উত্পাদন লগগুলিতে অনির্বাচিত ব্যতিক্রম সতর্কতা।
Python 3.11 চালু করা হয়েছেasyncio.TaskGroup, একটি স্ট্রাকচার্ড কনকারেন্সি প্রাইমিটিভ যা এটিকে সঠিকভাবে ঠিক করে: যদি কোনো শিশুর কাজ ব্যর্থ হয়, তাহলে গ্রুপটি ভাইবোনের বাকি সব কাজ বাতিল করে এবং একটিExceptionGroupপ্রতিটি ব্যর্থতা ধারণ করে।
import asyncio
async def risky(n):
if n == 2:
raise ValueError("boom at " + str(n))
await asyncio.sleep(1)
return n
async def main():
try:
async with asyncio.TaskGroup() as tg:
results = [tg.create_task(risky(i)) for i in range(4)]
except* ValueError as eg:
for exc in eg.exceptions:
print("caught:", exc)
asyncio.run(main())
|||| সিনট্যাক্স হ্যান্ডেলexcept*দৃষ্টান্ত, আপনাকে শুধুমাত্র প্রথমটির পরিবর্তে গোষ্ঠী জুড়ে ঘটে যাওয়া প্রতিটি ব্যর্থতা প্রক্রিয়া করতে দেয়। আপনি যদি পাইথন 3.11 বা তার পরে টার্গেট করেন তবে পছন্দ করুনExceptionGroupবেশি কাঁচাTaskGroupতুচ্ছ আগুন-এবং-ভুলে যাওয়া সমঝোতার বাইরে কিছুর জন্য।gather()Async কনটেক্সট ম্যানেজার এবং লক
একযোগে কাজ জুড়ে ভাগ করা পরিবর্তনযোগ্য অবস্থার এখনও সুরক্ষা প্রয়োজন, এমনকি একটি একক থ্রেডেও, কারণ একটি
পয়েন্ট অন্য টাস্ক মধ্য অপারেশন নিয়ন্ত্রণ হস্তান্তর করতে পারেন.awaitসমালোচনামূলক বিভাগগুলিকে একইভাবে রক্ষা করেasyncio.Lockথ্রেড জন্য করে.threading.Locklock_example.py
import asyncio
counter = 0
lock = asyncio.Lock()
async def increment():
global counter
async with lock:
current = counter
await asyncio.sleep(0) # simulate a yield point
counter = current + 1
async def main():
await asyncio.gather(*(increment() for _ in range(100)))
print(counter) # always 100, never less
asyncio.run(main())
ফলন পয়েন্ট অন্য একটি কাজ পড়া এবং লেখার মধ্যে ইন্টারলিভ করতে দেয়await asyncio.sleep(0), হারানো আপডেটের কারণ — ক্লাসিক রেস কন্ডিশন, অনেকের পরিবর্তে শুধুমাত্র একটি থ্রেডে।counterব্লকিং কল ট্র্যাপ
এটি “মাই অ্যাসিনসিও অ্যাপ স্লো” বাগ রিপোর্টের একক বৃহত্তম উত্স। ইভেন্ট লুপ একক-থ্রেডেড। যেকোনো সিঙ্ক্রোনাস কল যা ব্লক করে —
, একটি ব্লকিংtime.sleep(), একটি সিপিইউ-ভারী লুপ, একটি ধীরগতির ডিস্কে পড়া একটি আনবাফার করা ফাইল — এটির উপর অপেক্ষা করা অন্য প্রতিটি কাজ সহ সমগ্র লুপকে হিমায়িত করে।requests.get()bad_vs_good.py
# BAD: blocks the whole event loop for 2 seconds
import time
async def bad():
time.sleep(2)
# GOOD: yields control back to the loop
import asyncio
async def good():
await asyncio.sleep(2)
# GOOD: offload a real blocking call to a thread
async def good_blocking_lib():
result = await asyncio.to_thread(some_blocking_function, arg1, arg2)
return result
(3.9+) তৃতীয় পক্ষের লাইব্রেরিগুলি থেকে I/O ব্লক করার জন্য যেগুলির একটি async সমতুল্য নেই৷ CPU- আবদ্ধ কাজের জন্য,asyncio.to_thread()ব্যবহার করুন সঙ্গে একটিloop.run_in_executor()পরিবর্তে — জিআইএল-এর কারণে থ্রেডগুলি CPU- আবদ্ধ কাজে সাহায্য করবে না।ProcessPoolExecutorটাইমআউট এবং বাতিলকরণ
প্রতিটি বাহ্যিক কলে উৎপাদন কোডের সময়সীমা প্রয়োজন। Python 3.11 যোগ করা হয়েছে
Production code needs timeouts on every external call. Python 3.11 addedasyncio.timeout()বয়স্কদের জন্য একটি পরিষ্কার প্রসঙ্গ-ব্যবস্থাপক প্রতিস্থাপন হিসাবে .asyncio.wait_for()timeout_example.py
import asyncio
async def slow_call():
await asyncio.sleep(10)
async def main():
try:
async with asyncio.timeout(2):
await slow_call()
except TimeoutError:
print("operation timed out after 2s")
asyncio.run(main())
উত্থাপন করে ভিতরের কাজটি বাতিল করে এর ভিতরে যদি আপনার কোরোটিন এমন সংস্থানগুলিকে র্যাপ করে যেগুলির পরিচ্ছন্নতার প্রয়োজন (খোলা সংযোগ, ফাইল হ্যান্ডেল), ব্যবহার করুন ||||৷ অথবা একটি async কনটেক্সট ম্যানেজার যাতে বাতিল করা রিসোর্স ফাঁস না করে।asyncio.CancelledErrorবাস্তব উদাহরণ: সমবর্তী API ফেচারtry/finallyএখানে একটি সম্পূর্ণ, উৎপাদন-আকৃতির উদাহরণ: সংযোগের সীমা সহ একাধিক ইউআরএল একসাথে আনা, প্রতি-অনুরোধের সময়সীমা, এবং
ব্যবহার করে কাঠামোগত ত্রুটি পরিচালনা করা .
fetcher.pyaiohttp📋 কপি
import asyncio
import aiohttp
async def fetch_one(session, url, semaphore):
async with semaphore:
try:
async with asyncio.timeout(5):
async with session.get(url) as resp:
return url, resp.status, await resp.text()
except (TimeoutError, aiohttp.ClientError) as e:
return url, None, str(e)
async def fetch_all(urls, max_concurrent=10):
semaphore = asyncio.Semaphore(max_concurrent)
async with aiohttp.ClientSession() as session:
async with asyncio.TaskGroup() as tg:
tasks = [tg.create_task(fetch_one(session, u, semaphore)) for u in urls]
return [t.result() for t in tasks]
urls = ["https://example.com"] * 50
results = asyncio.run(fetch_all(urls))
print(len(results), "requests completed")
একটি করুটিনের জন্য অপেক্ষা করতে ভুলে যাওয়া।Semaphoreএকটি
ফাংশন ছাড়া
- শুধু একটি করোটিন অবজেক্ট তৈরি করে এবং কিছুই করে না — পাইথন সতর্ক করবে “করোটিন কখনই প্রতীক্ষিত ছিল না” কিন্তু শোরগোল লগে এটি মিস করা সহজ।রেফারেন্স না রেখে কাজ তৈরি করা।
async defশুধুমাত্র অভ্যন্তরীণভাবে একটি দুর্বল রেফারেন্স ধারণ করে; যদি টাস্ক অবজেক্টটি শেষ হওয়ার আগে আবর্জনা সংগ্রহ করে তবে এটি নীরবে বাতিল করা যেতে পারে। একটি তালিকায় কাজগুলি সংরক্ষণ করুন বা সেগুলি সম্পূর্ণ না হওয়া পর্যন্ত সেট করুন৷awaitসিঙ্ক এবং অ্যাসিঙ্ক ডাটাবেস ড্রাইভার মিশ্রিত করা। - অ্যাসিঙ্ক কোডের ভিতরে একটি ব্লকিং ড্রাইভার (যেমন প্লেইন ||||) ব্যবহার করা উদ্দেশ্যকে ব্যর্থ করে — একটি অ্যাসিঙ্ক ড্রাইভার ব্যবহার করুন (
asyncio.create_task(), - ) বাদিয়ে কলটি মোড়ানো .
psycopg2টাইমআউট সেট করা হচ্ছে না।asyncpgএকটি টাইমআউট ছাড়া একটি একক হ্যাং নেটওয়ার্ক কল একটি সম্পূর্ণ অনুরোধ হ্যান্ডলারকে অনির্দিষ্টকালের জন্য লোডের মধ্যে আটকাতে পারে।aiomysqlসিপিইউ-বাউন্ড কাজের জন্য অ্যাসিনসিওর অত্যধিক ব্যবহার।to_thread()যদি আপনার বাধা গণনা হয়, অপেক্ষা না করে, অ্যাসিঙ্কিও গতি যোগ না করে জটিলতা যোগ করে। - প্রায়শই জিজ্ঞাসিত প্রশ্নঅ্যাসিনসিও কি 2026 সালে এখনও প্রাসঙ্গিক?
- হ্যাঁ। অ্যাসিঙ্কিও সমসাময়িক I/O-বাউন্ড পাইথন কোড লেখার আদর্শ উপায় হিসেবে রয়ে গেছে এবং এটি FastAPI, aiohttp, এবং Starlette-এর মতো প্রধান ফ্রেমওয়ার্ককে আন্ডারপিন করে। পাইথন 3.11+-এ টাস্কগ্রুপ এবং ব্যতিক্রম গোষ্ঠীর মতো নতুন বৈশিষ্ট্যগুলি এটিকে আরও বেশি প্রাসঙ্গিক করে তুলেছে, কম প্রাসঙ্গিক নয়।আমি কি অ্যাসিনসিও বা থ্রেডিং ব্যবহার করব?
অনেক সমসাময়িক সংযোগ (নেটওয়ার্ক কল, ডাটাবেস প্রশ্ন, ফাইল I/O) সহ I/O-বাউন্ড কাজের জন্য asyncio ব্যবহার করুন। অ্যাসিঙ্ক সমর্থন করে না এমন তৃতীয় পক্ষের লাইব্রেরিগুলিকে ব্লক করার জন্য থ্রেডিং ব্যবহার করুন৷ সিপিইউ-বাউন্ড কাজের জন্য মাল্টিপ্রসেসিং ব্যবহার করুন যেহেতু asyncio GIL-কে বাইপাস করে না।
asyncio.gather এবং TaskGroup এর মধ্যে পার্থক্য কি?
asyncio.gather() একাধিক coroutines থেকে ফলাফল সংগ্রহ করে কিন্তু ত্রুটির ক্ষেত্রে অসামঞ্জস্যপূর্ণ বাতিল আচরণ রয়েছে। টাস্কগ্রুপ (পাইথন 3.11+) হল একটি স্ট্রাকচার্ড কনকারেন্সি প্রিমিটিভ যা ভাইবোনের কাজগুলিকে স্বয়ংক্রিয়ভাবে বাতিল করে যখন কেউ ব্যর্থ হয় এবং একটি ব্যতিক্রম গোষ্ঠী উত্থাপন করে, ত্রুটি পরিচালনাকে আরও বেশি অনুমানযোগ্য করে তোলে।
কেন আমার asyncio প্রোগ্রাম হিমায়িত হয়?
সবচেয়ে সাধারণ কারণ হল একটি ব্লকিং, সিঙ্ক্রোনাস ফাংশন (যেমন time.sleep, একটি ব্লকিং requests.get, বা ভারী CPU কাজ) একটি করটিনের ভিতরে কল করা। এটি একক ইভেন্ট লুপ থ্রেডকে ব্লক করে এবং অন্য প্রতিটি কাজকে স্টল করে। কল ব্লক করার জন্য asyncio.sleep, async HTTP ক্লায়েন্ট বা run_in_executor ব্যবহার করুন।
আমি কি সিঙ্ক্রোনাস কোডের সাথে অ্যাসিনসিও মিশ্রিত করতে পারি?
হ্যাঁ, asyncio.to_thread() (Python 3.9+) বা loop.run_in_executor() এর মাধ্যমে ইভেন্ট লুপ ব্লক না করে একটি থ্রেড পুলে ব্লকিং কল অফলোড করতে। এছাড়াও আপনি asyncio.run() এ কল করতে পারেন সিঙ্ক্রোনাস এন্ট্রি পয়েন্ট থেকে অ্যাসিঙ্ক কোডে ব্রিজ করতে।
আমি একটি ছোট স্ক্রিপ্ট জন্য asyncio প্রয়োজন?
সাধারণত না। আপনি যদি এক বা দুটি অনুক্রমিক API কল করেন, সিঙ্ক্রোনাস কোড সহজ এবং ডিবাগ করা সহজ। যখন আপনার অনেকগুলো সমসাময়িক I/O অপারেশন থাকে যেখানে ওভারল্যাপিং অপেক্ষার সময় আসলে গুরুত্বপূর্ণ।
TechPulse এ সম্পর্কিত পড়া
কিভাবে FastAPI দিয়ে একটি REST API তৈরি করবেন
ওয়েবসকেট বনাম সার্ভার-প্রেরিত ইভেন্ট
2026 সালে পাইথন সেরা অনুশীলন
Keep Building
asyncio rewards a clear mental model more than memorized syntax: understand the event loop, know when something blocks, and lean on structured concurrency primitives like TaskGroup for anything beyond a quick script. Bookmark this guide and come back to the fetcher example next time you need a concurrent client built right the first time.
🔗 Share this article
✍️ Leave a Comment