ליפול מהר עם Pylint


אם יש downside שאני לא מפסיק לשמוע בנוגע לפייתון זה היעדר הקומפילציה. התלונה שאני שומע הכי הרבה זה - ״לא הגיוני שאני כותב קוד וצריך לחכות עד ההרצה שלו כדי להבין אם מה שעשיתי היה בסדר!״.

בתור אחד שמגיע משפה סטטית עם קומפילציה, מהרגע הראשון בו התחלתי לכתוב בפייתון הרגשתי שחסר לי משהו שיעבור על הקוד שלי ויספר לי על בעיות שעלולות לצוץ בעת ההרצה.

בפוסט הזה אציג בקצרה ואספר איך אני משתמש בכלי שאולי היודע ביותר בתחום ה code analysis עבור פייתון, שמתיימר לתת מענה לא רע לבעיה שהצגתי - pylint.

מה זה pylint

pylint הוא כלי שבודק שגיאות בקוד, מנסה לאכוף סטנדרטים של השפה, ומחפש 'smells' בקוד שלנו, בנוסף הכלי יודע לתת הצעות refactor לחלקים בקוד ומספק מידע על מורכבות הקוד שלנו.

ובסוף, אחרי כל זה הוא נותן לקוד שלנו ציון לפי הפרמטרים שהוזכרו לעיל.

איך משתמשים ב pylint

pylint הוא cli tool פשוט מאוד לשימוש. 

נתקין אותו באמצעות pip install pylint בסביבה בה שאר החבילות שלנו מותקנות (אחרת נקבל שגיאות רבות על כך שחבילות אינן מותקנות).

לאחר ההתקנה ניתן לראות את יכולות הכלי באמצעות pylint --help

בגדול כל מה שצריך לעשות כדי לבדוק את הקוד שלנו זה רק להריץ את הפקודה pylint עם הנתיב לקובץ או לתיקייה אותם נרצה לבדוק.

זה פשוט מאוד ויראה ככה:
כתבתי אסופה של שורות קוד שלא עושות הרבה אבל לפיילינט יש לא מעט להגיד עליהן (כמובן שיצרתי שגיאות וטעויות קונבנציה בכוונה כאן).

לקובץ קראתי app.py ועכשיו אריץ את הפקודה pylint app.py

וזו התוצאה שקיבלתי (כן, לנוסחה שמחשבת את הציון אין גבול תחתון ואפשר לקבל ציון שלילי על הקוד)


אנחנו יכולים לראות כאן כל מיני שגיאות וכל שגיאה מתחילה באות כאשר האותיות הן E(rror), W(arning), R(efactor) ו (C(onvenion.

אפשר לראות שבתכלס הדבר היחיד מבין כל ההודעות כאן שיגרום לכך שהקוד שלנו לא יצליח לרוץ הוא הerror שאומר שאנחנו לא יכולים לעשות import ל request (כי בכוונה לא התקנתי אותו).

מה אני עושה עם הפרויקט שלי כבר מוכן?

בתכלס, זה החלק המעניין וגם החסרון העיקרי של pylint, הכלי כנראה לא יותר חכם מאיתנו כמפתחים ויעיר לנו לא מעט גם על דברים שעשינו בכוונה.
אבל אין צורך לדאוג משתי סיבות - 
  1. לאחר מספר שנים של שימוש בכלי אני יכול להעיד שעלות התחזוקה של הכלי שווה לגמרי את התועלת שמקבלים ממנו (בהמשך אסביר למה).
  2. הכלי מציע אפשרויות פשוטות של ביטול התראות מכל סוג שנרצה (גם בקובץ קונפיגורציה, גם בשורת ההרצה, וגם ממש כחלק מהקוד), כך שבקלות אפשר לנקות חלקים גדולים מהרעש שנוצר ולהתמקד בדברים המעניינים יותר.
הסיבה העיקרית בגללה אני רואה צוותים נכשלים בשימוש ב pylint היא בגלל שכבר יש להם הרבה קוד כתוב, וכשהם מריצים את הכלי על הקודבייס הקיים שלהם נוצר רעש רב של שגיאות שצפות ולא יודעים איפה להתחיל.

אז מה אפשר לעשות עם זה?

יש כמה דרכים באמצעותן ניתן לתקוף את האירוע הזה -
1. לפתוח בכל פעם רמת שגיאות אחת רלוונטית: להתחיל לקבל הודעות על הסוג Error, לאחר מכן על Warning וכן הלאה.. את זה ניתן לעשות באמצעות הוספה של --disable לשורת ההרצה
2. לעבוד כל פעם על איזורים רלוונטיים אחרים בקוד: אפשר להתחיל ממודול אחד, ולהגדיל את הסקופ כל פעם קצת איך שנבחר וככה נוכל לתקוף כל פעם איזור אחר ולא יהיה הרבה רעש של שגיאות.
3. להריץ pylint רק על קבצים חדשים: באמצעות git diff אנחנו יכולים לגלות בדיוק אילו קבצים השתנו ולהריץ את הכלי רק עליהם.
4. diff של pylint בין git branches: זו כנראה הדרך ה״patchית״ וכדאי לגשת אליה כשאנחנו רואים שהעלות לביצוע שלוש הדרכים הראשונות גבוהה מדי עבורנו.
בדרך זו אני משתמש לרוב כשהרצה רגילה של פיילינט מציגה לי הרבה רעש ואני רוצה לבצע השוואה בין הבראנץ׳ ממנו יצאתי לבראנץ׳ עם השינוי שביצעתי.
את הdiff אבצע באמצעות לקיחת "snapshot" של ה output שלי בכל אחד מהברנצ׳ים (המקור וזה ששינתי) ואז אשווה בניהם:


ויודפס לנו ההפרש בין הפלטים.

כל הדרכים שהוצגו יכולות לעזור לנו להתמודד עם קוד קיים וסביר להניח ששילוב בין הדרכים יהיה נכון, אבל איזו דרך שלא נבחר - מה שחשוב זה להכין תכנית כדי לגרום לכמה שיותר איזורים בקוד להיות מכוסים.

שילוב כחלק מ continuous integration pipeline

כל מה שכתבתי למעלה נחמד מאוד אבל סביר להניח שלא נרצה בעבור כל שינוי שעשינו להריץ pylint בעצמנו.

לאחר שביצענו הטמעה של הכלי בקוד שלנו (או באיזורים מסויימים ממנו) מה שמומלץ לעשות כדי לקבל את הפידבק המהיר והזול ביותר הוא פשוט להוסיף לפני הרצת הטסטים ב CI flow, שלב של הרצת pylint ואז במקרה של כשלון, הכלי יחזיר exit code שונה מ 0 מה שיגרום ל CI שלנו להכשל (זה כמובן ניתן לביטול עם הדגל exit-zero).

עלות מול תועלת של השימוש (וגילוי נאות)

מן הכל, בסוף מסתכם בעלות מול התועלת של הדברים שאנחנו עושים. בראייתי ואחרי שהטמעתי את הכלי בכמה פרויקטים שונים ובכמה צוותים שונים, הדרך שעבדה לי הכי טוב ושיעבדה אותי הכי פחות הייתה לעשות disable לכל מה שלא Error ולהכניס את ההרצה של הכלי כשלב חוסם לפני הרצת הטסטים של המוצר עליו עבדתי. צריך לזכור שבסופו של דבר, הכלי (כל כלי) אמור לשרת אותנו ולהקל עלינו ולא לגרום לעבוד יותר מדי קשה בתחזוקה יומיומית.

סיכום

pylint הוא כלי סריקת קוד ששינה עבורי את כללי המשחק בכתיבת פייתון וקיצר את מחזור חיי פיתוח התוכנה שלי פלאים. קל מאוד להפעיל אותו, יש סביבו קהילה גדולה, ואפשר להפיק ממנו לא מעט גם רק על ידי מעבר חד פעמי של סריקה וביצוע תיקונים. המלצתי העיקרית היא להכניס את הכלי כחלק מתהליך ה CI וכך לאכוף סטנדרטים ושגיאות באופן אוטומטי בשניות בודדות במקום לחכות שסוויטות שלמות של טסטים יפלו רק כדי להבין שיש לנו syntax error.

כמובן שזהו רק קצה הקרחון של הכלי ויש לו יכולות רבות ועומק - ממליץ מאוד לעבור על הדוקומנטציה שלו.

נתראה בפוסט הבא :)

תגובות

פוסטים פופולריים מהבלוג הזה

מהם קבצי DLL ואיך להשתמש בהם?

תכנות מונחה עצמים | Dependency Inversion Principle

מה ההבדל בין אוטומציה לפיתוח רגיל