2.27. القراءة والكتابة

تقيم الملفات على القرص؛ وتصل إليها Python عبر open()، التي تُرجع كائن ملف تقرأ أساليبه وتكتب البايتات الكامنة.

2.27.1. open والأوضاع

الوسيط الأول هو المسار؛ والثاني هو الوضع -- سلسلة قصيرة تخبر Python كيف سيُستخدم الملف:

  • "r" -- قراءة (افتراضي). يفتح ملفًا موجودًا للقراءة.

  • "w" -- كتابة. ينشئ ملفًا جديدًا أو يقتطع ملفًا موجودًا ليصبح فارغًا.

  • "a" -- إلحاق. يفتح ملفًا للكتابة عند نهايته دون اقتطاع.

  • "b" ملحقة بأيٍّ مما سبق ("rb" و "wb" و "ab") -- الوضع الثنائي. تكون محتويات الملف bytes بدلًا من str.

f = open("notes.txt", "r")
text = f.read()
f.close()

2.27.2. استخدم مدير سياق

النمط أعلاه يسرّب مقبض الملف إذا أطلق أي شيء بين open() و close استثناءً. والحل هو تعليمة with (انظر مدراء السياق):

with open("notes.txt") as f:
    text = f.read()

# f is closed here, even if read() failed

هذا هو الشكل المعياري -- اكتبه بهذه الطريقة في كل مرة.

2.27.3. القراءة

تدعم كائنات الملفات عدة أساليب للقراءة:

  • io.IOBase.read() -- قراءة الملف كاملًا (أو N بايت) وإرجاعه كسلسلة نصية واحدة (أو كائن بايتات).

  • io.IOBase.readline() -- قراءة سطر واحد، بما في ذلك "\n" اللاحقة.

  • التكرار على الملف مباشرةً ينتج الأسطر سطرًا تلو الآخر، باستخدام ذاكرة أقل بكثير من قراءة الملف كله دفعة واحدة.

with open("log.txt") as f:
    for line in f:
        print(line.rstrip())

str.rstrip() تزيل سطر السطر الجديد اللاحق قبل الطباعة كي لا تكون المخرجات مزدوجة التباعد.

2.27.4. الكتابة

افتح الملف في الوضع "w" واستخدم io.IOBase.write():

with open("out.txt", "w") as f:
    f.write("hello\n")
    f.write("world\n")

io.IOBase.write() لا تضيف سطرًا جديدًا -- إذ تكتب بالضبط البايتات (أو الأحرف، في الوضع النصي) التي تمرّرها إليها.

2.27.5. النصي مقابل الثنائي

يفكّ الوضع النصي (الافتراضي، "r" / "w" دون "b") ترميز البايتات الواردة إلى str باستخدام ترميز افتراضي، ويرمّز str الصادرة عائدًا إلى بايتات. استخدمه للإعداد والسجلات و JSON -- أي شيء هو نص.

يتخطّى الوضع الثنائي ("rb" / "wb") خطوة فك الترميز ويُرجع bytes. استخدمه للصور والسجلات المحزومة بهيكل (struct) وملفات التقاط الشبكة -- أي شيء يهمّ فيه كل بايت ولا يكون الملف قابلًا للقراءة البشرية.

2.27.6. سرد الملفات وإزالتها

تكشف وحدة os عمليات نظام الملفات التي ليست على كائن الملف نفسه:

  • os.listdir() -- تُرجع قائمة بالأسماء في دليل.

  • os.remove() -- حذف ملف.

  • os.rename() -- إعادة تسمية ملف.

  • os.stat() -- بيانات وصفية للملف (الحجم، وقت التعديل، ...).

  • os.mkdir() -- إنشاء دليل جديد.

import os

for name in os.listdir("/"):
    print(name)

التقط OSError حول هذه العمليات عندما قد لا يكون الملف أو الدليل موجودًا -- إذ تُعدّ هذه العملية أحد الأماكن الشائعة التي تظهر فيها الاستثناءات في البرامج النصية الحقيقية.