অ্যাসিনক্রোনাস ইনপুট/আউটপুট

অ্যাসিনক্রোনাস ইনপুট/আউটপুট

এই প্রবন্ধে অ্যাসিনক্রোনাস ইনপুট/আউটপুট ব্যাখ্যা করা হয়েছে।

এই গাইডে ধাপে ধাপে পাইথনে ব্যবহারিকভাবে কার্যকর অ্যাসিনক্রোনাস ইনপুট/আউটপুট-এর ধারণা ও প্যাটার্নগুলি সংক্ষেপে ব্যাখ্যা করা হয়েছে।

YouTube Video

অ্যাসিঙ্ক্রোনাস ইনপুট/আউটপুট (I/O)

অ্যাসিঙ্ক্রোনাস I/O-র ধারণা

অ্যাসিঙ্ক্রোনাস I/O এমন একটি পদ্ধতি, যেখানে ফাইল অপারেশন বা নেটওয়ার্ক যোগাযোগের মতো সময়সাপেক্ষ I/O-র জন্য অপেক্ষা করার সময় অন্যান্য অপারেশনগুলো সমান্তরালভাবে চালানো যায়। পাইথনে, asyncio একটি স্ট্যান্ডার্ড অ্যাসিঙ্ক্রোনাস ফ্রেমওয়ার্ক হিসেবে দেওয়া হয়েছে এবং অনেকগুলো লাইব্রেরি এই পদ্ধতি অনুসরণ করার জন্য তৈরি।

মৌলিক বিষয়: async / await এবং ইভেন্ট লুপ

প্রথমে, কীভাবে মৌলিক coroutine লিখতে হয় এবং asyncio.gather ব্যবহার করে একাধিক coroutine একসাথে চালানো যায়, তার একটি উদাহরণ এখানে দেয়া হলো।

নিচের কোডটি অ্যাসিঙ্ক্রোনাস ফাংশন একযোগে সংজ্ঞায়িত ও চালানোর একটি সহজতম উদাহরণ। sleep ফাংশন সমান্তরাল এক্সিকিউশন দেখানোর জন্য ব্যবহার করা হয়েছে।

 1import asyncio
 2
 3async def worker(name: str, delay: float):
 4    # Simulate I/O-bound work by sleeping
 5    print(f"{name} started")
 6    await asyncio.sleep(delay)
 7    print(f"{name} finished after {delay}s")
 8    return name, delay
 9
10async def main():
11    # Run multiple coroutines concurrently
12    tasks = [
13        worker("A", 1.5),
14        worker("B", 1.0),
15        worker("C", 0.5),
16    ]
17    results = await asyncio.gather(*tasks)
18    print("Results:", results)
19
20if __name__ == "__main__":
21    asyncio.run(main())
  • এই কোডটি asyncio.run() দিয়ে ইভেন্ট লুপ শুরু করে এবং তিনটি coroutine একসঙ্গে চালায়।

async with এবং অ্যাসিঙ্ক্রোনাস কনটেক্সট ম্যানেজার

অ্যাসিঙ্ক্রোনাস প্রসেসিং-এ সংযোগ খোলা ও ফাইল বন্ধ করার মতো রিসোর্স ব্যবস্থাপনা সহজেই জটিল হয়ে যেতে পারে। এখানেই async with-এর মাধ্যমে অ্যাসিঙ্ক্রোনাস কনটেক্সট ম্যানেজার ব্যবহার কার্যকরী হয়ে ওঠে। এই সিনট্যাক্সটি সিঙ্ক্রোনাস with স্টেটমেন্টের মতোই ব্যবহার করা হয়, তবে এর অভ্যন্তরীণ প্রসেসিং অ্যাসিঙ্ক্রোনাস হওয়ায় এটি async/await প্রবাহে সহজেই মানিয়ে যায়।

async with ব্যবহারের দুটি প্রধান কারণ আছে:।

  • সংযোগ, ফাইল হ্যান্ডেল বা সেশনের মতো রিসোর্স যথাযথভাবে পরিষ্কার করার জন্য। অপ্রত্যাশিতভাবে বন্ধ হলেও, রিসোর্সগুলো সঠিকভাবে মুক্ত হয়ে যাবে—এটি নিশ্চিত করতে পারবেন।
  • সংযোগ স্থাপন বা বন্ধকরণ ও ফ্লাশ করার মতো ইনিশিয়ালাইজেশন ও ক্লিনআপ টাস্কগুলো অ্যাসিঙ্ক্রোনাসভাবে স্বয়ংক্রিয় করার জন্য। এতে হাতে কোড লেখার ঝামেলা কমে এবং কোডের স্বচ্ছতা বাড়ে।

নিচে স্ক্র্যাচ থেকে একটি সহজ অ্যাসিঙ্ক্রোনাস কনটেক্সট ম্যানেজার তৈরির উদাহরণ দেওয়া হলো।

 1import asyncio
 2
 3class AsyncResource:
 4    async def __aenter__(self):
 5        print("Opening resource...")
 6        await asyncio.sleep(0.5)
 7        print("Resource opened")
 8        return self
 9
10    async def __aexit__(self, exc_type, exc, tb):
11        print("Closing resource...")
12        await asyncio.sleep(0.5)
13        print("Resource closed")
14
15async def main():
16    async with AsyncResource() as r:
17        print("Using resource...")
18
19if __name__ == "__main__":
20    asyncio.run(main())
  • __aenter____aexit__ সংজ্ঞায়িত করে আপনি async with ব্যবহার করতে পারবেন।
  • async with ব্লকে প্রবেশ ও বাহির হওয়ার সময় যে প্রসেসিং হয় তা অ্যাসিঙ্ক্রোনাস এবং নিরাপদভাবে সম্পন্ন হয়।

অ্যাসিঙ্ক্রোনাস ফাইল I/O (aiofiles)

ফাইল অপারেশন ব্লকিং-এর একটি ক্লাসিক উদাহরণ। aiofiles ব্যবহারে আপনি ফাইল অপারেশন নিরাপদভাবে অ্যাসিঙ্ক্রোনাসভাবে সামলাতে পারবেন। এটি ভিতরে থ্রেড পুল ব্যবহার করে এবং async with-এর মাধ্যমে ফাইলগুলি সঠিকভাবে বন্ধ কিনা তা নিশ্চিত করে।

নিচের উদাহরণটি একাধিক ফাইল সমান্তরালভাবে অ্যাসিঙ্ক্রোনাস রিডিং দেখায়। এই কোড চালানোর আগে আপনাকে pip install aiofiles দিয়ে aiofiles ইনস্টল করতে হবে।

 1# pip install aiofiles
 2import asyncio
 3import aiofiles
 4from pathlib import Path
 5
 6async def read_file(path: Path):
 7    # Read file content asynchronously
 8    async with aiofiles.open(path, mode='r', encoding='utf-8') as f:
 9        contents = await f.read()
10    return path.name, len(contents)
11
12async def main():
13    files = [
14        Path("example1.txt"),
15        Path("example2.txt"),
16        Path("example3.txt")
17    ]
18    tasks = [read_file(p) for p in files]
19    results = await asyncio.gather(*tasks)
20    for name, size in results:
21        print(f"{name}: {size} bytes")
22
23if __name__ == "__main__":
24    asyncio.run(main())
  • এটি প্রতিটি ফাইলের রিডিং সমান্তরাল করে। aiofiles প্রায়ই ভিতরে থ্রেড পুল ব্যবহার করে, ফলে আপনি ব্লকিং ফাইল I/O-কে অ্যাসিঙ্ক্রোনাস ইন্টারফেসের মাধ্যমে সামলাতে পারেন।

অ্যাসিঙ্ক্রোনাস HTTP ক্লায়েন্ট (aiohttp)

নেটওয়ার্ক I/O-র একটি ক্লাসিক উদাহরণ হিসেবে এখানে অ্যাসিঙ্ক্রোনাসভাবে HTTP রিকোয়েস্ট সম্পাদনের পদ্ধতি দেখানো হয়েছে। সমান্তরালে প্রচুর HTTP রিকোয়েস্ট পাঠানোর দরকার হলে এটি বিশেষভাবে কার্যকর।

নিচে aiohttp ব্যবহার করে একাধিক URL সমান্তরালভাবে আনার একটি উদাহরণ দেওয়া হলো। aiohttp চালাতে হলে আপনাকে pip install aiohttp দিয়ে এটি ইনস্টল করতে হবে।

 1# pip install aiohttp
 2import asyncio
 3import aiohttp
 4
 5async def fetch(session: aiohttp.ClientSession, url: str):
 6    # Fetch a URL asynchronously and return status and size
 7    async with session.get(url) as resp:
 8        text = await resp.text()
 9        return url, resp.status, len(text)
10
11async def main(urls):
12    async with aiohttp.ClientSession() as session:
13        tasks = [fetch(session, u) for u in urls]
14        for coro in asyncio.as_completed(tasks):
15            url, status, size = await coro
16            print(f"{url} -> {status}, {size} bytes")
17
18if __name__ == "__main__":
19    urls = [
20        "https://codesparklab.com/json/example1.json",
21        "https://codesparklab.com/json/example2.json",
22        "https://codesparklab.com/json/example3.json",
23    ]
24    asyncio.run(main(urls))
  • asyncio.as_completed ব্যবহার করে, টাস্ক শেষ হওয়ার ক্রমানুসারে রেজাল্ট প্রসেস করতে পারবেন। এটি প্রচুর অনুরোধ দক্ষতার সাথে সামলানোর জন্য উপযোগী।

ব্লকিং I/O এর সাথে সহাবস্থান: run_in_executor

অ্যাসিনক্রোনাস কোডে সিপিইউ-নির্ভর কাজ বা বিদ্যমান ব্লকিং API নিয়ে কাজ করার সময়, loop.run_in_executor দিয়ে ThreadPoolExecutor অথবা ProcessPoolExecutor ব্যবহার করুন।

নিম্নের কোডটি থ্রেড পুল ব্যবহার করে ব্লকিং ইনপুট/আউটপুট ধারণা করা টাস্কগুলোকে সমান্তরালভাবে চালানোর একটি উদাহরণ।

 1import asyncio
 2from concurrent.futures import ThreadPoolExecutor
 3import time
 4
 5def blocking_io(n):
 6    # Simulate a blocking I/O or CPU-bound function
 7    time.sleep(n)
 8    return f"slept {n}s"
 9
10async def main():
11    loop = asyncio.get_running_loop()
12    with ThreadPoolExecutor() as pool:
13        tasks = [
14            loop.run_in_executor(pool, blocking_io, 1),
15            loop.run_in_executor(pool, blocking_io, 2),
16        ]
17        results = await asyncio.gather(*tasks)
18        print("Blocking results:", results)
19
20if __name__ == "__main__":
21    asyncio.run(main())
  • run_in_executor ব্যবহার করে, আপনি বিদ্যমান সিনক্রোনাস কোডকে বেশি পরিবর্তন ছাড়াই অ্যাসিনক্রোনাস প্রবাহের মধ্যে অন্তর্ভুক্ত করতে পারেন। তবে, থ্রেড সংখ্যা ও CPU-র ওপর লোড নিয়ে সতর্ক থাকবেন।
  • ProcessPoolExecutor সিপিইউ-নির্ভর কাজের জন্য উপযুক্ত।

অ্যাসিঙ্ক্রোনাস সার্ভার: asyncio ভিত্তিক TCP ইকো সার্ভার

আপনি যদি সরাসরি সোকেট ব্যবহারে আগ্রহী হন, তবে asyncio.start_server ব্যবহার করে সহজেই অ্যাসিঙ্ক্রোনাস সার্ভার তৈরি করতে পারেন।

নিচের উদাহরণটি একটি সহজ ইকো সার্ভার, যা ক্লায়েন্ট থেকে যেভাবে ডেটা পায়, ঠিক সেভাবেই ফেরত পাঠায়।

 1import asyncio
 2
 3async def handle_echo(reader: asyncio.StreamReader, writer: asyncio.StreamWriter):
 4    # Handle a single client: read data and echo it back
 5    addr = writer.get_extra_info('peername')
 6    print(f"Connection from {addr}")
 7    while True:
 8        data = await reader.read(1024)
 9        if not data:
10            break
11        writer.write(data)  # echo back
12        await writer.drain()
13    writer.close()
14    await writer.wait_closed()
15    print(f"Connection closed {addr}")
16
17async def main():
18    server = await asyncio.start_server(handle_echo, '127.0.0.1', 8888)
19    addr = server.sockets[0].getsockname()
20    print(f"Serving on {addr}")
21    async with server:
22        await server.serve_forever()
23
24if __name__ == "__main__":
25    asyncio.run(main())
  • asyncio-এর সাহায্যে TCP যোগাযোগে, StreamReader এবং StreamWriter অ্যাসিঙ্ক্রোনাস ইনপুট ও আউটপুটে কেন্দ্রীয় ভূমিকা পালন করে। StreamReader ক্লায়েন্ট থেকে পাঠানো ডেটা অ্যাসিঙ্ক্রোনাসভাবে পড়ে, এবং StreamWriter সার্ভার থেকে ক্লায়েন্টে রেসপন্স পাঠাতে ব্যবহৃত হয়।

  • আপনি নিজে সকেটের বিস্তারিত অপারেশন পরিচালনা না করেও, সহজে এবং দক্ষতার সাথে অ্যাসিঙ্ক্রোনাস সার্ভার চালু করতে পারেন asyncio.start_server ব্যবহার করে।

  • যখন আপনি asyncio.start_server-এ একটি হ্যান্ডলার ফাংশন প্রদান করেন, তখন ঐ ফাংশনটি reader এবং writer আর্গুমেন্ট হিসেবে গ্রহণ করে। এসব ব্যবহারের মাধ্যমে, আপনি সরাসরি লো-লেভেল সকেট API পরিচালনার চেয়ে আরও নিরাপদ ও স্পষ্টভাবে যোগাযোগ প্রক্রিয়া বাস্তবায়ন করতে পারেন। উদাহরণস্বরূপ, reader.read() দিয়ে ডেটা গ্রহণ এবং writer.write()writer.drain() একত্রে ব্যবহার করে আপনি ডেটা সম্পূর্ণরূপে পাঠানো হয়েছে তা নিশ্চিত করে অ্যাসিঙ্ক্রোনাস প্রেরণ বাস্তবায়ন করতে পারেন।

  • এই সেটআপ অনেকগুলো সমান্তরাল সংযোগ পরিচালনার জন্য উপযোগী এবং সহজ প্রটোকল বা ছোট TCP সার্ভিসের জন্য আদর্শ।

বৃহৎ স্ট্রিমিং ডেটা ব্যবস্থাপনা

বড় ফাইল বা রেসপন্স ক্রমান্বয়ে প্রসেস করার সময়, মেমোরি ব্যবহার কম রাখতে ডেটা চাঙ্ক আকারে পড়া ও লেখা উচিত। নিচে aiohttp ব্যবহার করে স্ট্রিমিং রিডের একটি উদাহরণ দেওয়া হলো।

নিচের কোডটি HTTP রেসপন্সকে চাঙ্ক আকারে প্রসেস করে এবং ডেটা আসার সঙ্গে সঙ্গেই ডিস্কে লেখে।

 1import aiohttp
 2import asyncio
 3import aiofiles
 4
 5async def stream_download(url: str, dest: str):
 6    # Stream download and write to file in chunks
 7    async with aiohttp.ClientSession() as session:
 8        async with session.get(url) as resp:
 9            async with aiofiles.open(dest, 'wb') as f:
10                async for chunk in resp.content.iter_chunked(1024 * 64):
11                    await f.write(chunk)
12
13if __name__ == "__main__":
14    asyncio.run(stream_download("https://codesparklab.com/100MB.bin", "download.bin"))
  • এই কোডটি বড় কোন ফাইল একবারে লোড করে না; বরং, এটি ডেটাকে টুকরো টুকরো করে (ছোট ছোট ভাগে) গ্রহণ করে এবং অ্যাসিঙ্ক্রোনাসভাবে ফাইলে লিখে। ফলে, এটি দ্রুত ও দক্ষতার সাথে ডাউনলোড করতে পারে এবং মেমরি ব্যবহার কম রাখে। aiohttp অ্যাসিঙ্ক্রোনাসভাবে ডেটা সংগ্রহ করে এবং aiofiles ব্লক না করেই ফাইলে লেখে, যার ফলে অন্য প্রসেসের সাথে একত্রে সহজেই চালানো যায়।

  • এই পদ্ধতি বড় ফাইল দক্ষতার সাথে ডাউনলোড ও সংরক্ষণ এবং মেমোরি ব্যবহারের পরিমাণ কমানোর জন্য উপযোগী।

সাবপ্রসেসের অ্যাসিঙ্ক্রোনাস এক্সিকিউশন

আপনি যদি বাইরের কমান্ড অ্যাসিঙ্ক্রোনাসভাবে চালাতে ও তাদের আউটপুট রিয়েলটাইমে পড়তে চান, তবে asyncio.create_subprocess_exec কার্যকর।

নিচে বাইরের একটি কমান্ড চালানো ও তার স্ট্যান্ডার্ড আউটপুট রিয়েলটাইমে পড়ার উদাহরণ দেওয়া হলো।

 1import asyncio
 2
 3async def run_cmd(cmd):
 4    # Run external command asynchronously and capture output line by line
 5    proc = await asyncio.create_subprocess_exec(
 6        *cmd,
 7        stdout=asyncio.subprocess.PIPE,
 8        stderr=asyncio.subprocess.PIPE
 9    )
10
11    async def read_stream(stream, name):
12        while True:
13            line = await stream.readline()
14            if not line:
15                break
16            print(f"[{name}] {line.decode().rstrip()}")
17
18    await asyncio.gather(
19        read_stream(proc.stdout, "stdout"),
20        read_stream(proc.stderr, "stderr"),
21    )
22    await proc.wait()
23    return proc.returncode
24
25if __name__ == "__main__":
26    asyncio.run(run_cmd(["python", "--version"]))
  • সাবপ্রসেসগুলোকে অ্যাসিঙ্ক্রোনাসভাবে নিয়ন্ত্রণ করে, বাইরের টুলের লগ রিয়েলটাইমে হ্যান্ডেল বা সমান্তরালে একাধিক প্রসেস চালাতে পারবেন।

ক্যানসেল ও টাইমআউট হ্যান্ডলিং

অ্যাসিঙ্ক্রোনাস টাস্ক ক্যানসেল করা যায়। টাইমআউট লাগাতে হলে asyncio.wait_for সহজে ব্যবহার করা যায়।

নিচে টাস্ক টাইমআউটসহ চালানোর একটি উদাহরণ দেওয়া হলো।

 1import asyncio
 2
 3async def slow_task():
 4    await asyncio.sleep(5)
 5    return "done"
 6
 7async def main():
 8    try:
 9        result = await asyncio.wait_for(slow_task(), timeout=2.0)
10        print("Result:", result)
11    except asyncio.TimeoutError:
12        print("Task timed out")
13
14if __name__ == "__main__":
15    asyncio.run(main())
  • wait_for এ টাইমআউট হলে TimeoutError দেয় এবং প্রয়োজনে টাস্কটি ক্যানসেল করে। টাস্ক ক্যানসেলেশনের প্রভাব ও ক্লিনআপের ব্যাপারে সতর্ক থাকুন।

সমান্তরাল নিয়ন্ত্রণ (Semaphore)

অনেকগুলো সংযোগ বা অনুরোধ একসাথে করলে রিসোর্স ফুরিয়ে যেতে পারে, তাই asyncio.Semaphore দিয়ে সমান্তরালতা সীমিত করুন।

নিচে সেমাফোর দিয়ে একসঙ্গে ডাউনলোডের সংখ্যা সীমিত করার একটি উদাহরণ।

 1import asyncio
 2import aiohttp
 3
 4semaphore = asyncio.Semaphore(3)  # allow up to 3 concurrent tasks
 5
 6async def limited_fetch(session, url):
 7    async with semaphore:
 8        async with session.get(url) as resp:
 9            return url, resp.status
10
11async def main(urls):
12    async with aiohttp.ClientSession() as session:
13        tasks = [limited_fetch(session, u) for u in urls]
14        results = await asyncio.gather(*tasks)
15        print(results)
16
17if __name__ == "__main__":
18    urls = ["https://codesparklab.com/json/example.json"] * 10
19    asyncio.run(main(urls))
  • এই পদ্ধতিতে বাইরের সার্ভিসে নমনীয়ভাবে প্রবেশ ও নিজের প্রসেসকে অতিরিক্ত লোড থেকে বাঁচাতে পারবেন।

এরর হ্যান্ডলিং ও পুনরায় চেষ্টার কৌশল

অ্যাসিঙ্ক্রোনাস প্রসেসিংয়েও অবশ্যম্ভাবীভাবে ত্রুটি ঘটে। এক্সসেপশন যথাযথভাবে ধরুন এবং পুনরায় চেষ্টার কৌশল (যেমন, এক্সপোনেনশিয়াল ব্যাকঅফ) প্রয়োগ করুন।

নিচে N বার পর্যন্ত সহজে পুনরায় চেষ্টা করার একটি বাস্তবায়ন উদাহরণ দেওয়া হলো।

 1import asyncio
 2import aiohttp
 3import random
 4
 5async def fetch_with_retry(session, url, retries=3):
 6    for attempt in range(1, retries + 1):
 7        try:
 8            async with session.get(url) as resp:
 9                resp.raise_for_status()
10                text = await resp.text()
11                return text
12        except Exception as e:
13            if attempt == retries:
14                raise
15            await asyncio.sleep(0.5 * attempt + random.random())
16
17async def main():
18    async with aiohttp.ClientSession() as session:
19        text = await fetch_with_retry(session, "https://codesparklab.com/")
20        print("Fetched length:", len(text))
21
22if __name__ == "__main__":
23    asyncio.run(main())
  • সঠিক পুনরায় চেষ্টার যুক্তি ব্যবহারে কনসিস্টেন্সি ও ট্রাফিক কন্ট্রোলের সমতা বজায় রাখা যায়।

ডিবাগ ও লগিংয়ের টিপস

অ্যাসিঙ্ক্রোনাস প্রসেসিং-এ টাস্কগুলো একসঙ্গে চলে, তাই সমস্যার কারণ চিহ্নিত করা কঠিন হতে পারে। সমস্যা দক্ষতার সাথে শনাক্ত করতে, নিচের বিষয়গুলো মনে রাখলে ডিবাগিং আরও সহজ হবে।

  • asyncio.run() এবং Task-এর এক্সসেপশন চোখ এড়িয়ে যেতে পারে, তাই অপ্রসেসকৃত এক্সসেপশনগুলো অবশ্যই লগ করুন।
  • logging ব্যবহারের সময়, করুটিনের নাম বা (Python 3.8 এবং উপরের ভার্সনে) task.get_name() লগে যুক্ত করলে ট্র্যাক করা আরও সহজ হয়।
  • asyncio.Task.all_tasks() ব্যবহার করে আপনি টাস্কের বর্তমান অবস্থা পরীক্ষা করতে পারেন। তবে, এই API ডিবাগিং-এর জন্য নির্ধারিত এবং প্রোডাকশন পরিবেশে পারফরমেন্স সংক্রান্ত সমস্যা বা অপ্রত্যাশিত হস্তক্ষেপ এড়াতে সতর্কতার সাথে ব্যবহার করা উচিত।

পারফরম্যান্স বিষয়ে চিন্তাভাবনা

অ্যাসিঙ্ক্রোনাস প্রোগ্রামিং I/O অপেক্ষা সামলাতে পারদর্শী, কিন্তু ভুল ব্যবহারে পারফরম্যান্স খারাপ হতে পারে। নিচের বিষয়গুলো মনে রেখে অপটিমাইজ করুন:।

  • অ্যাসিঙ্ক্রোনাস প্রসেসিং I/O-বাউন্ড টাস্কে ভালো, কিন্তু CPU-বাউন্ড টাস্কে উপযুক্ত নয়; তখন প্রসেস পুল ব্যবহার করুন।
  • থ্রেড বা প্রসেস পুল ব্যবহার করলে, পুলের আকার ও টাস্কের ধরন বিবেচনা করুন।
  • একসঙ্গে অনেক ছোট টাস্ক দিলে ইভেন্ট লুপের ওভারহেড বাড়ে—তাই ব্যাচিং বা সেমাফোর ব্যবহার করে সামঞ্জস্য আনুন।

সারসংক্ষেপ

পাইথনের অ্যাসিঙ্ক্রোনাস I/O একটি শক্তিশালী পদ্ধতি, যা I/O অপেক্ষার সময় কাজে লাগিয়ে নেটওয়ার্ক ও ফাইল অপারেশন দক্ষতার সাথে একযোগে সম্পন্ন করে। asyncio, aiohttp, aiofiles, এবং run_in_executor এর মতো টেকনিক একত্র করে আপনি সহজে ব্যবহারযোগ্য অ্যাসিঙ্ক্রোনাস অ্যাপ্লিকেশন তৈরি করতে পারবেন। async with-এর মাধ্যমে রিসোর্স সংগ্রহ ও মুক্তিকরণ স্বয়ংক্রিয় করে, আপনি ফাইল, HTTP সেশন, লক ইত্যাদি অ্যাসিঙ্ক্রোনাস রিসোর্স নিরাপদ ও নির্ভরযোগ্যভাবে ব্যবস্থাপনা করতে পারবেন। সঠিক এরর হ্যান্ডলিং ও সমান্তরাল ব্যবস্থাপনা অন্তর্ভুক্ত করে, আপনি উচ্চতর নির্ভরযোগ্য অ্যাসিঙ্ক্রোনাস প্রোগ্রাম নিরাপদে চালাতে পারবেন।

আপনি আমাদের ইউটিউব চ্যানেলে ভিজ্যুয়াল স্টুডিও কোড ব্যবহার করে উপরের নিবন্ধটি অনুসরণ করতে পারেন। দয়া করে ইউটিউব চ্যানেলটিও দেখুন।

YouTube Video