Monkey patching בשפת תכנות דינמית
ניסיתי להריץ אפליקציה של FastApi, כדי לקרוא מיילים בעזרת הספרייה Imbox אלא שהתוכנה קרסה עם הודעת שגיאה:
LookupError: unknown encoding: iso-8859-8-i
ולא הצלחתי למצוא בשום מקום איך לפתור את הבעיה.
המטרה של מדריך זה היא להסביר איך פתרתי את הבעיה ואף יותר מכך להסביר את הטכניקה של Monkey Patching, כדרך להוסיף טלאים של קוד לספריית קוד קיימת, יתרונות הגישה וחסרונותיה, ומה החלופות.
הבעיה עם תווים עבריים
עברית היא שפה המונה מעט מאוד משתמשים בעולם, ובהתאם למחשבים לא תמיד קל לעבוד אותה. במשך שנים, גובשו סטנדרטים שונים לשימוש בעברית. ביניהם:
- iso-8859-8 לקידוד עברי סטנדרטי (ויזואלי).
- iso-8859-8-i "עברית לוגית" הנפוצה הרבה פחות בימינו.
בעוד כל השפות והספריות בימינו תומכות בסטנדרט הויזואלי, ישנם מקרים שבהם יש צורך להשתמש בקידוד שאינו סטנדרטי. במקרה שלי, הבעיה הייתה שהאימייל נשלח כשהוא מקודד בסטנדרט של "עברית לוגית". ובזה פייתון לא תומך אם הוא לא נדרש לכך במפורש.
ניסיון ראשון: הפנייה לקידוד הסטנדרטי
המחשבה הראשונה הייתה, שאם פייתון לא תומך בקידוד אז ננסה לגרום לכך שהוא יקרא את הטקסט כאילו היה הקידוד סטנדרטי. וזה בדיוק מה שהקוד הבא מנסה לעשות:
import codecs
codecs.register(
lambda name: codecs.lookup("iso-8859-8")
if name.lower() in ["iso-8859-8-i", ]
else None
)
- התוצאה של שילוב הקוד באפליקציה היתה אותה הודעת שגיאה כך שלא פתרנו את הבעיה.
ניסיון שני: Monkey Patching של קוד ספרייה קיימת
כיוון שמקור הבעיה היא בקוד של ספרייה קיימת, Imbox, שהדבר האחרון שכדאי לעשות הוא לשנות אותו, ומכיוון שהבעיה היתה זמנית בלבד, כך הובטח לי, פניתי לפתרון "מהיר ומלוכלך" של Monkey Patching.
Monkey patching היא טכניקה המשמשת בשפות דינמיות, דוגמת: JavaScript או Python, כדי לשנות או להרחיב את התנהגות הקוד הקיים בזמן ריצה מבלי לשנות את קוד המקור. משתמשים בזה כדי לתקן באגים בספריות צד שלישי, אבל בעיקר לצורך בדיקות תוכנה. כך שחשוב להכיר את הטכניקה.
בתחילה, ניסיתי לעשות patching לפונקציה `imbox.utils.str_decode` שלפי VSCODE בה היתה הבעיה. אבל זה לא עבד.
למה זה לא עבד? כי מקור התקלה היה ב-`imbox.parser` שמייבא את הפונקציה בנפרד, כך התברר.
בירורים העלו את האפשרות שה-`parser` דווקא הוא המקום בו יש לטפל, בהתאם את ה-patch עשיתי על ה-`parser`:
from imbox import parser as imbox_parser
# Keep original
_orig_decode = imbox_parser.str_decode
def patched_str_decode(value, encoding=None, errors="replace"):
if encoding and encoding.lower() in ("iso-8859-8-i", "iso_8859-8-i"):
encoding = "iso-8859-8"
return _orig_decode(value, encoding, errors)
# Apply patch
imbox_parser.str_decode = patched_str_decode
- שים לב, שאת הפונקציה המקורית אין דורסים אלא שומרים (במקרה זה, במשתנה `_orig_decode`) לשימוש בהמשך, אם צריך.
patch זה עבד, והתקלה נפתרה.
למה Monkey Patching הוא לא בהכרח הפתרון הכי טוב ומה אפשר לעשות במקום?
Monkey patching זו טכניקה שכדאי להכיר בשביל בדיקות מהירות או תיקונים "מהירים ומלוכלכים" אבל יש לה גם מגבלות שחשוב להכיר:
- תחזוקה וקריאות: הטכניקה עלולה להקשות על הבנת הקוד ותחזוקתו, כיוון שכאשר המתכנת קורא את קוד המקור הוא עלול לגלות שהוא אינו תואם את התנהגות התוכנה בפועל.
- קושי בתיקון באגים: הנובע מבעית הקריאות ומכך שקשה לזהות את מקור התקלות.
לפיכך, אם בוחרים להשתמש ב- Monkey patchingיש לעשות זאת בזהירות מרבית. ואם צריך תיקון יותר רציני אז עדיף להשתמש בירושה, או באחד הדפוסים: קומפוזיציה או decorator.
מה אפשר ללמוד מזה?
- Monkey patching משמש לתיקוני באגים ובדיקות תוכנה של ספריות צד שלישי בלי לערוך את קוד המקור.
- אם משתמשים ב-Monkey patching אז בזהירות ובמתינות כי יש פתרונות טובים יותר.
מדריכים נוספים שעשויים לעניין אותך
לכל המדריכים בסדרה ללימוד פייתון
אהבתם? לא אהבתם? דרגו!
0 הצבעות, ממוצע 0 מתוך 5 כוכבים
המדריכים באתר עוסקים בנושאי תכנות ופיתוח אישי. הקוד שמוצג משמש להדגמה ולצרכי לימוד. התוכן והקוד המוצגים באתר נבדקו בקפידה ונמצאו תקינים. אבל ייתכן ששימוש במערכות שונות, דוגמת דפדפן או מערכת הפעלה שונה ולאור השינויים הטכנולוגיים התכופים בעולם שבו אנו חיים יגרום לתוצאות שונות מהמצופה. בכל מקרה, אין בעל האתר נושא באחריות לכל שיבוש או שימוש לא אחראי בתכנים הלימודיים באתר.
למרות האמור לעיל, ומתוך רצון טוב, אם נתקלת בקשיים ביישום הקוד באתר מפאת מה שנראה לך כשגיאה או כחוסר עקביות נא להשאיר תגובה עם פירוט הבעיה באזור התגובות בתחתית המדריכים. זה יכול לעזור למשתמשים אחרים שנתקלו באותה בעיה ואם אני רואה שהבעיה עקרונית אני עשוי לערוך התאמה במדריך או להסיר אותו כדי להימנע מהטעיית הציבור.
שימו לב! הסקריפטים במדריכים מיועדים למטרות לימוד בלבד. כשאתם עובדים על הפרויקטים שלכם אתם צריכים להשתמש בספריות וסביבות פיתוח מוכחות, מהירות ובטוחות.
המשתמש באתר צריך להיות מודע לכך שאם וכאשר הוא מפתח קוד בשביל פרויקט הוא חייב לשים לב ולהשתמש בסביבת הפיתוח המתאימה ביותר, הבטוחה ביותר, היעילה ביותר וכמובן שהוא צריך לבדוק את הקוד בהיבטים של יעילות ואבטחה. מי אמר שלהיות מפתח זו עבודה קלה ?
השימוש שלך באתר מהווה ראייה להסכמתך עם הכללים והתקנות שנוסחו בהסכם תנאי השימוש.