وحدة `io` في بايثون
تشرح هذه المقالة وحدة io في بايثون۔
سنشرح وحدة io في بايثون مع أمثلة عملية۔
YouTube Video
وحدة io في بايثون
تشكل معالجة الإدخال/الإخراج الأساس لجميع أنواع عمليات البيانات، مثل الملفات والشبكات وإدخال/إخراج البيانات القياسي۔ توفر وحدة io في بايثون مجموعة من الأصناف المجردة التي توحد عمليات الإدخال/الإخراج هذه۔ المفهوم الأساسي لفهم هذه الوحدة هو فكرة "التدفق".۔
ما هو التدفق؟
التدفق هو مسار مجرد لقراءة وكتابة البيانات بشكل متسلسل ومستمر۔
عند قراءة محتوى الملفات بايتاً تلو الآخر أو إرسال واستقبال البيانات عبر الشبكة، يمكن التعامل مع كل هذه العمليات كتدفقات بيانات۔
من خلال تجريد هذه الآلية، يمكن التعامل مع مصادر الإدخال/الإخراج المختلفة مثل الملفات والذاكرة والشبكات من خلال عمليات موحدة كـ القراءة والكتابة۔
توفر وحدة io في بايثون واجهة موحدة للتدفقات، مما يسمح بالتعامل الفعال مع البيانات النصية والثنائية۔
البنية الأساسية لوحدة io
تتبع وحدة io في بايثون بنية هرمية من ثلاث طبقات حسب نوع التدفق۔
-
الطبقة الخام (
RawIOBase)تتعامل
RawIOBaseمع عمليات الإدخال/الإخراج على مستوى البايت الأدنى، مثل موصِّفات ملفات نظام التشغيل والأجهزة۔ -
الطبقة المؤقتة (
BufferedIOBase)توفر
BufferedIOBaseذاكرة مؤقتة لتحسين كفاءة الإدخال/الإخراج۔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 على قناتنا على YouTube.۔ يرجى التحقق من القناة على YouTube أيضًا.۔