خانه زبان های برنامه نویسی Coroutine در پایتون | روش پیاده سازی، مدیریت و رفع مشکلات رایج زبان های برنامه نویسی پایتون نوشته شده توسط: تیم فنی نیک آموز تاریخ انتشار: ۰۲ مرداد ۱۴۰۳ آخرین بروزرسانی: 02 مرداد 1403 زمان مطالعه: 9 دقیقه ۵ (۱) Coroutine در پایتون یک قابلیت کارآمد است که برنامهنویسی غیرهمزمان را ممکن میکند. این تکنیک امکان اجرای چندین کار را در یک رشته واحد فراهم میکند. همچنین بخشی از قابلیتهای غیرهمزمانی ورودی / خروجی (Asynchronous I/O) گستردهتر است که توسط پایتون و با کمک کتابخانه asyncio ارائه میشود. این ویژگی همراهبا مزایا و قابلیتهای متعددی ارائه شده است که در این مقاله به آنها میپردازیم. عنوانهایی همچون تاریخچه و تکامل Coroutine، تفاوت آن با Threading، نحوه تعریف، استفاده از Coroutine و… مباحثی هستند که در ادامه خواهید خواند. معرفی Coroutine در پایتون Coroutine در پایتون تکنیکی برای نوشتن کدها بهصورت غیرهمزمان (Asynchronous) است. توسط این تابع میتوانید در یک لحظه واحد، چندین تابع و فرآیند را اجرا کنید. درنتیجه، مجبور به انتظار برای یک ورودی یا خروجی – مانند کارت شبکه یا اجرای تابع قبلی – نخواهید بود. در این تکنیک، برخی از توابع اجرای خود را به حالت تعلیق درمیآورند تا در زمان نیاز، دقیقاً از جایی که متوقف شدهاند، اجرا شوند. Coroutine به سایر کوروتینها اجازه اجرای همزمان را میدهد. تاریخچه و تکامل Coroutine در پایتون در سال ۱۹۵۸، یک دانشمند کامپیوتر به نام ملوین کانوی (Melvin Conway) اصطلاح Coroutine را ابداع کرد. او این ترکیبواژهای را هنگامی که درحال ساخت یک برنامه اسمبلی بود، بهکار برد. سپس در سال ۱۹۶۳، اولین توصیف منتشرشده درباره Coroutine در دسترس عموم قرار گرفت. Coroutineها بهعنوان یک ویژگی بومی در پایتون ۳.۵، با PEP 492 عرضه و به این زبان برنامهنویسی اضافه شدند. امروزه این قابلیت علاوهبر پشتیبانی توسط پایتون، در برخی از انواع زبان های برنامه نویسی سطح بالا هم پشتیبانی میشود. میتوانید نام برخی از این زبانها را در لیست زیر مشاهده کنید: ++C #C Dynamic C #F Go JavaScript Kotlin Perl 5 PHP Python Ruby درحالحاضر چهار نسخه از پایتون، Coroutine را پشتیبانی میکنند که در ادامه آنها را لیست کردهایم: ۲.۵ ۳.۳ ۳.۴ ۳.۵ تفاوت Coroutine و Threading ماژول Threading به شما امکان میدهد رشتههایی را در برنامههای پایتون ایجاد و مدیریت کنید. این ماژول تسکها یا درخواستها را بهصورت همزمان روی سرورها یا برنامههای شما اجرا میکند. Coroutine در پایتون روش جدیدتری نسبتبه Threading است؛ اما هرکدام مزایا و معایب خود را دارند که در ادامه آنها را نام خواهیم برد. مزایای Threading این ماژول برنامههای چندرشتهای را روی سیستمهای کامپیوتری مجهز به چندین CPU، با سرعت بالایی اجرا میکند. رشتههای یک فرآیند میتوانند حافظه متغیرهای سراسری (Global Variables) را بهاشتراک بگذارند؛ یعنی اگر مقدار متغیر در رشته تغییر کند، برای همه رشتهها قابل استفاده خواهد بود و دسترسی عمومی دارد. Threading گزینه بسیارخوبی برای اجرای همزمان چندین وظیفه محدود I/O است. معایب Threading پایتون براساس پیادهسازی CPython کار میکند و فقط یک رشته را در هرلحظه اجرا میکند؛ بنابراین، Threading ممکن است سرعت همه عملیات را افزایش ندهد. دلیل اصلی این موضوع، (GIL) است. Threading برای سرعتبخشیدن به کارهای فشرده CPU، گزینه مناسبی نیست. برنامههایی که از رشتههای مختلفی تشکیل شدهاند، باید بهسرعت بین رشتهها جابهجا شوند. بههمیندلیل، در چنین برنامههایی، باید از تکنیک زمانبندی (Scheduling) استفاده شود. گاهی بهاشتراکگذاری منابع در Threading مشکلساز میشود؛ چراکه همه رشتهها منابع و حافظه یکسانی از متغیرهای سراسری را بهاشتراک میگذارند. ازاینرو، عملیات انجامشده در یک رشته میتواند باعث خطای حافظه برای رشتههای دیگر شود. همچنین ممکن است رشتههای دیگر حافظه را وادار به انجام تسکهای خود نکنند. مزایای Coroutine در پایتون اجرای عملیات بهصورت غیرهمزمان امکان پیادهسازی تکنیکهای برنامهنویسی تابعی (Functional Programming) بهرهمندی ساده و سریع از مزایای زمانبندی پیشگیرانه (Pre-emptive Scheduling ) استفاده بهینه از سیستم و منابع آن نیاز به منابع کمتر نسبتبه رشتهها کاهش ضرورت برای قفلکردن منابع (Resource Locking) افزایش محل مرجع (Locality of Reference) افزایش پاسخگویی برنامهها به عملیات I/O سینتکسهای سادهتر در مقایسه با روش Callback یا رویکردهای مبتنیبر رشته مدیریت آسانتر تسکهای غیرهمزمان کاهش سربار روی حافظه و منابع پردازشی دستگاه معایب Coroutine در پایتون احتمال بروز خطا در کنترل جریانهای پیچیده عدم نمایش منطق برنامه ضرورت بر اجرای کنترل دستی بهمنظور کنترل منطق و جریان برنامه احتمال هدررفتن منابع برنامه بهدلیل عدم دقت در استفاده از برنامههای مشترک دشواری در آموختن برای مبتدیان بهدلیل منحنی یادگیری پرشیب آموزش پیاده سازی یک Coroutine ساده پیش از یادگیری پیادهسازی یک Coroutine ساده، ابتدا باید چند نکته بسیار مهم را مرور کنیم: یک Coroutine بااستفاده از “async def” تعریف میشود. در داخل کوروتین، میتوانید از “await” برای توقف اجرای کد تا زمانیکه کار موردنظر کامل شود، استفاده کنید. “await” برای بازگرداندن کنترل به حلقه رویداد استفاده میشود و به سایر تسکها اجازه اجرا میدهد. از این کلیدواژه فقط میتوانید روی یک شیء با قابلیت “awaitable” استفاده کنید؛ مانند کوروتینهای دیگر، تسکها و Future ها. کوروتینها توسط یک حلقه رویداد (Event Loop) مدیریت میشوند که آنها را زمانبندی و اجرا میکند. حلقه رویداد چندین کار غیرهمزمان را انجام میدهد و مطمئن میشود که در زمان آماده بودنشان، اجرا میشوند. حال میتوانیم با شناخت این مفاهیم، بهسراغ نحوه تعریف و استفاده از Coroutine برویم. import asyncio async def say_hello(): print("Hello" await asyncio.sleep(1) # Pauses here, allowing other tasks to run print("World") # Running the coroutine asyncio.run(say_hello()) تابع say_hello یک coroutine است؛ زیرا از “async def” استفاده میکند. await asyncio.sleep(1) اجرای کوروتین را بهمدت یک ثانیه متوقف میکند و به سایر تسکها اجازه میدهد تا در این فاصله اجرا شوند. برای اجرای کوروتین say_hello هم از تابع asyncio.run(say_hello()) استفاده کردیم. درنهایت، خروجی نهایی چاپ “Hello” است و پس از یک ثانیه، کلمه “World” چاپ میشود. ۴ روش مدیریت همزمانی و غیرهمزمانی با Coroutine در پایتون برای مدیریت فرآیندهای همزمان و غیرهمزمان با Coroutine، میتوانیم روشهای زیر را پیاده کنیم. ۱. جداسازی موارد Async از Sync تا حد امکان، کدهای همزمان و غیرهمزمان را ازهم جدا نگه دارید. بدینمعناکه کدهای Async باید از توابع “async def” برای ساخت و از “await” برای مدیریت عملیات I/O-bound استفاده کنند. ازسوی دیگر، کدهای همزمان باید از توابع معمولی بدون “async” و “await” استفاده کنند. ۲. استفاده از Wrappers برای ایجاد پل بین توابع همزمان و غیرهمزمان اگر نیاز به فراخوانی کدهای غیرهمزمان از کدهای همزمان دارید، باید از توابع wrapper استفاده کنید. مثلاً: def call_async(coro): return asyncio.run(coro) این سینتکس به شما کمک میکند تا با تابع ()asyncio.run، یک کوروتین را از درون کد همزمان اجرا کنید. فراخوانی توابع غیرهمزمان از کدهای همزمان ممکن است. اما این روش پیشنهاد نمیشود؛ چراکه برای هر فراخوانی، نیاز به ساخت و اجرای یک Event Loop داریم. نتیجه این چرخه، اغلب ناکارآمد خواهد بود. ۳. استفاده از ابزارهای همزمانی برای اجرای چندین کوروتین بهصورت موازی در یک لحظه، از ابزارهای همزمانی asyncio مانند ()asyncio.gather استفاده کنید. این ابزارها به حداکثر رساندن مزایای برنامهنویسی همزمان را ممکن و ساده میکنند. ۴. استفاده از کتابخانه های Async برای کدهای غیرهمزمان هنگام نوشتن کدهای غیرهمزمان، از کتابخانههای طراحیشده برای این کار استفاده کنید؛ مانند aiohttp برای درخواستهای HTTP. این کتابخانهها API های سازگار با async را ارائه میدهند که بهخوبی با asyncio کار میکنند. ۵ مورد استفاده عملی از Coroutine در پایتون موارد استفاده از Coroutine در پایتون را میتوانید در لیست زیر بخوانید. ماشینهای حالت (State Machines) پیادهسازی ماشینهای حالت در یک زیربرنامه، روشی مؤثر است؛ جاییکه وضعیت برنامه با نقطه ورود یا خروج فعلی رویه تعیین میشود. این عمل، منجر به افزایش خوانایی کد در مقایسه با استفاده از روش goto خواهد شد. مدل بازیگر (Actor Model) Coroutine در پایتون برای اجرای مدل بازیگر به روش همزمانی بسیار مفید است. هر بازیگر رویههای خاص خود را دارد؛ اما کنترل را به زمانبندی مرکزی واگذار میکند تا این بخش بتواند بهصورت متوالی، مدلها را اجرا کند. مدلهای مولدها (Generators) Coroutine برای پیادهسازی مدلهای مولدی که در جریانها بهکار میروند، بهویژه جریانهای ورودی / خروجی، یک گزینه کاربردی است. همچنین متخصصان این تکنیک را یک رویکرد مؤثر برای پیمایش ساختارهای دادهای میدانند. برقراری ارتباط بین فرآیندهای متوالی با کمک Coroutine میتوان بین فرآیندهای متوالی پل ارتباطی ساخت؛ زیرفرآیندهایی که هرکدام از آنها، یک Coroutine است. ارتباط معکوس Coroutine در پایتون برای پیادهسازی ارتباط معکوس (Reverse Communication)، که اغلب در نرمافزارهای ریاضی استفاده میشود، کارآمد است؛ زیرا در این برنامهها، یک رویه برای انجام محاسبات، به فرآیند خاصی نیاز دارد. روش های رفع اشکالات و مشکلات رایج در کار با Coroutine در پایتون برای رفع اشکالات رایج هنگام کار با Coroutine در پایتون، میتوان چهار روش زیر را بهکار گرفت. استفاده از ()asyncio.run و await برای خطای Runtime درصورت دریافت پیغام “RuntimeWarning: coroutine was never awaited”، باید از دو روش ()asyncio.run یا await، بستهبه مشکل استفاده کنید. اگر Coroutine نقطه ورود به کد غیرهمزمان است، از “()asyncio.run” برای اجرای آن استفاده کنید و کد زیر را بنویسید: import asyncio if __name__ == "__main__": asyncio.run(do_something_asynchronously()) اگر کد توسط یک تابع غیرهمزمان دیگر فراخوانی میشود، مطمئن شوید که “await” را بهکار بردهاید: async def main(): await do_something_asynchronously() پیداکردن منابع تسک (Task References) این روش برای رفع مشکلات مربوطبه Coroutine های متوقفشده (آنهایی که درحال اجرا نیستند) بهکار میرود. از ()asyncio.create_task برای ایجاد تسکها و گرفتن منابع آنها استفاده کنید. سپس، ()asyncio.wait را برای انتظار تا تکمیل تسکها بنویسید: async def do_hello(): hello_task = asyncio.create_task(hello()) world_task = asyncio.create_task(world()) await asyncio.wait([hello_task, world_task]) بلوک try و except برای مدیریت استثناها برنامه خود را در یک بلوک try و except قرار دهید تا استثناها را پیدا و مدیریت کنید: async def failing_coroutine(): raise Exception('This coroutine failed!') try: asyncio.run(failing_coroutine()) except Exception as e: print(f'Caught an exception: {e}') استفاده از ()asyncio.run برای دیباگ کردن از ()asyncio.run برای اجرای کوروتین خود استفاده کنید و مطمئن شوید که بهدرستی اجرا میشود: import asyncio async def hello(): await asyncio.sleep(1) print("Hello") async def world(): await asyncio.sleep(2) print("World") async def do_hello(): asyncio.create_task(hello()) asyncio.create_task(world()) if __name__ == "__main__": asyncio.run(do_hello()) از ()asyncio.run برای اجرای Event Loop و مدیریت چرخه حیات Coroutine های خود استفاده کنید. از ()asyncio.wait برای ایجاد وقفه و انتظار در زمان اجرای چندین کار استفاده کنید: async def do_hello(): hello_task = asyncio.create_task(hello()) world_task = asyncio.create_task(world()) await asyncio.wait([hello_task, world_task]) جمع بندی: Coroutine در پایتون استفاده از Coroutine در پایتون سرعت فرآیند برنامهنویسی و کارایی یک برنامه را بهشکل قابل قبولی افزایش میدهد. این تکنیک بهسادگی و با دستور “async def” ساخته و با سینتکس “asyncio.run”، اجرا میشود. این روش مزایای متعددی دارد؛ مانند افزایش پاسخگویی برنامهها به عملیات I/O، استفاده بهینه از سیستم و نیاز به منابع کمتر نسبتبه رشتهها. کاربرد دیگر این تابع در پایتون، افزایش کارایی مدلهای هوش مصنوعی و اجرای چند دستور بهصورت همزمان در نرمافزارها است. ما خوشحال میشویم که در بخش نظرات، پاسخگوی کامنت شما باشیم و بدانیم با خواندن این مقاله، چه نکاتی را کارآمد و مؤثر میدانید؟ چه رتبه ای میدهید؟ میانگین ۵ / ۵. از مجموع ۱ اولین نفر باش معرفی نویسنده مقالات 401 مقاله توسط این نویسنده محصولات 0 دوره توسط این نویسنده تیم فنی نیک آموز معرفی محصول هادی تایانلو مسیر آموزش پایتون 1.390.000 تومان مقالات مرتبط ۰۶ آذر زبان های برنامه نویسی مقایسه بهترین زبانهای برنامهنویسی ۲۰۲۵ ۰۵ آذر زبان های برنامه نویسی زبان گو (GO) و بررسی مزایا و کاربرد این زبان برنامه نویسی ۱۰ آبان زبان های برنامه نویسی عملکرد کتابخانه Turtle در پایتون و کاربرد های آن ۰۸ آبان زبان های برنامه نویسی Migration در لاراول چیست و چه کاربردهایی دارد؟ تیم فنی نیک آموز دیدگاه کاربران لغو پاسخ دیدگاه نام و نام خانوادگی ایمیل ذخیره نام، ایمیل و وبسایت من در مرورگر برای زمانی که دوباره دیدگاهی مینویسم. موبایل برای اطلاع از پاسخ لطفاً مرا با خبر کن ثبت دیدگاه Δ