איך עובדים עם קבצים בפייתון - מדריך ל-open, קריאה וכתיבה¶
בואו נדבר בכנות. בשלב מסוים כל תוכנית אמיתית צריכה לגעת בקובץ בפועל - לקרוא הגדרות, לשמור תוצאות, לעבד קובץ טקסט ענק. פייתון עושה את זה בצורה נוחה יחסית, אבל יש כמה הרגלים שכדאי ללמוד נכון מהתחלה, כדי לא לגרור באגים מציקים.
פתיחת קובץ עם open¶
הפונקציה הבסיסית היא open, שמקבלת נתיב לקובץ ומצב פתיחה:
זה עובד, אבל יש כאן בעיה - אם קורה חריגה בין open ל-close, הקובץ אף פעם לא ייסגר. זה נקרא דליפת משאב - resource leak, וכשזה קורה הרבה פעמים בתוכנית ארוכת חיים, זה יכול לגרום לבעיות אמיתיות.
מדוע כדאי להשתמש ב-with¶
הפתרון הסטנדרטי בפייתון הוא בלוק with:
היתרון כאן - הקובץ נסגר אוטומטית ברגע שיוצאים מהבלוק, גם אם קרתה חריגה בפנים. אין צורך לזכור לקרוא close בעצמכם, ואין סיכוי לשכוח את זה בטעות. זה לא תחביר נחמד בלבד - זו הדרך הנכונה לעבוד עם קבצים בפייתון, וכדאי להתרגל לכתוב אותה כברירת מחדל.
מצבי פתיחה - read, write, append¶
הפרמטר השני ב-open קובע מה מותר לעשות עם הקובץ:
- "r" - קריאה בלבד, ברירת המחדל. הקובץ חייב כבר להתקיים.
- "w" - כתיבה. אם הקובץ קיים, כל התוכן שלו נמחק לפני שכותבים אליו מחדש. אם הוא לא קיים, הוא נוצר.
- "a" - הוספה - append. כותבים לסוף הקובץ הקיים, בלי למחוק את מה שכבר שם. אם הוא לא קיים, הוא נוצר.
הטעות הכי נפוצה כאן היא לפתוח קובץ במצב "w" מתוך מחשבה שהוא מוסיף תוכן, ולגלות שהוא מחק את כל מה שהיה שם קודם. אם הכוונה היא להוסיף בלי למחוק, הפתרון הוא "a", לא "w".
דרכים לקרוא תוכן¶
יש כמה דרכים לקרוא קובץ, וכדאי לבחור לפי המצב:
השיטה השלישית, לעבור על הקובץ ישירות עם לולאה, היא בדרך כלל הבחירה הכי טובה לקבצים גדולים - היא לא טוענת את כל הקובץ לזיכרון בבת אחת, אלא קוראת שורה אחת בכל פעם. read ו-readlines נוחים לקבצים קטנים, אבל בקובץ של כמה ג'יגה הם עלולים לתפוס הרבה זיכרון מיותר.
שימו לב גם ל-strip בדוגמה - כל שורה שנקראת מקובץ טקסט מגיעה עם תו ירידת שורה בסוף, וברוב המקרים רוצים להסיר אותו לפני שמשתמשים בתוכן.
כתיבה לקובץ¶
כתיבה עובדת בדומה, עם write:
בשונה מ-print, write לא מוסיף ירידת שורה אוטומטית - אם רוצים כמה שורות נפרדות, צריך להוסיף \n בעצמכם.
קידוד תווים - encoding¶
כשעובדים עם עברית או כל שפה שאינה אנגלית, שווה להכיר גם את הפרמטר encoding. ברירת המחדל של פייתון תלויה במערכת ההפעלה, ולפעמים זה גורם לתווים מוזרים או לשגיאה כשפותחים קובץ שנכתב בקידוד אחר. הפתרון הפשוט הוא לציין את הקידוד במפורש:
זו הרגל טוב לאמץ כברירת מחדל בכל פעם שפותחים קובץ טקסט, במיוחד כשיש בו עברית, כדי לא להיתקל בבאגים שקשה מאוד לאבחן.
פתיחת כמה קבצים בו-זמנית¶
אפשר גם לפתוח יותר מקובץ אחד באותו בלוק with, למשל כשקוראים מקובץ אחד וכותבים לקובץ אחר:
with open("input.txt", "r", encoding="utf-8") as infile, open("output.txt", "w", encoding="utf-8") as outfile:
for line in infile:
outfile.write(line.upper())
שני הקבצים נסגרים אוטומטית בסוף הבלוק, בדיוק כמו עם קובץ יחיד.
מילה על נתיבים - pathlib¶
עד כאן עבדנו עם שם קובץ פשוט, אבל ברגע שצריך לבנות נתיבים מורכבים יותר, לבדוק אם קובץ קיים, או לעבוד עם תיקיות, מודול pathlib הוא הכלי המודרני והנוח לזה בפייתון, במקום התעסקות ידנית במחרוזות של נתיבים. זה נושא רחב שמצדיק הסבר נפרד, אבל שווה לדעת שהוא קיים כשתגיעו לשם.
מי שרוצה לתרגל את זה על בסיס יציב של לולאות ומחרוזות, שווה לעבור על החומר בקורס התכנות הבסיסי שלנו לפני שקופצים ישר לעבודה עם קבצים.
לסיכום¶
עבודה עם קבצים בפייתון מתחילה תמיד מ-with open, כי זה חוסך לכם דליפות משאב בלי מאמץ. מעבר לזה, זה עניין של לבחור את מצב הפתיחה הנכון ואת שיטת הקריאה שמתאימה לגודל הקובץ שאתם עובדים איתו.