• בלוג
  • היום למדתי: SystemExit בפייתון

היום למדתי: SystemExit בפייתון

09/09/2026

קלוד החליט לגוון בסקריפט פייתון שביקשתי וסיים את הסקריפט עם הקטע הבא שקצת הפתיע אותי:

if __name__ == "__main__":
    raise SystemExit(main())

למה לסיים קוד עם raise? מי זה SystemExit? ומה ההגיון בשיטת הכתיבה הזו?

נתחיל בחיבור של הסקריפט עם מערכת ההפעלה. ביוניקס תנאים עובדים בצורה קצת מוזרה בתוכנית המעטפת - בתוכניות רגילות אנחנו רגילים שתנאי בודק אם ביטוי מסוים הוא "אמת" או "שקר". ביוניקס תנאי ב bash בודק אם תוכנית מסוימת הצליחה או נכשלה. לדוגמה הפקודה:

if rm demo
then
    echo "yes"
else
    echo "no"
fi

מנסה להריץ את פקודת המחיקה, אם הצליחה למחוק אז היא תדפיס yes ואם לא הצליחה למחוק תדפיס no.

איך אנחנו יודעים אם תוכנית "הצליחה" או "לא הצליחה"? כל תוכנית יוניקס מחזירה ערך למערכת ההפעלה. ערך 0 מעיד על הצלחה וכל ערך שאינו 0 מעיד על כשלון. בפייתון אפשר להשתמש ב sys.exit כדי להחזיר ערך למערכת ההפעלה לדוגמה תוכנית הפייתון הבאה תמיד תכשל:

import sys

sys.exit(1)

ותוכנית הפייתון הבאה תמיד תצליח:

import sys

sys.exit(0)

מי שרוצה להעביר את ההחלטה אם להצליח או להכשל לפונקציה בשם main יכול לכתוב קוד כזה:

import sys

result = main()
sys.exit(result)

או צעד לכיוון הקוד מתחילת הפוסט:

import sys

sys.exit(main())

ומה עושה sys.exit? שימו לב למימוש מתוך sysmodule.c:

static PyObject *
sys_exit_impl(PyObject *module, PyObject *status)
/*[clinic end generated code: output=13870986c1ab2ec0 input=b86ca9497baa94f2]*/
{
    /* Raise SystemExit so callers may catch it or clean up. */
    PyErr_SetObject(PyExc_SystemExit, status);
    return NULL;
}

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

raise SystemExit(main())

ולחסוך את ה import sys.

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