Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
AhmadAlsaadi
GitHub Repository: AhmadAlsaadi/Arabic-python-notebook
Path: blob/master/الفصل السابع-التعامل مع الملفات.ipynb
675 views
Kernel: Python 3 (ipykernel)
import style style._set_css_style("custom.css")

الفصل السابع : التعامل مع الملفات


إن جميع البرامج التي قمنا بكتابتها حتى الآن كانت تتطلب إدخال البيانات يدوياً داخل الكود البرمجي قبل تشغيله. وهذه الطريقة تعتبر بدائية الى حد ما وغير مفيدة خاصةً عندما نرغب في إدخال بيانات جديدة غير التي أدخلناها قبل تشغيل البرنامج. لذلك سوف نتطرق الى معرفة كيفية إدخال البيانات للبرنامج بشكل تفاعلي باستخدام الدالة ()input وكذلك طريقة التعامل مع الملفات من أجل قراءتها أو التعديل عليها وحفظ هذه التعديلات لاستخدامها لاحقاً بعد إغلاق البرنامج.

أهداف الفصل

عند إتمام هذا الفصل يجب أن يكون لديك إلمام بالآتي:

  1. معرفة كيفية استخدام الدالة ()input من أجل إدخال البيانات للبرنامج بشكل تفاعلي.
  2. التعرف على طريقة فتح الملفات النصية.
  3. التعرف على طريقة قراءة البيانات النصية.
  4. التعرف على طرق الكتابة والحفظ على ملف نصي.

إدخال البيانات بشكل تفاعلي

في لغة بايثون يتم تكمين مستخدمي البرنامج من إدخال بياناتهم بعد تشغيل البرنامج بغية معالجتها وتحليلها من خلال استخدام الدالة ()input كما في المثال التالي:
name=input("please enter your name: ") print("Hello ",name)
فالتركيب اللغوي السابق يطلب من المستخدم بعد تشغيله للبرنامج أن يقوم بإدخال قيمة المتغير name وذلك من خلال كتابة ملاحظة أو رسالة يكتبها المبرمج بين قوسي الدالة ()input على شكل نص لترشد المستخدم الى ما يجب عمله. ويبقى البرنامج منتظراً للمستخدم حتى يدخل قيمة ويضغط على زر الإدخال ليكمل بعدها البرنامج تنفيذ ما تبقى من كود برمجي.
يجب ملاحظة أن كل ما يقوم بإدخاله المستخدم من بيانات في هذا التركيب اللغوي يتم التعامل معه على أنه نص. ويمكن التأكد من هذه المعلومة باستخدام الدالة ()type كما في المثال التالي:
num=input("Please enter a number: ") print(type(num))
لاحظ أنه بعد إدخال الرقم 10 والضغط على زر الإدخال طبع لنا البرنامج نوع البيان الذي أدخلناه وهو من النوع النصي “str”. وكمثال آخر لنفرض اننا نريد كتابة برنامج يطلب من المستخدم إدخال قيمتين x وy لكي يقوم بحساب حاصل جمعهما. فمن خلال تعلمنا للتركيب اللغوي السابق يمكن كتابة البرنامجع على النحو التالي:
x=input("please enter a value for x: ") y=input("please enter a value for y: ") sum=x+y print("The sum of x and y = ",sum)
please enter a value for x: 4 please enter a value for y: 5 The sum of x and y = 45
عند تنفيذ البرنامج السابق وإدخال قيمة 5 للمتغير x وقيمة 9 للمتغير y نجد أن هناك مشكلة في البرنامج. فالبرنامج تعامل مع المدخلات على أنها سلسلة نصية وتمت عملية الجمع كما تعلمنا سابقا بتجميع النصوص مع بعضها البعض. يمكن حل هذه المشكلة بتحويل سلسلة النصوص المدخلة الى أرقام عشرية باستخدام الدالة ()float كما في المثال التالي:
x=input("please enter a value for x: ") y=input("please enter a value for y: ") sum=float(x)+float(y) print("The sum of x and y = ",sum)
please enter a value for x: 4 please enter a value for y: 5 The sum of x and y = 9.0

تمارين استكشافية

١- طور البرنامج السابق باستخدام حلقة while بحيث تجعل البرنامج يسأل المستخدم بعد إجراء عملية الجمع عما إذا كان يرغب في إجراء عملية جمع أخرى أو يرغب في إنهاء البرنامج. فإذا كانت الإجابة بـ yes فعندها يقوم بإجراء عملية جمع أُخرى أما إذا كانت الإجابة بـ no فإن البرنامج يطبع رسالة "Good by"؟
٢- قم بكتابة برنامج يطلب من المستخدم تخمين رقم سري أنت تختاره بين العددين 0 و 20 بحيث يقوم البرنامج بإرشاد المستخدم الي الرقم السري بكتابة تلميح في كل مرة يدخل فيها رقماً غير صحيح. فمثلا إذا أدخل المستخدم رقماً أقل من الرقم السري يظهر البرنامج رسالة تخبره بأن يختار رقماً أكبر والعكس صيحيح إذا كان الرقم المدخل أكبر من الرقم السري؟ عندما يصل المستخدم للرقم السري الصحيح يطبع البرنامج رسالة تفيد بذلك وينهي البرنامج؟
٣- طور البرنامج الموجود في تمرين رقم 2 بحيث يعطي البرنامج 3 محاولات فقط للمستخدم للوصول للرقم السري الصحيح؟

فتح الملفات

إن البرامج السابقة لم تكن تمكننا من إدخال البيانات بشكل آلي ولم تكن تمكننا من الإحتفاظ بمخرجات البرنامج بعد أن ينتهي البرنامج من تنفيذ الكود البرمجي. لذلك كان لا بد أن يوجد المبرمجين تركيباً لغوياً يمكننا من التعامل مع الملفات بغرض القراءة منها أو الكتابة عليها. وفي لغة بايثون نجد أن التعامل مع الملفات يتم من خلال استخدام الدالة ()open والتي يكون تركيبها اللغوي على النحو التالي:
open("filename","mode",buffer)

حيث تحتوي الدالة على ثلاثة مدخلات أحدهم الزامي والآخران اختياريان وهي على النحو التالي:

filename : مدخل إلزامي يمثل اسم الملف المطلوب التعامل معه. أذا لم يكن اسم الملف موجود في نفس المجلد الذي يتم من خلاله تشغيل البرنامج فلابد من تحديد مسار الملف حتى يتسنى للبرنامج الوصول للملف. كما يجب ملاحظة أن كتابة اسم و مسار الملف دائما ما يكون على هيئة نص أي بمعنى آخر يجب أن يكون بين علامتي تنصيص.

Mode : مدخل اختياري يمثل نوع العملية المراد تنفيذها على الملف. وعند حذف قيمة هذا المدخل فإن القيمة الافتراضية التي سوف يعتمدها مفسر بايثون هي عملية القراءة "r". والجدول التالي يمثل العمليات الأكثر استخداما عند التعامل مع الملفات:

العملية قراءة ملف كتابة ملف إضافة البيانات الى آخر الملف
mode "r" "w" "a"

buffer : مدخل اختياري يمثل كمية البيانات التي يُراد قراءتها أو كتابتها الى الملف. وعند حذف هذه القيمة عند استخدام الدالة ()open فإن القيمة الافتراضية التي سوف يعتمدها مفسر بايثون هي قراءة كافة محتويات الملف.

من خلال استخدام التركيب السابق يصبح لدينا كائن في ذاكرة الكمبيوتر فقط تم تحديد نوع العملية المراد عملها من خلاله اما اجراء عملية القراءة والكتابة الفعلية لا تتم الا باستخدام دوال خاصة بالقراءة والكتابة والتي سوف نتعرف عليها بشئ من التفصيل في الجزئية التالية.

القراءة من الملفات

يحتوي مجلد الكتاب هذا على مجلد آخر اسمه data يحوي ملفا نصياً اسمه days.txt كتبت فيه مجموعة من البيانات النصية. لنقم بفتح الملف هذا وطباعة ما بداخله من بيانات من خلال كتابة الكود البرمجي التالي:
file_name=open("data/days.txt") data=file_name.read() print(data) file_name.close()
عند تشغيل الكود السابق سوف يقوم مفسر بايثون بإنشاء كائن برمجي داخل الذاكرة يمثل قناة تواصل بين القرص الصلب الذي يحوي الملف ومفسر بايثون ويتم اسناد هذا الكائن للمتغير file_name . لاحظ أننا احتجنا الى كتابة مسار الملف لأن الملف الذي نحن بصدده لا يقع في نفس مجلد الكتاب مباشرة وإنما يوجد في مجلد فرعي اسمه data . كما يجب ملاحظة أن مفسر بايثون تعرف على نوع العملية التي نريد القيام بها على الملف على الرغم من عدم تحديدها في مدخلات الدالة ()open وذلك لأن القيمة الافتراضية لنوع العملية mode هي عملية القراءة "r" كما أشرنا سابقاً. ومن ثم يقوم بتنفيذ عملية قراءة محتيويات الملف من خلال الدالة ()read ويقوم بإسناد محتويات الملف للمتغير data وأخيراً يقوم بطباعة محتويات الملف من خلال الدالة ()print وإغلاق الكائن البرمجي ومسحة من الذاكرة من خلال الدالة ()close.
كما يجب الإشارة الى أن هناك دوال أخرى تقوم بعملية القراءة من ملف ولكن بخصائص تختلف قليلاً عن الدالة ()read. فمثلاً يمكن استخدام الدالة ()readline لقراءة سطر واحد من الملف كما في المثال التالي:
file=open("data/days.txt") line=file.readline() print(line)
Sunday: go to school
كما يمكن قراءة الملف السابق بأكمله باستخدام الدالة ()readlines (لاحظ s الجمع للتفريق بين الدالة السابقة والدالة التي نحن بصددها الآن) بحيث يكون ناتج القراءة عبارة عن قائمة من البيانات كل بيان فيها يمثل محتوى كل سطر من الملف الذي تتم قراءته كما في المثال التالي:
file=open("data/days.txt") lines=file.readlines() print(lines)
['Sunday: go to school\n', 'Monday: play football\n', 'Tuesday: visit mam\n', 'Friday: read a chapter from Quran.']

تمارين استكشافية

1. قم بكتابة برنامج يقرأ من ملف نصي اسمه numbers.txt موجود في نفس المجلد data ويحتوي على الأعداد من 1 الى 10 في السطر الأول و 11 الى 20 في السطر الثاني و 21 الى 30 في السطر الثالث. حاول أن تقرأ محتويات الملف باستخدام الدوال الثلاث السابقة وطباعتها على الشاشة؟
2. حاول التعرف على نوع البيانات الناتجة من عملية القراءة بالدوال الثلاث السابقة باستخدام الدالة ()type؟
3. قم بفتح الملف countries.txt من المجلد data ثم قم بقراءة الملف وطباعة جميع أسماء الدول الموجودة في الملف؟
4. طور البرنامج في التمرين 3 بحيث يقوم بطباعة الدول التي يزيد عدد حروفها عن 10 احرف؟
5. طور البرنامج في التمرين 3 بحيث يقوم بطباعة الدول التي يقل عدد حروفها عن 6 احرف؟

الكتابة الى الملفات

لنفرض الآن أننا نريد الكتابة على ملف ماذا بوسعنا أن نغير في الدالة ()open للقيام بهذه المهمة؟ في حقيقة الأمر إن الكتابة على ملف تتطلب فقط القيام بتغيير قيمة النمط (mode) الافتراضية في الدالة ()open والتي تمثل المدخل الثاني الذي يلي اسم الملف كما في المثال التالي:
file=open("data/weeks.txt","w")
عند كتابة "w" كمدخل ثاني في الدالة ()open فإن مفسر بايثون سوف يقوم بإنشاء كائن أرتباط للكتابة بدلاً من كائن إرتباط للقراءة. لكن يجب ملاحظة أن هناك اختلاف بسيط بين نمطي الكتابة والقراءة. فنمط الكتابة عند عدم وجود الملف المحدد فإن مفسر بايثون يقوم بإنشائه تلقائيا بينما نمط القراءة يعطي رسالة بوجود خطأ في حال عدم العثور على الملف.
ودالة الكتابة في بايثون هي ()write. ويتم التعامل معها تقريباً بنفس الطريقة التي استخدمناها مع دالة القراءة كما هو موضح في المثال التالي:
file=open("data/weeks.txt","w") file.write("1st week 2nd week 3rd week 4th week") file.close()
فبعد إنشاء كائن الإرتباط للكتابة file نستخدم الدالة ()write لتنفيذ عملية الكتابة على الملف والتي هي هنا عبارة عن نص وضع بين قوسي الدالة ()write. ويمكن كذلك استخدام الدالة ()writelines وذلك لكتابة قائمة من البيانات كما في المثالين التاليين:
file=open("data/greeting.txt","w") file.write("you reached good level in python") file.close()
file=open("data/greeting.txt","w") file.writelines(["Welcome ","to ", "python ", "world!"]) file.close()
يجب ملاحظة أن فتح ملف بغرض الكتابة عليه يختلف بحسب النمط المدخل. فالنمط "w" يعنى مسح محتويات الملف السابقة إن وجدت والكتابة على الملف من بدايته. أما إذا استخدمنا النمط "a" كمدخل ثاني في الدالة ()open فإن ذلك يعنى أن محتويات الملف السابقة لا يتم مسحها وإنما تتم الكتابة من حيث ما أنتهى محتوى الملف السابق. وهناك أنماط أخرى لا يسعنا الحديث عنها هنا ويمكن البحث عنها من خلال محركات البحث للاستزادة.

تمارين استكشافية

1- لتأكد أن عمليتي الكتابة في المثالين السابقين تمتا بشكل صحيح. قم بتنفيذ كل كود ومن ثم قم بكتابة كود برمجي آخر يقوم بقراءة وطباعة ما تم كتابته؟
2- قم بفتح الملف countries.txt وحاول كتابة عدد الدول في نهاية الملف؟
إن فتح ملف سواءً للقراءة أو الكتابة بالطريقة السابقة قد يسبب إشكالية في نفاذ جزء من مساحة الذاكرة وذلك لأن الملف الذي تم فتحه سوف يظل في ذاكرة الكمبيوتر حتى يتم إغلاقه. لذلك فإن استخدام الطريقة السابقة للتعامل مع الملفات يتطلب تنظيف الذاكرة بعد الإنتهاء من عملية القراءة أو الكتابة باستخدام الدالة ()close كما في المثال التالي:
file=open("data/weeks.txt") content=file.read() print(content) file.close()
ولتلافي نسيان إغلاق الملفات بعد الإنتهاء من إجراء العمليات عليها يمكن استخدام تركيب لغوي آخر في لغة بايثون يعتمد على استخدام البادئة with والذي من خلاله يقوم مفسر بايثون بإغلاق الملف المفتوح بمجرد الانتهاء من هذه المهمة كما في المثال التالي:
with open("data/weeks.txt") as file: content=file.read() print(content)
لاحظ أن في المثال السابق تم استخدام الاتي:
• بدء التركيب اللغوي باستخدام كلمة with.
• استخدام كلمة as لإسناد كائن الربط الى المتغير file.
• استخدام النقطتين فوق بعض ":" عند نهاية السطر الأول.
• ترك مسافة في الأسطر التي تلي السطر الأول للقيام بالعمليات المطلوبة على الملف المفتوح.
• يتم اقفال كائن الإرتباط بعد الإنتهاء من آخر سطر في الأسطر المبدوءة بترك مسافة.

تمارين استكشافية

1- قم بإعادة كتابة تمارين القراءة والكتابة السابقة باستخدام التركيب اللغوي with؟