Python Asynchronous Programming

Python Asynchronous Programming

הרבה פעמים, כשאני מדבר בקורס ה Python שאני מעביר על נושאים כמו Multithreading ואסינכרוניות, לאנשים יש נטיה להתבלבל ביניהם. אני אנסה להסביר ולבאר את המושג של תכנות אסינכרוני, בדגש על שפת פייתון. כשאנו מדברים על תכנות אסינכרוני, אנו מתכוונים לתכנות בו התוכנית הראשית קוראת לתהליך אחד או יותר במהלכה ולא ממתינה עד שיסתיים. הרבה פעמים זה בסגנון של ״שגר ושכח״, מה שהופך את התוכנית למהירה יותר. דוגמה לכך היא תוכנית בשפת Python הכותבת לקובץ Log תוך כדי. התוכנית הראשית, תוף כדי ריצתה, ״משגרת״ תהליכים של כתיבה לקובץ לוג וממשיכה הלאה במהלך הקוד, גם שהכתיבה לקובץ ה log עוד לא הסתיימה. צורת העבודה הזאת לא רק מהירה יותר (מבחינת זמן ריצת התוכנית) אלא גם ״מוגנת״ יותר, שכן אם התהליך של כתיבה לקובץ ה Log ייכשל, התוכנית הראשית לא תקרוס !  במקרים רבים של תכנות אסינכרוני, אנו רוצים להריץ קטע קוד מסויים לאחר שהתהליך האסינכרוני יסתיים, אך היות והתוכנית הראשית אינה ממתינה( שכן המשיכה לרוץ), הדרך היחידה שלנו היא להעביר כתובת לפונקציה לתהליך האסינכרוני כך שהפונקציה תקרא לה בסופו ( Callback Function)

. תכנות אסינכרוני מחייב עבודה עם Thread נוסף כשמדובר על מעבד עם ליבה אחת. במקרים של מעבדים מרובי ליבות, זה יכול להתבצע אף בתהליכים (Processes) שונים.

 

 

אסינכרוניות ב Python

הטכניקות היותר חדישות לתכנות אסינכרוני בפייתון הם ה asyncio module שהופיע בפייתון 3.4 וה async-await שהופיע לראשונה בפייתון 3.5, למרות שגם לפני גרסה 3.4 ניתן היה, רק בדרכים פחות ״אלגנטיות״.

להמחשת העבודה האסינכרונית, אתאר 2 מושגים, בהם אני גם עושה שימוש בקורסים שלי.

מדובר על Coroutines ו Tasks.

 

 

Coroutines & Tasks

Coroutine זה בדרך כלל פונקציה עם הגדרה של async, למרות שזה יכול להיות גם אובייקט שחוזר מפונקציה שהיא async.

ברגע שפונקציה מוגדרת כ async, היא יכולה להיקרא ע״י await, לדוגמה :

 (await some_function(

כשקוד התוכנית ״פוגש״ ב await, התוכנית קוראת לפונקציה ומשהה את הריצה עד שהפונקציה מסתיימת. אז – Coroutine אחד יכול לרוץ.

מדמעות השהיית ריצת הקוד היא שהשליטה חוזרת ל Event Loop: כשמשתמשים ב asyncio, ה Event Loop מריץ את כל הפעולות האסינכרוניות, מבצע פעולות IO ופעיל תתי תהליכים, ולכן, ברוב המקרים, כשאנו נריץ Coroutines, הם ירוצו למעשה בתוך Tasks.

Task מאפשר לנו להריץ Coroutine בתוך ה Event Loop, מה שמפשט את הניהול של מספר Coroutines במקביל.

ראו הדוגמה הבאה :

פונקציית ה say_after מלווה ב async ולכן היא Coroutine.  בדוגמה הזאת, ה Coroutines רצים במקביל, במשך 2 שניות, בעוד שיכולנו גם להריץ אותם בצורה סדרתית ואז זה היה לוקח 3 שניות:

וזה למעשה היתרון בשימוש ב Tasks בפייתון, היכולת להריץ במקביל ולקצר את זמני הריצה.

המאמר נכתב על ידי יניב ארד מרצה ומנטור 

למידע על קורס פייתון כנסו כאן

העתיד שלך בהייטק מתחיל כאן
צור איתי קשר עוד היום

דילוג לתוכן