اذهب إلى المحتوى

تعلّمنا في المقال السابق كيفية استخراج النص من مستندات PDF ووورد التي تُعَدّ ملفاتٍ بتنسيق ثنائي، إذ تتطلب هذه الملفات استخدام وحدات بايثون Python خاصة للوصول إلى بياناتها، بينما تُعَد ملفات CSV و JSON مجرد ملفاتٍ نصية عادية، حيث يمكنك عرضها في محرر نصوص مثل محرر النصوص Mu. تحتوي لغة بايثون مسبقًا على وحدتين خاصتين هما csv و json، حيث توفّر كلٌّ منهما دوالًا لمساعدتك في العمل مع تنسيقات هذه الملفات.

يرمز الاختصار CSV إلى "القيم المفصولة بفواصل Comma-separated Values"، وملفات CSV هي جداول بيانات بسيطة مُخزَّنة بوصفها ملفات نصية عادية، وتسهّل وحدة csv في بايثون تحليل ملفات CSV. يُنطَق الاختصار JSON بالطريقة "JAY-sawn" أو "Jason"، ولكن لا يهم كيف تنطقها لأن الناس سيقولون أنك تنطقها بطريقة خاطئة في كلتا الحالتين، وهو تنسيق يخزن المعلومات بوصفها شيفرة جافاسكربت مصدرية في ملفات نصية عادية. JSON هو اختصار لترميز الكائنات باستعمال جافاسكربت JavaScript Object Notation، ولكن لا تحتاج إلى معرفة لغة البرمجة جافاسكربت لاستخدام ملفات JSON، ولكن من المفيد معرفة تنسيق ملفات JSON لأنه يُستخدَم في العديد من تطبيقات الويب.

وحدة CSV

يمثّل كل سطر في ملف CSV صفًا في جدول البيانات، حيث تفصل الفواصل بين الخلايا الموجودة في الصف، فمثلًا سيبدو جدول البيانات example.xlsx في ملف CSV كما يلي:

4/5/2015 13:34,Apples,73
4/5/2015 3:41,Cherries,85
4/6/2015 12:46,Pears,14
4/8/2015 8:59,Oranges,52
4/10/2015 2:07,Apples,152
4/10/2015 18:10,Bananas,23
4/10/2015 2:40,Strawberries,98

سنستخدم هذا الملف لأمثلة الصدفة التفاعلية Interactive Shell الموجودة في هذا المقال، حيث يمكنك تنزيله أو إدخال النص في محرّر النصوص وحفظه بالاسم example.csv.

تُعَد ملفات CSV بسيطة، ولا تحتوي على العديد من ميزات جدول بيانات إكسل Excel مثل الميزات التالية:

  • ليس لديها أنواع لقيمها، فكل شيء فيها هو سلسلة نصية String.
  • ليس لديها إعدادات لحجم الخط أو لونه.
  • ليس لديها أوراق عمل متعددة.
  • لا يمكنها تحديد عرض الخلية وارتفاعها.
  • لا يمكنها أن تحتوي على خلايا مدموجة.
  • لا يمكنها تضمين الصور أو المخططات.

ميزة ملفات CSV الأساسية هي البساطة، إذ تدعمها العديد من أنواع البرامج على نطاقٍ واسع، ويمكن عرضها في برامج تحرير النصوص بما في ذلك محرّر النصوص Mu، وتُعَد ملفات CSV طريقةً مباشرة لتمثيل بيانات جداول البيانات. تنسيق ملف CSV هو مجرد ملف نصي يحتوي على قيم يُفصَل بينها بفواصل.

تُعَد ملفات CSV مجرد ملفات نصية، لذا قد تقرأها بوصفها سلسلة نصية ثم تعالج تلك السلسلة باستخدام التقنيات التي تعلمتها سابقًا في مقالٍ سابق، فمثلًا يمكنك استدعاء التابع split(',')‎ في كل سطر من النص للحصول على القيم المفصولة بفواصل بوصفها قائمةً من السلاسل النصية، لأن كل خلية في ملف CSV مفصولة عن غيرها من الخلايا بفاصلة، ولكن لا تمثّل جميع الفواصل في ملف CSV هذه الحدود بين الخلايا، إذ تحتوي ملفات CSV أيضًا على مجموعة خاصة بها من محارف الهروب Escape Characters للسماح بتضمين الفواصل والمحارف الأخرى كجزء من القيم، حيث لا يعالج التابع split()‎ محارف الهروب. يجب عليك دائمًا استخدام وحدة csv لقراءة ملفات CSV وكتابتها بسبب هذه المخاطر المحتملة.

كائنات reader

يمكنك قراءة البيانات من ملف CSV باستخدام وحدة csv من خلال إنشاء كائن reader الذي يتيح لك التكرار على الأسطر الموجودة في ملف CSV. أدخِل ما يلي في الصدفة التفاعلية مع وضع الملف example.csv في مجلد العمل الحالي:

 >>> import csv
 >>> exampleFile = open('example.csv')
 >>> exampleReader = csv.reader(exampleFile)
 >>> exampleData = list(exampleReader)
 >>> exampleData
   [['4/5/2015 13:34', 'Apples', '73'], ['4/5/2015 3:41', 'Cherries', '85'],
   ['4/6/2015 12:46', 'Pears', '14'], ['4/8/2015 8:59', 'Oranges', '52'],
   ['4/10/2015 2:07', 'Apples', '152'], ['4/10/2015 18:10', 'Bananas', '23'],
   ['4/10/2015 2:40', 'Strawberries', '98']]

تحتوي لغة بايثون على وحدة csv، لذا يمكننا استيرادها ➊ دون الحاجة إلى تثبيتها أولًا. يمكنك قراءة ملف CSV باستخدام وحدة csv من خلال فتحه أولًا باستخدام الدالة open()‎ ➋ كما تفعل مع أيّ ملف نصي آخر، ولكننا لا نستدعي التابع read()‎ أو readlines()‎ لكائن File الذي تعيده الدالة open()‎، بل نمرّره إلى الدالة csv.reader()‎ ➌، مما يؤدي إلى إعادة كائن reader لتستخدمه. لاحظ أنك لا تمرّر السلسلة النصية التي تمثّل اسم الملف مباشرةً إلى الدالة csv.reader()‎.

أكثر الطرق مباشرةً للوصول إلى القيم الموجودة في كائن reader هي تحويله إلى قائمة بايثون عادية من خلال تمريره إلى التابع list()‎ ➍، حيث يعيد استخدام التابع list()‎ لكائن reader قائمةً من القوائم، والتي يمكنك تخزينها في متغير مثل المتغير exampleData الذي يؤدي إدخاله في الصدفة إلى عرض قائمةٍ القوائم ➎.

أصبح لديك ملف CSV بوصفه قائمةً من القوائم، ويمكنك الآن الوصول إلى القيمة الموجودة في صف وعمود محدّد باستخدام التعبير exampleData[row][col]‎، حيث يكون row هو فهرس إحدى القوائم الموجودة في المتغير exampleData، ويكون col هو فهرس العنصر الذي تريده من تلك القائمة. لندخِل الآن ما يلي في الصدفة التفاعلية:

>>> exampleData[0][0]
'4/5/2015 13:34'
>>> exampleData[0][1]
'Apples'
>>> exampleData[0][2]
'73'
>>> exampleData[1][1]
'Cherries'
>>> exampleData[6][1]
'Strawberries'

لاحظ أن exampleData[0][0]‎ ينتقل إلى القائمة الأولى ويعطي السلسلة النصية الأولى، وينتقل exampleData[0][2]‎ إلى القائمة الأولى ويعطينا السلسلة النصية الثالثة وإلخ.

قراءة البيانات من كائنات reader في حلقة for

يجب استخدام كائن reader في حلقة for بالنسبة لملفات CSV الكبيرة، مما يؤدي إلى تجنّب تحميل الملف بأكمله إلى الذاكرة دفعة واحدة، إذًا لندخِل ما يلي مثلًا في الصدفة التفاعلية:

>>> import csv
>>> exampleFile = open('example.csv')
>>> exampleReader = csv.reader(exampleFile)
>>> for row in exampleReader:
        print('Row #' + str(exampleReader.line_num) + ' ' + str(row))

Row #1 ['4/5/2015 13:34', 'Apples', '73']
Row #2 ['4/5/2015 3:41', 'Cherries', '85']
Row #3 ['4/6/2015 12:46', 'Pears', '14']
Row #4 ['4/8/2015 8:59', 'Oranges', '52']
Row #5 ['4/10/2015 2:07', 'Apples', '152']
Row #6 ['4/10/2015 18:10', 'Bananas', '23']
Row #7 ['4/10/2015 2:40', 'Strawberries', '98']

استوردنا وحدة csv وأنشأنا كائن reader من ملف CSV، ويمكنك بعد ذلك التكرار ضمن حلقة على الصفوف الموجودة في كائن reader، حيث يمثل كلّ صف قائمةً من القيم، وتمثّل كل قيمة خلية. يطبع استدعاء الدالة print()‎ رقم الصف الحالي ومحتوياته، ويمكنك الحصول على رقم الصف من خلال استخدام المتغير line_num الخاص بكائن reader، والذي يحتوي على رقم السطر الحالي. يمكن تكرار كائن reader مرة واحدة فقط، لذا يجب استدعاء الدالة csv.reader لإنشاء كائن reader وإعادة قراءة ملف CSV.

كائنات writer

يتيح كائن writer كتابة البيانات في ملف CSV، حيث يمكنك استخدام الدالة csv.writer()‎ لإنشاء هذا الكائن. لندخِل الآن ما يلي في الصدفة التفاعلية:

   >>> import csv
 >>> outputFile = open('output.csv', 'w', newline='')
 >>> outputWriter = csv.writer(outputFile)
   >>> outputWriter.writerow(['spam', 'eggs', 'meat', 'beef'])
   21
   >>> outputWriter.writerow(['Hello, world!', 'eggs', 'meat', 'beef'])
   32
   >>> outputWriter.writerow([1, 2, 3.141592, 4])
   16
   >>> outputFile.close()

استدعِ أولًا الدالة open()‎ ومرّر لها القيمة 'w' لفتح الملف في وضع الكتابة ➊، مما يؤدي إلى إنشاء الكائن الذي يمكنك بعد ذلك تمريره إلى الدالة csv.writer()‎ ➋ لإنشاء كائن writer.

يجب أيضًا في نظام ويندوز تمرير سلسلة نصية فارغة لوسيط الكلمات المفتاحية Keyword Argument الذي هو newline للدالة open()‎، وإذا نسيت ضبط الوسيط newline، فستكون الصفوف في الملف output.csv مزدوجة المسافات كما هو موضّح في الشكل التالي:

01 000110

إذا نسيت وسيط الكلمات المفتاحية newline=''‎ في الدالة open()‎، فسيكون ملف CSV مزدوج المسافة

يأخذ التابع writerow()‎ الخاص بكائنات writer وسيطًا من نوع قائمة، حيث تُوضَع كل قيمة من هذه القائمة في خليتها الخاصة في ملف CSV الناتج، ويعيد هذا التابع عدد المحارف المكتوبة في الملف لهذا الصف بما في ذلك محارف السطر الجديد.

ينتج عن الشيفرة البرمجية السابقة ملف output.csv الذي يبدو كما يلي:

spam,eggs,meat,beef
"Hello, world!",eggs,meat,beef
1,2,3.141592,4

لاحظ كيف يهرّب الكائن writer تلقائيًا الفاصلة الموجودة في القيمة ‎'Hello, world!'‎ مع علامات الاقتباس المزدوجة في ملف CSV، إذ توفّر وحدة csv عليك الاضطرار إلى معالجة هذه الحالات الخاصة بنفسك.

وسطاء الكلمات المفتاحية delimiter و lineterminator

لنفترض أنك تريد الفصل بين الخلايا باستخدام محرف جدولة Tab بدلًا من الفاصلة وتريد أن تكون الصفوف ذات مسافات مزدوجة، لندخِل مثلًا ما يلي في الصدفة التفاعلية:

   >>> import csv
   >>> csvFile = open('example.tsv', 'w', newline='')
 >>> csvWriter = csv.writer(csvFile, delimiter='\t', lineterminator='\n\n')
   >>> csvWriter.writerow(['apples', 'oranges', 'grapes'])
   24
   >>> csvWriter.writerow(['eggs', 'meat', 'beef'])
   17
   >>> csvWriter.writerow(['spam', 'spam', 'spam', 'spam', 'spam', 'spam'])
   32
   >>> csvFile.close()

يؤدي ذلك إلى تغيير محارف المحدِّد Delimiter والفاصل بين السطور Line Terminator في ملفك، فالمحدِّد هو المحرف الذي يظهر بين الخلايا في الصف، والمحدِّد الافتراضي لملف CSV هو الفاصلة، بينما يكون الفاصل بين السطور هو المحرف الذي يأتي في نهاية الصف، فالفاصل بين السطور الافتراضي هو محرف السطر الجديد. يمكنك تغيير هذه المحارف إلى قيم مختلفة باستخدام وسطاء الكلمات المفتاحية Keyword Arguments التي هي delimiter و lineterminator باستخدام الدالة csv.writer()‎.

يؤدي تمرير الوسطاء delimiter='\t'‎ و lineterminator='\n\n'‎ ➊ إلى تغيير المحرف بين الخلايا إلى محرف الجدولة والمحرف بين الصفوف إلى محرفي سطر جديد. نستدعي بعد ذلك الدالة ‎writerow()‎ ثلاث مرات لتعطينا ثلاثة صفوف.

ينتج عن ذلك ملف بالاسم example.tsv يحتوي ما يلي:

apples  oranges grapes

eggs    meat   beef

spam    spam    spam    spam    spam    spam

فصلنا بين الخلايا بمحارف جدولة، وبالتالي سنستخدم امتداد الملف ‎.tsv للقيم المفصول بينها بمحارف جدولة.

كائنات DictReader و DictWriter الخاصة بملفات CSV

من الأسهل العمل مع كائنات DictReader و DictWriter بدلًا من كائنات reader و writer بالنسبة لملفات CSV التي تحتوي على صفوف الترويسات، إذ تقرأ وتكتب كائنات reader و writer صفوف ملف CSV باستخدام القوائم، وتطبّق كائنات DictReader و DictWriter الخاصة بملفات CSV الوظائف نفسها ولكن باستخدام القواميس Dictionaries، وتستخدم الصف الأول من ملف CSV بوصفها مفاتيحًا لهذه القواميس.

نزّل الملف exampleWithHeader.csv الذي هو الملف example.csv نفسه باستثناء أنه يحتوي على ترويسات الأعمدة Timestamp و Fruit و Quantity في الصف الأول. أدخِل ما يلي في الصدفة التفاعلية لقراءة هذا الملف:

>>> import csv
>>> exampleFile = open('exampleWithHeader.csv')
>>> exampleDictReader = csv.DictReader(exampleFile)
>>> for row in exampleDictReader:
...     print(row['Timestamp'], row['Fruit'], row['Quantity'])
...
4/5/2015 13:34 Apples 73
4/5/2015 3:41 Cherries 85
4/6/2015 12:46 Pears 14
4/8/2015 8:59 Oranges 52
4/10/2015 2:07 Apples 152
4/10/2015 18:10 Bananas 23
4/10/2015 2:40 Strawberries 98

يضبط الكائنُ DictReader ضمن الحلقة الصفَّ row على كائن القاموس مع المفاتيح المشتقة من الترويسات الموجودة في الصف الأول، ولكنه يَضبط الصف row على الكائن OrderedDict الذي يمكنك استخدامه بالطريقة نفسها لاستخدام القاموس، ولكننا لن نشرح الفرق بين هاتين الطريقتين في هذا المقال. يعني استخدام الكائن DictReader أنك لا تحتاج إلى شيفرة برمجية إضافية لتخطي معلومات ترويسة الصف الأول، لأن الكائن DictReader يفعل ذلك نيابةً عنك.

إذا حاولتَ استخدام كائنات DictReader مع الملف example.csv الذي لا يحتوي على ترويسات أعمدة في الصف الأول، فسيستخدم كائن DictReader مفاتيح القاموس ‎'4/5/2015 13:34'‎ و 'Apples' و '73'، حيث يمكننا تجنب ذلك من خلال تزويد الدالة DictReader()‎ بوسيطٍ ثانٍ يحتوي على أسماء الترويسات التي تريدها:

>>> import csv
>>> exampleFile = open('example.csv')
>>> exampleDictReader = csv.DictReader(exampleFile, ['time', 'name',
'amount'])
>>> for row in exampleDictReader:
...     print(row['time'], row['name'], row['amount'])
...
4/5/2015 13:34 Apples 73
4/5/2015 3:41 Cherries 85
4/6/2015 12:46 Pears 14
4/8/2015 8:59 Oranges 52
4/10/2015 2:07 Apples 152
4/10/2015 18:10 Bananas 23
4/10/2015 2:40 Strawberries 98

لا يحتوي الصف الأول من الملف example.csv على أيّ نص لعناوين الأعمدة، لذا أنشأنا عناوينا الخاصة 'time' و 'name' و 'amount'.

تستخدم كائنات DictWriter أيضًا القواميس لإنشاء ملفات CSV. إذا أردتَ أن يحتوي ملفك على صف الترويسات، فاكتب هذا الصف من خلال استدعاء الدالة ‎writeheader()‎، وإلّا فتخطى استدعاء هذه الدالة لحذف صف الترويسات من الملف. اكتب بعد ذلك كل صف من صفوف الملف CSV باستخدام استدعاء التابع writerow()‎ مع تمرير قاموسٍ يستخدم الترويسات بوصفها مفاتيحًا ويحتوي على البيانات المراد كتابتها في الملف.

>>> import csv
>>> outputFile = open('output.csv', 'w', newline='')
>>> outputDictWriter = csv.DictWriter(outputFile, ['Name', 'Pet', 'Phone'])
>>> outputDictWriter.writeheader()
>>> outputDictWriter.writerow({'Name': 'Alice', 'Pet': 'cat', 'Phone': '555-
1234'})
20
>>> outputDictWriter.writerow({'Name': 'Bob', 'Phone': '555-9999'})
15
>>> outputDictWriter.writerow({'Phone': '555-5555', 'Name': 'Carol', 'Pet':
'dog'})
20
>>> outputFile.close()

يبدو الملف output.csv الذي تنشئه الشيفرة البرمجية السابقة كما يلي:

Name,Pet,Phone
Alice,cat,555-1234
Bob,,555-9999
Carol,dog,555-5555

لاحظ أن ترتيب أزواج القيمة-المفتاح key-value في القواميس التي مرّرتها إلى الدالة writerow()‎ غير مهم، فهي مكتوبة بترتيب المفاتيح المعطاة إلى الدالة DictWriter()‎، فمثلًا لا يزال رقم الهاتف يظهر في آخر الخرج بالرغم من أنك مرّرتَ المفتاح Phone وقيمته قبل مفاتيح وقيم Name و Pet في الصف الرابع. لاحظ أيضًا أن أيّ مفاتيح مفقودة مثل 'Pet' في {'Name': 'Bob', 'Phone': '555-9999'} ستكون ببساطة فارغة في ملف CSV.

تطبيق عملي: إزالة الترويسة من ملفات CSV

لنفترض أن لديك مهمة مملة تتمثل في إزالة السطر الأول من عدة مئات من ملفات CSV، إذ قد تدخل هذه الملفات في عملية آلية تتطلب البيانات فقط وليس الترويسات الموجودة في أعلى الأعمدة، حيث يمكنك فتح كل ملف في إكسل وحذف الصف الأول، ثم تعيد حفظ الملف، ولكن قد يستغرق ذلك ساعات، إذًا لنكتب برنامجًا ينفّذ هذه المهمة بدلًا من ذلك.

يجب أن يفتح البرنامج كل ملفٍ امتداده ‎.csv في مجلد العمل الحالي، ويقرأ محتويات ملف CSV، ثم يعيد كتابة المحتويات بدون الصف الأول في ملف يحمل الاسم نفسه، مما يؤدي إلى وضع المحتويات الجديدة لملف CSV بدون الترويسات مكان المحتويات القديمة.

ملاحظة: تأكد من إنشاء نسخة احتياطية للملفات أولًا عندما تكتب برنامجًا يعدّل الملفات، فأنت لا تريد مسح ملفاتك الأصلية عن طريق الخطأ في حالة عدم عمل البرنامج بالطريقة التي تتوقعها.

إليك الخطوات العامة التي سيطبّقها برنامجك:

  1. البحث عن جميع ملفات CSV في مجلد العمل الحالي.
  2. قراءة المحتويات الكاملة لكل ملف.
  3. كتابة المحتويات مع تخطي السطر الأول في ملف CSV جديد.

ولكن سيحتاج برنامجك إلى تطبيق الخطوات التالية من ناحية الشيفرة البرمجية:

  1. المرور على قائمة الملفات باستخدام التابع os.listdir()‎ مع تخطي الملفات التي ليست ملفات CSV.
  2. إنشاء كائن reader الخاص بوحدة CSV وقراءة محتويات الملف باستخدام السمة Attribute التي هي line_num لمعرفة السطر الذي يجب تخطيه.
  3. إنشاء كائن writer الخاص بوحدة CSV وكتابة بيانات القراءة في الملف الجديد.

افتح نافذة محرّر جديدة لإنشاء ملف جديد واحفظه بالاسم removeCsvHeader.py لهذا المشروع.

الخطوة الأولى: المرور على جميع ملفات CSV

أول شيء يجب على برنامجك فعله هو المرور على قائمة جميع أسماء ملفات CSV الموجودة في مجلد العمل الحالي، لذا اجعل الملف removeCsvHeader.py يبدو كما يلي:

#! python3
# removeCsvHeader.py - إزالة الترويسات من جميع ملفات‫ CSV الموجودة في مجلد العمل الحالي

import csv, os

os.makedirs('headerRemoved', exist_ok=True)

# المرور ضمن حلقة على جميع الملفات الموجودة في مجلد العمل الحالي
for csvFilename in os.listdir('.'):
     if not csvFilename.endswith('.csv'):
       continue    # تخطي الملفات التي ليست ملفات‫ CSV

     print('Removing header from ' + csvFilename + '...')

     # ‫قراءة ملف CSV مع تخطي الصف الأول

     # ‫كتابة ملف CSV

يؤدي استدعاء التابع os.makedirs()‎ إلى إنشاء المجلد headerRemoved الذي سنكتب فيه جميع ملفات CSV التي ليس لها ترويسات. ستقودك حلقة for التي نكررها على التابع os.listdir('.')‎ إلى هذه النتيجة جزئيًا، ولكنها ستتكرر على جميع الملفات الموجودة في مجلد العمل، لذلك يجب إضافة بعض الشيفرة البرمجية في بداية الحلقة التي تتخطى أسماء الملفات التي لا تنتهي بالامتداد ‎.csv. تجعل التعليمة continueحلقة for تنتقل إلى اسم الملف التالي عندما تصل إلى ملف ليس ملف CSV.

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

الخطوة الثانية: قراءة ملف CSV

لا يزيل البرنامج السطر الأول من ملف CSV، بل ينشئ نسخةً جديدة من ملف CSV بدون السطر الأول، وستحل النسخة محل الملف الأصلي لأن اسم ملف النسخة هو اسم الملف الأصلي نفسه.

سيحتاج برنامجك إلى طريقة لتعقّب المرور على الصف الأول حاليًا، لذا أضِف ما يلي إلى الملف removeCsvHeader.py:

#! python3
# removeCsvHeader.py - إزالة الترويسات من جميع ملفات‫ CSV الموجودة في مجلد العمل الحالي

--snip--

    # ‫قراءة ملف CSV مع تخطي الصف الأول
    csvRows = []
    csvFileObj = open(csvFilename)
    readerObj = csv.reader(csvFileObj)
    for row in readerObj:
        if readerObj.line_num == 1:
            continue    # تخطي الصف الأول
        csvRows.append(row)
    csvFileObj.close()

    # ‫كتابة ملف CSV

يمكن استخدام السمة line_num الخاصة بكائن reader لتحديد السطر الموجود في ملف CSV الذي يقرأه حاليًا، حيث توجد حلقة for أخرى للمرور على الصفوف التي يعيدها كائن reader الخاص بوحدة CSV، وستُلحَق جميع الصفوف باستثناء الصف الأول بالقائمة csvRows.

تتحقق الشيفرة البرمجية السابقة مما إذا كان readerObj.line_num مضبوطًا على القيمة 1 أثناء تكرار حلقة for على كل صف. إذا كان ذلك صحيحًا، فستُنفَّذ تعليمة continue للانتقال إلى الصف التالي دون إلحاقه بالقائمة csvRows، وستكون قيمة الشرط False دائمًا بالنسبة لكل صفٍ لاحق، وسيُلحَق هذا الصف بالقائمة csvRows.

الخطوة الثالثة: كتابة ملف CSV بدون الصف الأول

أصبحت القائمة csvRows تحتوي على كافة الصفوف باستثناء الصف الأول، ويجب الآن كتابة هذه القائمة في ملف CSV الموجود في المجلد headerRemoved. أضِف ما يلي إلى الملف removeCsvHeader.py:

   #! python3
   # removeCsvHeader.py - إزالة الترويسات من جميع ملفات‫ CSV الموجودة في مجلد العمل الحالي

   --snip--

   # المرور ضمن حلقة على جميع الملفات الموجودة في مجلد العمل الحالي
 for csvFilename in os.listdir('.'):
       if not csvFilename.endswith('.csv'):
           continue    #  تخطي الملفات التي ليست ملفات‫ CSV

       --snip--

       #  ‫كتابة ملف CSV
       csvFileObj = open(os.path.join('headerRemoved', csvFilename), 'w',
                    newline='')
       csvWriter = csv.writer(csvFileObj)
       for row in csvRows:
           csvWriter.writerow(row)
       csvFileObj.close()

يكتب الكائن writer الخاص بوحدة CSV القائمة الناتجة في ملف CSV موجود ضمن المجلد headerRemoved باستخدام المتغير csvFilename الذي استخدمناه أيضًا في كائن reader الخاص بوحدة CSV، مما يؤدي إلى الكتابة فوق الملف الأصلي. نمر بعد إنشاء الكائن writer على القوائم الفرعية المُخزَّنة في القائمة csvRows ونكتب كل قائمة فرعية في الملف. تنتقل حلقة for الخارجية ➊ إلى اسم الملف التالي من os.listdir('.')‎ بعد تنفيذ الشيفرة البرمجية، وسيكتمل البرنامج عند الانتهاء من تلك الحلقة.

اختبر برنامجك من خلال تنزيل الملف المضغوط removeCsvHeader.zip وفك ضغطه في مجلدٍ ما، ثم شغّل البرنامج removeCsvHeader.py في هذا المجلد، وسيكون الخرج كما يلي:

Removing header from NAICS_data_1048.csv...
Removing header from NAICS_data_1218.csv...
--snip--
Removing header from NAICS_data_9834.csv...
Removing header from NAICS_data_9986.csv…

يجب أن يطبع هذا البرنامج اسم ملفٍ في كل مرة يزيل فيها السطر الأول من ملف CSV.

أفكار لبرامج مماثلة

تشبه البرامجُ التي يمكنك كتابتها لملفات CSV أنواعَ البرامج التي يمكنك كتابتها لملفات إكسل، لأنهما ملفات جداول بيانات، حيث يمكنك كتابة برامج تنفّذ ما يلي:

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

JSON وواجهات برمجة التطبيقات API

يُعَد ترميز الكائنات باستعمال جافاسكربت JavaScript Object Notation -أو JSON اختصارًا- طريقةً شائعة لتنسيق البيانات بوصفها سلسلة نصية واحدة يمكن أن يقرأها البشر، وهو الطريقة الأصيلة التي تكتب بها برامج جافاسكربت هياكلَ البيانات الخاصة بها وتشبه ما ستنتجه دالة pprint()‎ في بايثون. لست بحاجةٍ لمعرفة لغة جافاسكربت لتتمكّن من التعامل مع البيانات المكتوبة بتنسيق JSON.

إليك مثال للبيانات المكتوبة بتنسيق JSON:

{"name": "Zophie", "isCat": true,
 "miceCaught": 0, "napsTaken": 37.5,
 "felineIQ": null}

تُعَد معرفة JSON أمرًا مفيدًا، لأن العديد من مواقع الويب تقدم محتوى JSON بوصفه وسيلةً للبرامج للتفاعل مع موقع الويب، ويُعرَف ذلك بتوفير واجهة برمجة تطبيقات Application Programming Interface -أو API اختصارًا. يشبه الوصول إلى واجهة برمجة التطبيقات الوصولَ إلى أيّ صفحة ويب أخرى باستخدام عنوان URL، ولكن الفرق بينهما هو أن البيانات التي تعيدها واجهة برمجة التطبيقات تكون منسَّقة لتفهمها الأجهزة باستخدام JSON مثلًا، إذ ليس من السهل أن يقرأ البشر واجهات برمجة التطبيقات.

تتيح العديد من مواقع الويب بياناتها بتنسيق JSON، حيث توفر فيسبوك Facebook وتويتر Twitter وياهو Yahoo وجوجل Google وتمبلر Tumblr وويكيبيديا Wikipedia وفليكر Flickr و Data.gov وريديت Reddit و IMDb وروتن توميتوز Rotten Tomatoes ولينكد إن LinkedIn والعديد من المواقع الشهيرة الأخرى واجهات برمجة تطبيقات لتستخدمها البرامج. تتطلب بعض هذه المواقع التسجيل الذي يكون مجانيًا دائمًا، ويجب أن تعثر على توثيق عناوين URL التي يحتاج برنامجك إلى طلبها للحصول على البيانات التي تريدها، بالإضافة إلى التنسيق العام لهياكل بيانات JSON المُعادة. يجب توفير هذا التوثيق من خلال أيّ موقع يقدم واجهة برمجة التطبيقات، حيث إذا توافرت صفحة للمطورين "Developers"، فابحث عن التوثيق هناك.

يمكنك كتابة البرامج التي تنفّذ ما يلي باستخدام واجهات برمجة التطبيقات:

  • استخلاص البيانات الخام من المواقع، حيث يكون الوصول إلى واجهات برمجة التطبيقات أسهل من تنزيل صفحات الويب وتحليل شيفرة HTML باستخدام مكتبة Beautiful Soup.
  • تنزيل المنشورات الجديدة تلقائيًا من أحد حساباتك على شبكة التواصل الاجتماعي ونشرها على حسابٍ آخر، فمثلًا يمكنك أخذ منشوراتك على تمبلر ونشرها على فيسبوك.
  • إنشاء "موسوعة أفلام" لمجموعة أفلامك الشخصية من خلال سحب البيانات من IMDb و Rotten Tomatoes وويكيبيديا ووضعها في ملف نصي واحد على حاسوبك.

ملاحظة: يمكنك رؤية بعض الأمثلة على واجهات برمجة تطبيقات JSON في الموارد الموجودة على موقع nostarch.

لا تعد JSON الطريقة الوحيدة لتنسيق البيانات في سلسلة نصية يمكن أن يقرأها البشر، إذ توجد العديد من اللغات الأخرى بما في ذلك لغات XML (لغة التوصيف الموسَّعة eXtensible Markup Language) و TOML (أو Tom’s Obvious, Minimal Language) و YML (أو Yet another Markup Language) و INI (أو Initialization) وتنسيقات ASN.1 القديمة (Abstract Syntax Notation One)، حيث توفر جميع هذه اللغات هيكلًا لتمثيل البيانات بوصفها نصًا يمكن أن يقرأه البشر. لن نغطّي هذه اللغات في هذا المقال، لأن تنسيق JSON أصبح التنسيق البديل الأكثر استخدامًا على نطاق واسع، ولكن توجد وحدات بايثون خارجية يمكنها التعامل معها بسهولة.

وحدة json

تتعامل وحدة json في بايثون مع جميع تفاصيل الترجمة بين سلسلة نصية تحتوي على بيانات JSON وقيم بايثون الخاصة بالدوال json.loads()‎ و json.dumps()‎. لا يمكن لتنسيق JSON تخزين كل أنواع قيم بايثون، إذ يمكن أن يحتوي على قيم لأنواع بياناتٍ مُحدَّدة فقط وهي: السلاسل النصية Strings والأعداد الصحيحة Integers والأعداد العشرية Floats والقيم المنطقية Booleans والقوائم Lists والقواميس Dictionaries والنوع NoneType. كما لا يمكن لتنسيق JSON أن يمثل كائنات خاصة بلغة بايثون مثل كائنات File أو كائنات reader أو writer الخاصة بوحدة CSV أو كائنات Regex أو كائنات WebElement الخاصة بالوحدة Selenium.

قراءة بيانات JSON باستخدام الدالة loads()‎

يمكنك ترجمة سلسلة نصية تحتوي على بيانات JSON إلى قيمة في لغة بايثون من خلال تمريرها إلى الدالة json.loads()‎، حيث يعني اسم هذه الدالة loads تحميل سلسلة نصية "load string" ولا يعني مجموعة التحميلات "loads". لندخِل الآن ما يلي في الصدفة التفاعلية Interactive Shell:

>>> stringOfJsonData = '{"name": "Zophie", "isCat": true, "miceCaught": 0,
"felineIQ": null}'
>>> import json
>>> jsonDataAsPythonValue = json.loads(stringOfJsonData)
>>> jsonDataAsPythonValue
{'isCat': True, 'miceCaught': 0, 'name': 'Zophie', 'felineIQ': None}

نستورد أولًا الوحدة json، ثم يمكننا استدعاء الدالة loads()‎ وتمرير سلسلة نصية من بيانات JSON إليها، حيث تستخدم سلاسل JSON النصية دائمًا علامات اقتباس مزدوجة، وتعيد هذه الدالة البيانات بوصفها قاموس بايثون. تُعَد قواميس بايثون غير مرتبة، لذا يمكن أن تظهر أزواج مفتاح-قيمة بترتيب مختلف عند طباعة jsonDataAsPythonValue.

كتابة بيانات JSON باستخدام الدالة dumps()‎

تترجم الدالة json.dumps()‎ قيمة بايثون إلى سلسلة نصية من البيانات بتنسيق JSON، حيث يعني اسم هذه الدالة dumps تفريغ سلسلة نصية "dump string" ولا يعني الجمع "dumps"). لندخِل الآن ما يلي في الصدفة التفاعلية:

>>> pythonValue = {'isCat': True, 'miceCaught': 0, 'name': 'Zophie',
'felineIQ': None}
>>> import json
>>> stringOfJsonData = json.dumps(pythonValue)
>>> stringOfJsonData
'{"isCat": true, "felineIQ": null, "miceCaught": 0, "name": "Zophie" }'

يمكن أن يكون نوع القيمة أحد أنواع بيانات بايثون الأساسية فقط وهي: قاموس أو قائمة أو عدد صحيح أو عدد عشري أو سلسلة نصية أو قيمة منطقية أو None.

تطبيق عملي: جلب بيانات الطقس الحالية

يبدو التحقق من الطقس أمرًا بسيطًا إلى حد ما، حيث يمكنك فتح متصفح الويب الخاص بك والنقر على شريط العناوين، ثم كتابة عنوان URL لموقع ويب خاص بالطقس أو البحث عن موقع ثم النقر على الرابط، وانتظار تحميل الصفحة، والاطلاع على جميع الإعلانات وإلخ. هناك الكثير من الخطوات المملة التي يمكنك تخطيها إذا كان لديك برنامج ينزّل توقعات الطقس للأيام القليلة القادمة ويطبعها ضمن نصٍ عادي، حيث يستخدم هذا البرنامج الوحدة requests لتنزيل البيانات من الويب، فالخطوات العامة التي يطبّقها هذا البرنامج هي ما يلي:

  1. قراءة الموقع المطلوب من سطر الأوامر.
  2. تنزيل بيانات JSON الخاصة بالطقس من الموقع OpenWeatherMap.org.
  3. تحويل سلسلة بيانات JSON إلى هيكل بيانات بايثون.
  4. طباعة حالة الطقس لهذا اليوم واليومين القادمين.

لذا ستطبّق الشيفرة البرمجية الخطوات التالية:

  1. ضم السلاسل النصية إلى القائمة sys.argv للحصول على الموقع.
  2. استدعاء الدالة requests.get()‎ لتنزيل بيانات الطقس.
  3. استدعاء الدالة json.loads()‎ لتحويل بيانات JSON إلى هيكل بيانات بايثون.
  4. طباعة توقعات الطقس.

افتح نافذة محرّر جديدة لإنشاء ملف جديد لهذا المشروع واحفظه بالاسم getOpenWeather.py، ثم انتقل إلى الموقع OpenWeatherMap في متصفحك وسجّل فيه على حساب مجاني للحصول على مفتاح API، ويُسمَّى أيضًا معرّف التطبيق app ID، والذي يمثل رمز سلسلة نصية يبدو مثل الرمز '30144aba38018987d84710d0e319281e' بالنسبة لخدمة OpenWeatherMap. لا حاجة للدفع مقابل هذه الخدمة إلّا إذا أردتَ إجراء أكثر من 60 استدعاء لواجهة برمجة التطبيقات في الدقيقة. حافظ على سرية مفتاح API، إذ يمكن لأيّ شخص يعرفه كتابة سكربتات تأخذ من حصة الاستخدام الخاصة بحسابك.

الخطوة الأولى: الحصول على الموقع من وسيط سطر الأوامر

يأتي دخل هذا البرنامج من سطر الأوامر، لذا اجعل برنامج getOpenWeather.py كما يلي:

#! python3
# getOpenWeather.py - طباعة الطقس لموقعٍ ما من سطر الأوامر

APPID = 'YOUR_APPID_HERE'

import json, requests, sys

# حساب الموقع من وسطاء سطر الأوامر
if len(sys.argv) < 2:
    print('Usage: getOpenWeather.py city_name, 2-letter_country_code')
    sys.exit()
location = ' '.join(sys.argv[1:])

# ‫تنزيل بيانات JSON من واجهة برمجة تطبيقات OpenWeatherMap.org

# تحميل بيانات‫ JSON في متغير بايثون

تُخزَّن وسطاء سطر الأوامر ضمن القائمة sys.argv في لغة بايثون، ويجب ضبط المتغير APPID على قيمة مفتاح API الخاص بحسابك، إذ ستفشل طلباتك لخدمة الطقس بدون هذا المفتاح، ثم سيتحقق البرنامج من وجود أكثر من وسيط سطر أوامر بعد سطر Shebang (الذي يبدأ بالرمز !#) والتعليمة import. تذكّر أن القائمة sys.argv تحتوي دائمًا على عنصر واحد على الأقل sys.argv[0]‎، والذي يحتوي على اسم ملف سكربت بايثون. إذا كان هناك عنصر واحد فقط في القائمة، فهذا يعني أن المستخدم لم يقدّم موقعًا في سطر الأوامر، وستُعرَض رسالة الاستخدام "usage" للمستخدم قبل انتهاء البرنامج.

تتطلب خدمة OpenWeatherMap تنسيق الاستعلام بالشكل: اسم المدينة ثم فاصلة ثم رمز البلد المكون من حرفين مثل الرمز "US" للولايات المتحدة الأمريكية، حيث يمكنك العثور على قائمة بهذه الرموز على ويكيبيديا. يعرض هذا السكربت الطقس للمدينة الأولى المُدرَجة في نص JSON المُعاد، ولكن ستُضمَّن جميع المدن التي لها الاسم نفسه مثل مدينة بورتلاند Portland في ولاية أوريجون ومدينة بورتلاند بولاية ماين، بالرغم من أن نص JSON سيتضمّن معلومات خطوط الطول والعرض للتمييز بين هذه المدن.

تُقسَم وسطاء سطر الأوامر بناءً على الفراغات، حيث سيجعل وسيط سطر الأوامر San Francisco, US القائمة sys.argv تحتوي على ['getOpenWeather.py', 'San', 'Francisco,', 'US']، لذلك استدعِ التابع join()‎ لضم جميع السلاسل النصية باستثناء السلسلة النصية الأولى في القائمة sys.argv، وخزّن هذه السلسلة النصية الناتجة عن الضم في متغير اسمه location.

الخطوة الثانية: تنزيل بيانات JSON

يوفّر موقع OpenWeatherMap.org معلومات الطقس بتنسيق JSON في الزمن الحقيقي، ولكن يجب عليك أولًا التسجيل في الموقع للحصول على مفتاح API مجاني، حيث يُستخدَم هذا المفتاح لتقييد عدد مرات تقديم الطلبات على الخادم، مما يؤدي إلى إبقاء تكاليف حيز النطاق التراسلي منخفضة. يجب أن ينزّل برنامجك الصفحة الموجودة على الرابط:

 https://api.openweathermap.org/data/2.5/forecast/daily?q=<Location>&cnt=3&APPID=<APIkey>

حيث <Location> هو اسم المدينة التي تريد الطقس فيها و <API key> هو مفتاح API الشخصي الخاص بك. أضِف ما يلي إلى برنامج getOpenWeather.py:

#! python3
# getOpenWeather.py - طباعة الطقس لموقعٍ ما من سطر الأوامر

--snip--

# ‫تنزيل بيانات JSON من واجهة برمجة تطبيقات OpenWeatherMap.org
url ='https://api.openweathermap.org/data/2.5/forecast/daily?q=%s&cnt=3&APPID=%s ' % (location,
APPID)
response = requests.get(url)
response.raise_for_status()

# ‫ألغِ التعليق لرؤية نص JSON الخام:
#print(response.text)    

# تحميل بيانات‫ JSON في متغير بايثون

يأتي الموقع location من وسطاء سطر الأوامر، ويمكننا إنشاء عنوان URL الذي نريد الوصول إليه من خلال استخدام العنصر البديل s% وإدراج أيّ سلسلة نصية مُخزَّنة في location في ذلك المكان من السلسلة النصية التي تمثّل عنوان URL. نخزّن النتيجة في المتغير url الذي نمرّره إلى الدالة requests.get()‎، حيث يعيد استدعاء الدالة requests.get()‎ الكائن Response، والذي يمكنك التحقق من وجود أخطاء فيه من خلال استدعاء الدالة raise_for_status()‎. إن لم يظهر أيّ استثناء، فسيكون النص المُنزَّل موجودًا في response.text.

الخطوة الثالثة: تحميل بيانات JSON وطباعة الطقس

يحتوي المتغير العضو response.text على سلسلة نصية كبيرة من البيانات المُنسَّقة بتنسيق JSON، حيث يمكنك تحويلها إلى قيمة بايثون من خلال استدعاء الدالة json.loads()‎، وستبدو بيانات JSON كما يلي:

{'city': {'coord': {'lat': 37.7771, 'lon': -122.42},
          'country': 'United States of America',
          'id': '5391959',
          'name': 'San Francisco',
          'population': 0},
 'cnt': 3,
 'cod': '200',
 'list': [{'clouds': 0,
           'deg': 233,
           'dt': 1402344000,
           'humidity': 58,
           'pressure': 1012.23,
           'speed': 1.96,
           'temp': {'day': 302.29,
                    'eve': 296.46,
                    'max': 302.29,
                    'min': 289.77,
                    'morn': 294.59,
                    'night': 289.77},
           'weather': [{'description': 'sky is clear',
                        'icon': '01d',
--snip

يمكنك رؤية هذه البيانات من خلال تمرير المتغير weatherData إلى الدالة pprint.pprint()‎، وقد ترغب في الاطلاع على موقع openweathermap.org لمزيد من التوثيق الذي يوضّح معنى هذه الحقول، فمثلًا سيخبرك التوثيق عبر الإنترنت أن القيمة 302.29 بعد 'day' هي درجة الحرارة أثناء النهار بواحدة الكلفن وليست بواحدة فهرنهايت أو الدرجة المئوية.

يوجد وصف الطقس الذي تريده بعد 'main' و 'description'، لذا أضِف ما يلي إلى برنامج getOpenWeather.py لطباعته بدقة:

   ! python3
   # getOpenWeather.py - طباعة الطقس لموقعٍ ما من سطر الأوامر

   --snip--

   #  تحميل بيانات‫ JSON في متغير بايثون
   weatherData = json.loads(response.text)

   # طباعة وصف الطقس
 w = weatherData['list']
   print('Current weather in %s:' % (location))
   print(w[0]['weather'][0]['main'], '-', w[0]['weather'][0]['description'])
   print()
   print('Tomorrow:')
   print(w[1]['weather'][0]['main'], '-', w[1]['weather'][0]['description'])
   print()
   print('Day after tomorrow:')
   print(w[2]['weather'][0]['main'], '-', w[2]['weather'][0]['description'])

لاحظ كيف تخزّن الشيفرة البرمجية السابقة المتغير weatherData['list']‎ في المتغير w ليوفر عليك بعض الجهد عند الكتابة ➊، حيث يمكنك استخدام w[0]‎ و w[1]‎ و w[2]‎ لاسترداد القواميس الخاصة بطقس اليوم والغد وبعد الغد على التوالي، ويحتوي كلّ قاموس من هذه القواميس على مفتاح 'weather' الذي يحتوي على قيمة من النوع قائمة، ويهمنا منها عنصر القائمة الأول عند الفهرس 0، وهو قاموس متداخل يحتوي على عدة مفاتيح أخرى. نطبع القيم المخزنة في المفتاحين 'main' و 'description'، حيث نفصل بينها بشرطة واصلة.

سيبدو الخرج كما يلي عند تشغيل هذا البرنامج باستخدام وسيط سطر الأوامر getOpenWeather.py San Francisco, CA:

Current weather in San Francisco, CA:
Clear - sky is clear

Tomorrow:
Clouds - few clouds

Day after tomorrow:
Clear - sky is clear

أفكار لبرامج مماثلة

يمكن أن يشكّل الوصول إلى بيانات الطقس الأساس الذي نبني عليه العديد من أنواع البرامج الأخرى، حيث يمكنك إنشاء برامج مماثلة لتنفيذ ما يلي:

  • جمع تنبؤات الطقس للعديد من مواقع التخييم أو مسارات المشي لمسافات طويلة لمعرفة أيّ منها سيكون فيها الطقس الأفضل.
  • جدولة برنامج للتحقق من الطقس بانتظام وإرسال تنبيه عند حدوث الصقيع إذا أردتَ نقل نباتاتك إلى الداخل، حيث سنوضّح لاحقًا الجدولة وكيفية إرسال البريد الإلكتروني.
  • سحب بيانات الطقس من مواقع متعددة لإظهارها دفعة واحدة، أو حساب وإظهار متوسط توقعات الطقس المتعددة.

مشروع للتدريب: محوّل ملف إكسل إلى ملف CSV

يمكن لإكسل حفظ جدول بيانات في ملف CSV باستخدام بضع نقرات بالماوس، ولكن إذا أردتَ تحويل مئاتٍ من ملفات إكسل إلى ملفات CSV، فسيستغرق الأمر ساعات من النقر، لذا استخدم وحدة openpyxl لكتابة برنامجٍ يقرأ جميع ملفات إكسل الموجودة في مجلد العمل الحالي ويخرجها بوصفها ملفات CSV.

قد يحتوي ملف إكسل واحد على أوراق متعددة، لذا يجب إنشاء ملف CSV واحد لكل ورقة، ويجب أن تكون أسماء ملفات CSV هي ‎<excel filename>_<sheet title>.csv، حيث يكون <excel filename> هو اسم ملف إكسل بدون امتداد الملف مثل 'spam_data' وليس 'spam_data.xlsx' ويكون <sheet title> هو السلسلة النصية التي تأتي من المتغير title الخاص بكائن Worksheet.

سيتضمن هذا البرنامج العديد من حلقات for المتداخلة، وسيبدو هيكل هذا البرنامج كما يلي:

for excelFile in os.listdir('.'):
    # ‫تخطي الملفات التي ليست ملفات xlsx، وتحميل كائن المصنف workbook
    for sheetName in wb.get_sheet_names():
        # المرور ضمن حلقة على كل ورقة في المصنف
        sheet = wb.get_sheet_by_name(sheetName)

        # إنشاء اسم ملف‫ CSV من اسم ملف إكسل وعنوان الورقة
        # ‫إنشاء كائن csv.writer لملف CSV

        # المرور ضمن حلقة على كل صف في الورقة
        for rowNum in range(1, sheet.max_row + 1):
            rowData = []    # إلحاق كل خلية بهذه القائمة
            # المرور ضمن حلقة على كل خلية في الصف
            for colNum in range(1, sheet.max_column + 1):
                # إلحاق بيانات كل خلية بالقائمة‫ rowData

            # ‫كتابة القائمة rowData في ملف CSV

        csvFile.close()

نزّل الملف المضغوط excelSpreadsheets.zip وفك ضغط جداول البيانات في المجلد نفسه الموجود فيه برنامجك، حيث يمكنك استخدام جداول البيانات هذه كملفات لاختبار البرنامج عليها.

الخلاصة

تُعد CSV و JSON من تنسيقات النصوص العادية الشائعة لتخزين البيانات، حيث يسهُل على البرامج تحليلها مع بقاء قابليتها للقراءة، لذا تُستخدَم لجداول البيانات أو بيانات تطبيقات الويب البسيطة. تبسّط وحدتا csv و json عملية القراءة والكتابة في ملفات CSV و JSON بصورة كبيرة.

تعلّمنا سابقًا كيفية استخدام بايثون لتحليل معلومات مجموعة واسعة من تنسيقات الملفات، فإحدى المهام الشائعة هي أخذ البيانات من مجموعة متنوعة من التنسيقات وتحليلها للحصول على المعلومات المُحدَّدة التي تحتاجها، وتكون هذه المهام مُحدَّدة لدرجة أن البرمجيات التجارية لن تفيدك في إنجازها على النحو الأمثل، لذا يمكنك جعل حاسوبك يتعامل مع كميات كبيرة من البيانات المُقدَّمة بهذه التنسيقات من خلال كتابة السكربتات الخاصة بك.

سنبتعد في المقالات اللاحقة عن تنسيقات البيانات وسنتعلّم كيفية جعل برامجك يتواصل معك من خلال إرسال رسائل البريد الإلكتروني والرسائل النصية.

ترجمة -وبتصرُّف- للمقال Working with CSV files and JSON data لصاحبه Al Sweigart.

اقرأ أيضًا


تفاعل الأعضاء

أفضل التعليقات

لا توجد أية تعليقات بعد



انضم إلى النقاش

يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.

زائر
أضف تعليق

×   لقد أضفت محتوى بخط أو تنسيق مختلف.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   جرى استعادة المحتوى السابق..   امسح المحرر

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • أضف...