Logging א': למה print אינו Logging, ורמות הלוג
- להסביר מה זה Log ולמה print לא מתאים לתיעוד במערכת אמיתית
- להכיר את חמש רמות ה-Logging ומתי משתמשים בכל אחת
- להגדיר Logging בסיסי עם
logging.basicConfigולבחור רמה מינימלית - להוסיף לפורמט הלוג זמן ורמה
מה נלמד?
- מה זה Log (יומן) ולמה מערכות אמיתיות כותבות אותו.
- למה
printאינו Logging. - המודול
loggingשל Python. - חמש רמות הלוג:
debug,info,warning,error,critical.
למה צריך את זה?
השרת שתכתבו בנושא Backend ומסדי נתונים ירוץ בלי שאף אחד יסתכל עליו, אולי על מחשב בענן, באמצע הלילה. מחר בבוקר לקוח יגיד “ההזמנה שלי נעלמה בלילה”. איך תדעו מה קרה?
printהדפיס למסך שאף אחד לא ראה, וכבר נעלם.- ה-Debugger לא עוזר, כי הבאג קרה אתמול, לא עכשיו.
הלוג הוא “קופסה שחורה” כמו במטוס: תיעוד של מה שקרה, מתי, וכמה חמור. כל מערכת מקצועית כותבת לוגים, ומפתחים קוראים אותם כל יום.
הסבר מהבסיס
מה זה Log?
Log הוא רצף רשומות (Records). כל רשומה מתארת אירוע אחד: מתי קרה, כמה חמור הוא, ומה קרה.
2026-10-06 09:14:02 INFO User dana logged in
2026-10-06 09:14:30 WARNING Login attempt with wrong password for avi
2026-10-06 09:15:11 ERROR Payment failed for order 1042: card declinedלמה print אינו Logging
print | logging | |
|---|---|---|
| זמן | אין. לא יודעים מתי זה קרה. | אוטומטי בכל רשומה |
| חומרה | כל ההודעות נראות אותו דבר | 5 רמות. אפשר לסנן |
| כיבוי/הדלקה | צריך למחוק או להוסיף שורות בקוד | משנים הגדרה אחת, בלי לגעת בקוד |
| יעד | רק למסך | מסך, קובץ, שרת לוגים… |
| בשרת | הולך לאיבוד | נשמר ונבדק אחר כך |
כלל: print הוא לתקשורת עם משתמש (פלט של התוכנית). logging הוא לתקשורת עם מפתחים ואנשי תפעול (מה קרה בתוך התוכנית).
חמש הרמות
| רמה | מספר | מתי משתמשים | דוגמה |
|---|---|---|---|
DEBUG | 10 | פרטים טכניים למפתח, בזמן פיתוח ודיבאג | "cart contents: [...]" |
INFO | 20 | אירועים רגילים וחשובים — “הכול תקין” | "user dana logged in" |
WARNING | 30 | משהו חריג, אבל המערכת ממשיכה | "disk 90% full", "retrying request" |
ERROR | 40 | פעולה נכשלה | "payment failed for order 1042" |
CRITICAL | 50 | המערכת כולה בסכנה ואולי לא יכולה להמשיך | "database unreachable - shutting down" |
רמה מינימלית — הסינון
מגדירים רמה מינימלית, ומוצגות רק הודעות ממנה ומעלה:
- בזמן פיתוח:
DEBUG. רואים הכול. - בשרת אמיתי (Production):
INFOאוWARNING. רק מה שחשוב, בלי “רעש”.
ברירת המחדל של Python היא WARNING. לכן אם לא מגדירים כלום, הודעות debug ו-info לא יוצגו בכלל.
DEBUG = הרישום המלא של כל מדידה (רק הרופא החוקר מסתכל). INFO = “המטופל קיבל ארוחת צהריים”. WARNING = “חום מעט גבוה, לעקוב”. ERROR = “תרופה לא ניתנה בזמן”. CRITICAL = “קוד כחול!”. האחות במשמרת לילה מגדירה לעצמה לראות רק WARNING ומעלה, אחרת היא תטבע בהודעות.
תחביר
import logging
# configure once, at the start of the program
logging.basicConfig(
level=logging.INFO, # minimum level to show
format="%(asctime)s %(levelname)s %(message)s", # how each record looks
)
# write log records
logging.debug("technical details")
logging.info("normal important event")
logging.warning("something unusual")
logging.error("an operation failed")
logging.critical("the whole system is in danger")שדות נפוצים ב-format:
| שדה | מה מוצג |
|---|---|
%(asctime)s | תאריך ושעה |
%(levelname)s | שם הרמה (INFO, ERROR…) |
%(message)s | ההודעה שלכם |
%(funcName)s | שם הפונקציה שכתבה את הרשומה |
%(lineno)d | מספר השורה |
דוגמת קוד ראשונה
week-2/log_levels.py:
import logging
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s %(levelname)s %(message)s",
)
logging.debug("This is a debug message")
logging.info("Application started")
logging.warning("Config file not found, using defaults")
logging.error("Could not connect to the payment service")
logging.critical("Out of memory - shutting down")פלט:
2026-10-06 09:30:12,481 INFO Application started
2026-10-06 09:30:12,481 WARNING Config file not found, using defaults
2026-10-06 09:30:12,482 ERROR Could not connect to the payment service
2026-10-06 09:30:12,482 CRITICAL Out of memory - shutting downפירוק הקוד שורה אחר שורה
| שורה | הסבר |
|---|---|
import logging | המודול המובנה של Python ללוגים. אין צורך בהתקנה. |
logging.basicConfig(...) | הגדרה חד-פעמית בתחילת התוכנית: מה הרמה המינימלית ואיך נראית כל רשומה. |
level=logging.INFO | מציגים רק מ-INFO ומעלה. |
format="..." | תבנית הרשומה: זמן, רמה, הודעה. |
logging.debug(...) | לא מוצג! DEBUG (10) נמוך מ-INFO (20), ולכן סונן. |
logging.info(...) עד logging.critical(...) | מוצגים, כי הם ברמה INFO ומעלה. |
,481 בפלט | אלפיות שנייה. שימושי כשהרבה אירועים קורים באותה שנייה. |
נסו: שנו ל-level=logging.DEBUG והריצו שוב. עכשיו מופיעות 5 שורות. ב-level=logging.ERROR מופיעות רק 2. שיניתם שורה אחת, ולא נגעתם בהודעות עצמן. זה הכוח של רמות.
דוגמה נוספת
לוגים בתוך תוכנית אמיתית, משולבים עם Exceptions מהשיעורים הקודמים. week-2/orders.py:
import logging
logging.basicConfig(
level=logging.DEBUG,
format="%(asctime)s %(levelname)-8s %(funcName)s: %(message)s",
)
STOCK = {"bread": 5, "milk": 0, "eggs": 12}
def place_order(product, quantity):
logging.debug("place_order called with product=%s quantity=%s", product, quantity)
if product not in STOCK:
logging.error("Unknown product requested: %s", product)
return False
available = STOCK[product]
if available == 0:
logging.warning("Product out of stock: %s", product)
return False
if quantity > available:
logging.warning("Not enough %s: requested %s, available %s", product, quantity, available)
return False
STOCK[product] = available - quantity
logging.info("Order placed: %s x%s (left in stock: %s)", product, quantity, STOCK[product])
return True
place_order("bread", 2)
place_order("milk", 1)
place_order("cake", 1)
place_order("eggs", 20)פלט:
2026-10-06 09:41:03,115 DEBUG place_order: place_order called with product=bread quantity=2
2026-10-06 09:41:03,115 INFO place_order: Order placed: bread x2 (left in stock: 3)
2026-10-06 09:41:03,116 DEBUG place_order: place_order called with product=milk quantity=1
2026-10-06 09:41:03,116 WARNING place_order: Product out of stock: milk
2026-10-06 09:41:03,116 DEBUG place_order: place_order called with product=cake quantity=1
2026-10-06 09:41:03,116 ERROR place_order: Unknown product requested: cake
2026-10-06 09:41:03,117 DEBUG place_order: place_order called with product=eggs quantity=20
2026-10-06 09:41:03,117 WARNING place_order: Not enough eggs: requested 20, available 12פירוק:
%(levelname)-8s— ה--8מרפד את שם הרמה ל-8 תווים, כך שההודעות מיושרות בעמודה. נוח לקריאה.%(funcName)s— רואים מאיזו פונקציה הגיעה כל רשומה.logging.info("... %s ...", product, quantity)—%sהוא מקום לערך, והערכים מועברים כארגומנטים נוספים. זו הדרך המומלצת ב-logging: הטקסט נבנה רק אם ההודעה באמת תוצג, ולכן הודעות DEBUG מסוננות כמעט לא עולות כלום.- בחירת הרמות: “הוזמן” הוא INFO (אירוע רגיל וחשוב). “אזל מהמלאי” הוא WARNING (העסק עובד, אבל כדאי לדעת). “מוצר לא קיים” הוא ERROR (משהו לא תקין בבקשה, אולי באג בצד הלקוח). פרטי הקריאה הם DEBUG.
if product not in STOCK—inעל dict בודק אם המפתח קיים.
עכשיו שנו ל-level=logging.WARNING: הלוג יציג רק את 3 הבעיות. כך ייראה בשרת אמיתי, שבו מעניינות רק התקלות.
טעות נפוצה
הטעות 1: לקרוא ל-basicConfig אחרי שכבר נכתבה הודעה, או פעמיים.
import logging
logging.info("starting") # uses the default config!
logging.basicConfig(level=logging.INFO) # ignored - already configured
logging.info("now?") # still not shownהקריאה הראשונה ל-logging.info מגדירה אוטומטית את ברירת המחדל (WARNING), ו-basicConfig מאוחר מתעלם בשקט. basicConfig תמיד ראשון, ופעם אחת, מיד אחרי ה-import.
הטעות 2: “לא רואה את ה-info שלי”. הסיבה היא כמעט תמיד ברירת המחדל WARNING. הפתרון: level=logging.INFO (או DEBUG).
הטעות 3: רמה לא נכונה.
logging.error("User dana logged in") # not an error!
logging.info("Payment failed!") # this IS an errorרמה שגויה הופכת את הסינון לחסר תועלת: מי שמסתכל רק על ERROR יפספס תשלום שנכשל, ויוצף בהתחברויות רגילות.
הטעות 4: לרשום מידע רגיש. logging.info("login: user=dana password=1234") — לעולם לא סיסמאות, מספרי כרטיס אשראי או טוקנים. לוגים נקראים על ידי הרבה אנשים ונשמרים זמן רב.
תרגול
התרגילים מבוססים רק על מה שנלמד בשיעור הזה ובשיעורים שלפניו. נסו לבד, ורק אז פתחו את הפתרון.
תרגיל 1: איזו רמה?
לכל אירוע — באיזו רמת לוג הייתם רושמים אותו: DEBUG, INFO, WARNING, ERROR או CRITICAL?
- משתמש התחבר בהצלחה.
- ערך של משתנה בתוך לולאה, בזמן חיפוש באג.
- משתמש הקליד סיסמה שגויה.
- התשלום נכשל.
- אין חיבור למסד הנתונים, והשרת לא יכול לעבוד בכלל.
הצג פתרון
- INFO — אירוע רגיל וחשוב לתיעוד.
- DEBUG — פרטים טכניים שרלוונטיים רק בזמן פיתוח.
- WARNING — משהו חריג, אבל המערכת ממשיכה לעבוד.
- ERROR — פעולה נכשלה.
- CRITICAL — המערכת כולה לא יכולה לעבוד.
תרגיל 2: רמה מינימלית
import logging
logging.basicConfig(level=logging.WARNING)
logging.debug("checking item 3")
logging.info("order 17 created")
logging.warning("stock is low: 2 left")
logging.error("payment failed for order 17")אילו מההודעות יופיעו, ולמה? מה צריך לשנות כדי לראות את כולן?
הצג פתרון
יופיעו רק WARNING ו-ERROR:
WARNING:root:stock is low: 2 left
ERROR:root:payment failed for order 17level=logging.WARNING הוא רמה מינימלית: מוצגות רק הודעות ברמה הזו ומעליה. כדי לראות את כולן משנים ל-level=logging.DEBUG. בלי לגעת בשאר הקוד — זה כל היתרון.
תרגיל 3: מ-print ל-logging
החליפו כל print ברמת הלוג המתאימה, והגדירו פורמט עם זמן, רמה והודעה:
def withdraw(balance, amount):
print("withdraw called with", amount)
if amount > balance:
print("not enough money, balance is", balance)
return balance
print("withdrew", amount)
return balance - amountהצג פתרון
import logging
logging.basicConfig(
level=logging.DEBUG,
format="%(asctime)s %(levelname)-8s %(message)s",
)
def withdraw(balance, amount):
logging.debug("withdraw called with %s", amount)
if amount > balance:
logging.error("not enough money, balance is %s", balance)
return balance
logging.info("withdrew %s", amount)
return balance - amount
withdraw(100, 30)
withdraw(100, 500)- כניסה לפונקציה — DEBUG, משיכה מוצלחת — INFO, כישלון — ERROR.
- הפורמט מוסיף לכל שורה זמן ורמה, למשל:
2026-11-01 10:15:02 ERROR not enough money, balance is 100.
תרגיל 4: לקרוא שורת לוג
2026-11-01 09:14:30 WARNING Wrong password for avi- מה כל חלק בשורה, ואיזה חלק בהגדרה
formatיוצר אותו? - למה חשוב שיש בשורה זמן?
הצג פתרון
- החלקים:
2026-11-01 09:14:30— הזמן, נוצר מ-%(asctime)s.WARNING— הרמה, נוצרת מ-%(levelname)s.Wrong password for avi— ההודעה, נוצרת מ-%(message)s.
- כשמשהו קורה בשרת בשלוש בלילה, הזמן מאפשר לשחזר מה קרה ובאיזה סדר, ולהצליב עם אירועים אחרים.
תרגיל 5: print או logging?
לכל מקרה — print או logging? הסבירו.
- תוכנית שמבקשת מהמשתמש את שמו ומברכת אותו.
- שרת שרץ כל הלילה, ורוצים לדעת בבוקר אילו הזמנות נכשלו.
- בדיקה זמנית של ערך משתנה בזמן פיתוח, שתרצו לכבות בלי למחוק.
הצג פתרון
- print — זה הפלט שהתוכנית מציגה למשתמש.
- logging (ERROR) — מידע למפתח, עם זמן ורמה, שאפשר לשמור ולחפש בו.
- logging (DEBUG) — אפשר לכבות את כל הודעות ה-DEBUG בשורה אחת (העלאת הרמה המינימלית), בלי למחוק קוד.
הכלל: print למשתמש, logging למפתח.
סיכום
- Log = תיעוד של אירועים: מתי, כמה חמור, ומה קרה. “קופסה שחורה” של התוכנה.
print= פלט למשתמש.logging= תיעוד למפתחים: זמן, רמה, סינון ויעדים.- 5 רמות: DEBUG < INFO < WARNING < ERROR < CRITICAL. מוצגות רק הודעות מהרמה המינימלית ומעלה.
- ברירת המחדל היא WARNING.
basicConfigנקרא פעם אחת, ראשון. logging.info("x=%s", x)היא הצורה המומלצת. ולעולם לא רושמים סיסמאות.
דוקומנטציה רשמית
- Logging HOWTO — When to use logging — print מול logging, ואיזו רמה מתי
- logging — Logging Levels — debug, info, warning, error, critical