המודול `io` בפייתון
מאמר זה מסביר את המודול io בפייתון.
נסביר את המודול io בפייתון באמצעות דוגמאות מעשיות.
YouTube Video
המודול io בפייתון
עיבוד קלט/פלט מהווה את הבסיס לכל סוגי פעולות הנתונים, כמו קבצים, רשתות וקלט/פלט סטנדרטי. המודול io של פייתון מספק אוסף של מחלקות אבסטרקטיות המאחדות פעולות קלט/פלט אלו. המושג המרכזי להבנת מודול זה הוא הרעיון של "זרם".
מהו זרם נתונים (stream)?
זרם הוא זרימה מופשטת לקריאה וכתיבת נתונים באופן סדרתי ורציף.
כאשר קוראים תוכן של קובץ בייט אחרי בייט או שולחים ומקבלים נתונים ברשת, ניתן לטפל בכל אלו כזרמי נתונים.
על ידי הפשטת מנגנון זה, ניתן לטפל בקבצים, זיכרון ורשתות — מקורות קלט/פלט שונים — באמצעות פעולות משותפות כמו קריאה וכתיבה.
המודול io בפייתון מספק ממשק אחיד לזרמים, ומאפשר טיפול יעיל גם בנתונים טקסטואליים וגם בינאריים.
המבנה הבסיסי של מודול io
למודול io היררכיה בת שלוש שכבות לפי סוגי הזרמים.
-
שכבת גולמית (
RawIOBase)RawIOBaseמטפל בקלט/פלט ברמת הבייט הנמוכה ביותר, כגון מזהי קבצים של מערכת ההפעלה והתקנים. -
שכבת מטמון (
BufferedIOBase)BufferedIOBaseמספק מטמון (Buffer) לשיפור יעילות הקלט/פלט.BufferedReaderו-BufferedWriterהם דוגמאות טיפוסיות. -
שכבת טקסט (
TextIOBase)TextIOBaseממיר רצפים של בייטים למחרוזות ומטפל בקידוד. בדרך כלל, כאשר פותחים קובץ עם הפונקציהopen(), נעשה שימוש ב-TextIOWrapperמשכבה זו.
תודות למבנה זה, מודול io מפריד בבירור בין קלט/פלט טקסטואלי ובינארי, ומאפשר שילובים גמישים.
המבנה הבסיסי של מודול io
RawIOBase מטפל במזהי קבצים של מערכת ההפעלה בשכבה הנמוכה ביותר, BufferedIOBase מוסיף שכבת מטמון מעל, ושכבת TextIOBase שבראש ההיררכיה מטפלת בהמרות מחרוזות.
1import io
2
3# Check the core base classes hierarchy
4print(io.IOBase.__subclasses__())- קוד זה בודק את קבוצת המחלקות האבסטרקטיות היורשות מ-
IOBase. ניתן לראות אתTextIOBase,BufferedIOBase, ו-RawIOBase, מה שמאשר את מבנה ההיררכיה.
io.IOBase: מחלקת הבסיס של הכל
IOBase היא מחלקת בסיס מופשטת לכל אובייקטי הקלט/פלט ומגדירה מתודות משותפות כמו close(), flush(), ו- seekable(). לעתים נדירות משתמשים בה ישירות, ורוב הגישה אליה נעשית דרך מחלקות יורשות.
1import io
2
3f = io.StringIO("data")
4print(f.seekable()) # True
5print(f.readable()) # True
6print(f.writable()) # True
7f.close()- דוגמה זו מראה כי המתודות המשותפות של
IOBaseזמינות גם במחלקות ברמות הגבוהות יותר. המתודותseekable()ו-readable()שימושיות לבדיקת המאפיינים של זרם.
io.RawIOBase: השכבה הנמוכה ביותר
RawIOBase היא השכבה הקרובה ביותר למזהה קובץ של מערכת ההפעלה, ואינה מבצעת מטמון. המימוש הטיפוסי הוא FileIO, שקורא וכותב בייטים.
1import io, os
2
3# Create a low-level FileIO object (no buffering)
4fd = os.open('raw_demo.bin', os.O_RDWR | os.O_CREAT)
5raw = io.FileIO(fd, mode='w+')
6raw.write(b'abc123')
7raw.seek(0)
8print(raw.read(6)) # b'abc123'
9raw.close()FileIOהוא מימוש קונקרטי שלRawIOBase; כל הקריאות והכתיבות מבוצעות כ-bytes. ניתן לשפר את היעילות על ידי שילובו עם השכבה העליונהBufferedIOBase.
io.BufferedIOBase: שכבה אמצעית (עם מטמון)
BufferedIOBase היא שכבה אמצעית שמבצעת מטמון, וכך עושה את הגישה לדיסק ליעילה יותר. המימושים העיקריים הם BufferedReader, BufferedWriter, BufferedRandom, ו-BufferedRWPair.
1import io
2
3# Create a buffered binary stream on top of a BytesIO (simulate file)
4base = io.BytesIO()
5buffered = io.BufferedWriter(base)
6buffered.write(b'Python IO buffering')
7buffered.flush()
8base.seek(0)
9print(base.read()) # b'Python IO buffering'- בדוגמה זו, נתונים הנכתבים באמצעות
BufferedWriterנשמרים זמנית בזיכרון ומועברים לשכבה הנמוכה עם קריאתflush().
דוגמה ל-BufferedReader
BufferedReader הוא זרם בעל מאגר לקריאה בלבד, התומך בקריאה יעילה באמצעות peek() ו־read().
1import io
2
3stream = io.BytesIO(b"1234567890")
4reader = io.BufferedReader(stream)
5print(reader.peek(5)) # b'12345' (non-destructive)
6print(reader.read(4)) # b'1234'
7print(reader.read(3)) # b'567'peek()רק "מציץ" בנתונים ואינו מזיז את המצביע. באמצעות שילובו עםread(), ניתן לשלוט בגמישות במטמון.
io.TextIOBase: שכבת טקסט בלבד
TextIOBase הוא שכבת הפשטה עבור טיפול במחרוזות, שמבצעת קידוד ופענוח באופן פנימי. מחלקה מיישמת טיפוסית היא TextIOWrapper.
1import io
2
3# Wrap a binary stream to handle text encoding
4binary = io.BytesIO()
5text_stream = io.TextIOWrapper(binary, encoding='utf-8')
6text_stream.write("\u3053\u3093\u306B\u3061\u306F")
7text_stream.flush()
8
9# Reset stream position
10binary.seek(0)
11
12# Read bytes once
13data = binary.read()
14
15# Show both raw bytes and decoded text
16print("Raw bytes:", data)
17print("Decoded text:", data.decode('utf-8'))- בדוגמה זו,
TextIOWrapperמקודד את המחרוזת ל-UTF-8 וכותב אותה לזרם הבינארי שמתחתיו.
דוגמה לקריאה עם TextIOWrapper
פענוח מתבצע אוטומטית בזמן הקריאה.
1import io
2
3binary_data = io.BytesIO("Python I/O".encode('utf-8'))
4text_reader = io.TextIOWrapper(binary_data, encoding='utf-8')
5print(text_reader.read()) # 'Python I/O'TextIOWrapperמשמש כמחלקה הבסיסית לקלט/פלט טקסטואלי, ומהווה את התשתית לרוב פעולות הקבצים ברמה גבוהה.
io.StringIO: זרם טקסט בזיכרון
StringIO היא מחלקה המאפשרת לטפל במחרוזות בזיכרון כאילו היו קבצים. היא שימושית לבדיקות קלט/פלט וליצירה זמנית של נתונים.
1import io
2
3text_buf = io.StringIO()
4text_buf.write("In-memory text stream")
5text_buf.seek(0)
6print(text_buf.read()) # 'In-memory text stream'StringIOמאפשר פעולות דמויות קובץ ללא שימוש בדיסק, ונפוץ מאוד בבדיקות יחידה.
io.BytesIO: זרם בינארי בזיכרון
BytesIO היא מחלקת קובץ בזיכרון לטיפול ברצפי בייטים (bytes). היא שימושית למצבים כמו עיבוד בינארי או דחיסת נתונים, כאשר אינך רוצה להשתמש בקבצים.
1import io
2
3buf = io.BytesIO()
4buf.write(b'\x01\x02\x03')
5buf.seek(0)
6print(list(buf.read())) # [1, 2, 3]BytesIOבעלת אותו ממשק כמוBufferedIOBaseוניתן להשתמש בה כתחליף לרבות מממשקי קבצים.
זרמים מותאמים אישית (יצירת מחלקות מקוריות)
המחלקות במודול io ניתנות להרחבה, ומאפשרות ליצור מחלקות זרמים משלך. להלן דוגמה למחלקת משנה של TextIOBase שמבצעת אותיות רישיות לכל הטקסט בזמן כתיבה.
1import io
2
3class UpperTextIO(io.TextIOBase):
4 def __init__(self):
5 self.buffer = ""
6 def write(self, s):
7 self.buffer += s.upper()
8 return len(s)
9
10u = UpperTextIO()
11u.write("hello io")
12print(u.buffer) # "HELLO IO"- כל עוד אתה עומד בחוזה של
TextIOBase, תוכל להגדיר כל התנהגות מותאמת אישית כזו. קל גם להרחיב את הזרמים לשימושים מסוימים, כמו קבצים ורשתות.
סיכום
המודול io מארגן עיבוד קלט/פלט בהיררכיה של מחלקות אבסטרקטיות וקונקרטיות.
RawIOBaseהיא מחלקה לקלט/פלט ברמת בייטים של מערכת ההפעלה.BufferedIOBaseהיא מחלקה שמספקת שכבת מטמון יעילה.TextIOBaseהיא מחלקה שמנהלת קריאה וכתיבה של מחרוזות.StringIOו-BytesIOהן מחלקות המספקות זרמים בזיכרון.
הבנת מחלקות אלה מאפשרת להבין לעומק את מערכת הקלט/פלט של פייתון וליישם אותן לפעולות על קבצים, תקשורת רשת ועיצוב זרמי בדיקה.
תוכלו לעקוב אחר המאמר שלמעלה באמצעות Visual Studio Code בערוץ היוטיוב שלנו. נא לבדוק גם את ערוץ היוטיוב.