وحدة `io` في بايثون

وحدة `io` في بايثون

تشرح هذه المقالة وحدة io في بايثون۔

سنشرح وحدة io في بايثون مع أمثلة عملية۔

YouTube Video

وحدة io في بايثون

تشكل معالجة الإدخال/الإخراج الأساس لجميع أنواع عمليات البيانات، مثل الملفات والشبكات وإدخال/إخراج البيانات القياسي۔ توفر وحدة io في بايثون مجموعة من الأصناف المجردة التي توحد عمليات الإدخال/الإخراج هذه۔ المفهوم الأساسي لفهم هذه الوحدة هو فكرة "التدفق".۔

ما هو التدفق؟

التدفق هو مسار مجرد لقراءة وكتابة البيانات بشكل متسلسل ومستمر۔

عند قراءة محتوى الملفات بايتاً تلو الآخر أو إرسال واستقبال البيانات عبر الشبكة، يمكن التعامل مع كل هذه العمليات كتدفقات بيانات۔

من خلال تجريد هذه الآلية، يمكن التعامل مع مصادر الإدخال/الإخراج المختلفة مثل الملفات والذاكرة والشبكات من خلال عمليات موحدة كـ القراءة والكتابة۔

توفر وحدة io في بايثون واجهة موحدة للتدفقات، مما يسمح بالتعامل الفعال مع البيانات النصية والثنائية۔

البنية الأساسية لوحدة io

تتبع وحدة io في بايثون بنية هرمية من ثلاث طبقات حسب نوع التدفق۔

  1. الطبقة الخام (RawIOBase)

    تتعامل RawIOBase مع عمليات الإدخال/الإخراج على مستوى البايت الأدنى، مثل موصِّفات ملفات نظام التشغيل والأجهزة۔

  2. الطبقة المؤقتة (BufferedIOBase)

    توفر BufferedIOBase ذاكرة مؤقتة لتحسين كفاءة الإدخال/الإخراج۔ BufferedReader و BufferedWriter هما مثالان نموذجيان۔

  3. طبقة النص (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 أيضًا.۔

YouTube Video