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")

الفصل الثامن : التعامل مع المكتبات


في هذا الفصل سوف نتطرق الى الحديث عن المكتبات (modules) في لغة بايثون والتي تعتبر من أحد أهم العوامل التي ساهمت في ذياع صيت لغة بايثون على كافة الأصعدة. فعلى سبيل المثال نجد مكتبات مثل numpy و scipy وmatplotlib مشهورة الاستخدام في الأوساط العلمية والبحثية. وكذلك مكتبتي Django و flask التي يعتمد عليها المبرمجين في بناء تطبيقات الويب. وتعتبر مكتبة pandas مشهورة لدى المهتمين بتحليل البيانات الى غير ذلك من المكتبات الاخرى. سنحاول في هذا الفصل تبسط مفهوم المكتبات في بايثون لدى القارئ حيث سنبدأ بتعريف المكتبات وكيفية التعامل معها. وسنقوم أيضاً بتعريف القارئ ببعض المكتبات المبنية داخل إصدارة بايثون 3 والتي من الصعب الإستغناء عنها عند كتابة أي كود برمجي. كما سنتعرف أيضاً على كيفية تنصيب مكتبات خارجية الى مجلد مكتبات بايثون من أجل استخدامها في كتابة البرامج. وفي نهاية الفصل سوف نتطرق بشكل مبسط الى كيفية إنشاء مكتبة خاصة بنا.

أهداف الفصل

عند اتمام هذا الفصل يجب ان يكون لديك المام بالآتي:
  1. تعريف المكتبات في لغة بايثون وكيفية استدعائها.
  2. استخدام بعض المكتبات المبنية داخل إصدارة بايثون.
  3. معرفة كيفية تنصيب مكتبات خارجية داخل مجلد مكتبات بايثون لاستخدامها في كتابة البرامج.
  4. التعرف على كيفية بناء مكتبة خاصة بنا.

تعريف المكتبة في بايثون

المكتبة في بايثون هي عبارة عن ملف بايثون اعتيادي يحتوي على كود برمجي تم من خلاله تعريف عدد من الكائنات البرمجية والدوال والمتغيرات بهدف تسهيل أداء مهام متعلقة بموضوع معين. فنجد على سبيل المثال المكتبة math والتي هي عبارة مكتبة داخلية مبنية في اصدارة بايثون تحوي على دوال رياضية عديدة كدالة الجذر التربيعي ()sqrt وادالة جيب الزاوية ()sin وجيب تمام الزاوية ()cos الى غيرها من الدوال الرياضية. ولكي نتمكن من استخدام الدوال الموجودة داخل أي مكتبة يجب أن يتم استدعاؤها من خلال الامر import كما في المثال التالي:
import math x=math.sqrt(4) print(x)
لاحظ أن عملية الاستدعاء تمت باستخدام الأمر import متبوعاً باسم المكتبة. ومن ثم أصبح بإمكاننا استخدام الدوال داخل المكتبة math باستخدام اسم المكتبة أولاً ومن ثم اسم الدالة بعد الفصل بينها بنقطة. وطريقة الاستدعاء هذه ليست الوحيدة في بايثون. فهناك طرق استدعاء أخرى. فمثلا يمكن استدعاء المكتبة السابقة باستخدام التركيب اللغوي التالي:
from math import * x=sqrt(4) print(x)
لاحظ أن طريقة الاستدعاء في المثال السابق يمكن ترجمتها الى المعنى التالي: "من المكتبة math استورد كل الدوال والمتغيرات." وعلامة النجمة بعد كلمة import تعني استيراد كل شيء. كما يجب ملاحظة أنه عند استخدام طريقة الاستدعاء هذه فإننا لا نستخدم اسم المكتبة قبل الدالة وإنما نكتفى باستخدام الدالة مباشرة. لكن في حقيقة الأمر فإن مبرمجي بايثون لا يوصون باستخدام طريقة الاستدعاء هذه لسببين: أولها أن هذه الطريقة تستدعي كل شيء في المكتبة والتي قد لا نحتاج إلاّ لجزء يسير من الدوال الموجود في المكتبة. فتؤدي هذه الطريقة الى حشو ذاكرة الكمبيوتر بما لا فائدة منه. ثاني هذه الأسباب هو أنه قد يحصل تضارب بين أسماء الدوال الموجودة في المكتبة المستدعاه وأسماء دوال جديدة يمكن أن نقوم بإنشائها بأنفسنا. فمثلا عندما نستورد المكتبة math بالطريقة السابقة ثم نقوم بتعريف دالة جديدة تحمل اسم أحد الدوال الموجودة في المكتبة math فإنه يحصل ارتباك لدى المبرمج حول أية دالة تم استخدامها عند تنفيذ البرنامج كما في المثال التالي:
from math import * def sqrt(number): return "Hello " + str(number) x=sqrt(4) print(x)
على الرغم أن من يحدد أيتها دالة سوف يستدعيها مفسر بايثون عند تنفيذه الكود البرمجي السابق محكوم بمكان تعريف الدالة الجديدة التي قمنا بإنشائها داخل الكود البرمجي إلاّ أن طريقة الاستدعاء هذه تسبب ارباك لكل من يقرأ الكود البرمجي السابق. لذلك يفضل تحديد الدوال المراد استخدامها حين الاستدعاء بحيث لا يتم استدعاء دوال المكتبة بالكامل بل يكتفى باستدعاء الدوال المحددة فقط كما في المثال التالي:
from math import sin, pi print(sin(0.5*pi))
كما يمكن تغيير اسم المكتبة حين الاستدعاء بغرض تبسيط كتابة الكود البرمجي كما في المثال التالي:
import math as m print(m.sin(0.5*m.pi))

المكتبات المدمجة مع إصدارة بايثون

تحتوي إصدارة بايثون 3 على العديد من المكتبات الداخلية (built-in modules). وسوف نتطرق في هذه الجزئية من الفصل الي ثلاثة من هذه المكتبات وهي os و sys و أخيرا ًtime. أما بقية المكتبات فيمكن استخدام الدالة ()help والتي تعطي تعريف وشروحات وافيه عن أي مكتبة داخلية تكتب داخل قوسي الدالة كما في المثال التالي:
import random help(random)
كما يمكن أيضاً التعرف على محتويات أي مكتبة بعد استدعائها باستخدام الدالة ()dir كما في المثال التالي:
import math print(dir(math))
لاحظ أن ناتج الدالة ()dir هو عبارة قائمة تحوي جميع دوال ومتغيرات المكتبة math. ولو دققت النظر في بيانات القائمة السابقة لوجدت أن الدوال التي تعلمناها من المكتبة math موجودة بالفعل داخل هذه القائمة.
كما يمكن معرفة محتويات أي مكتبة مدمجة من خلال استخدام خلايا الكود في هذا الكتاب. فعند كتابة الأمر import والضغط على الزر tab من لوحة المفاتيح يقوم جوبتر نوت بوك باقتراح قائمة بالمكتبات التي يمكنك ان تستدعيها. وكلما كتبت أحرف أكثر من اسم المكتبة التي تريد استدعاؤها كلما كانت اقتراحات جوبتر نوت بوك أكثر دقة لما تنوي استدعاؤه. كما أن خاصية الإكمال الذاتي هذه تساعد المبرمج على مشاهدة محتويات المكتبة من دوال ومتغيرات. فبمجرد كتابة اسم المكتبة وإضافة نقطة بعدها ثم الضغط على زر tab من لوحة المفاتيح يبدأ جوبتر بعرض الدوال والمتغيرات التي تحتويها المكتبة لكي تساعد المبرمج على العثور على ما يبحث عنه.

مكتبة os

تسهل مكتبة os التفاعل مع نظام التشغيل الذي يعمل عليه المبرمج سواء كان ذلك نظام ويندوز أو ماك أو لينكس. وتقدم هذه المكتبة الكثير من الدوال الخاصة بالتعامل مع نظام التشغيل فمثلا يمكن معرفة المجلد الحالي الذي يتواجد فيه البرنامج والذي نعمل على كتابة كوده باستخدام الدالة ()getcwd كما في المثال التالي:
import os os.getcwd()
كما يمكن أيضاً تنفيذ جميع الأوامر التي يمكن تنفيذها على محرر الأوامر في ويندوز أو ماك أو لينكس من خلال كود بايثون البرمجي باستخدام الدالة ()system بحيث يوضع الأمر المراد تنفيذه بين علامتي تنصيص داخل قوسي الدالة كما في المثال التالي:
import os os.system("notepad")
وكذلك أيضاً يمكن تكوين مجلد باستخدام الدالة ()mkdir وكذلك حذف مجلد باستخدام ()rmdir وايضاً يمكن تغيير موقع المجلد باستخدام الدالة ()chdir وعرض قائمة بأسماء المجلدات باستخدام الدالة ()listdir والكثير الكثير من الدوال الخاصة بالتعامل مع الملفات والمجلدات والتي لا يسع المقام لذكرها هنا ويمكن الاطلاع عليها من خلال وسائل المساعدة التي ذكرناه سابقاً.

مكتبة sys

تمكن مكتبة sys المبرمج بلغة بايثون من التعامل مع كل ما يخص مفسر بايثون. فمثلا يمكن معرفة رقم إصدارة بايثون عن طريق استخدام المتغير version كما في المثال التالي:
import sys print(sys.version)
كما يمكن معرفة المجلدات التي سوف يقوم مفسر بايثون بالبحث فيها عند إجراء أي عملية استدعاء سواءً كانت لمكتبة أو دالة أو فتح لملف وذلك باستخدام المتغير path كما في المثال التالي:
import sys print(sys.path)
يجب ملاحظة أن ناتج الكود السابق يختلف بحسب اختلاف إعدادات النظام لكل مستخدم وطريقة ونوعية تنصيبه لإصدارة بايثون. فأول مكان يقوم مفسر بايثون بالبحث فيه هو المجلد الذي تم تشغيل الكود البرمجي منه ثم مجلد المكتبات الداخلية (يختلف باختلاف إصدارة بايثون المستخدمه) ومن ثم مجلد المكتبات الخارجية site-packages.
كما يمكن استخدام المتغير argv في مكتبة sys للتعرف على المدخلات التي تصاحب ملف بايثون عند تشغيله من محرر أوامر النظام الذي يعمل عليه المستخدم. ولتوضح هذه الفكرة أكثر أنشأنا داخل مجلد كتابنا هذا ملف بايثون اسمه test.py وكتبنا بداخله الكود البرمجي التالي:
import sys print(sys.argv)
لنقم الان بتشغيل الملف السابق من محرر الأوامر سواءً كان ذلك في ويندوز أو في غيره من الأنظمة. وللقيام بذلك من خلال خلية كود في هذا الكتاب سوف نستخدم علامة التعجب ! قبل أمر تشغيل الملف كما في المثال التالي:
!python test.py
بعد كتابة الامر python test.py والضغط على زر الادخال يتم تشغيل الملف الذي كتبناه بلغة بايثون والذي يقوم بطباعة قيمة المتغير argv. المتغير argv الذي تم طباعته هنا هو عبارة عن قائمة تحتوي على اسم الملف الذي قمنا بتشغيله. ويمكن إضافة بيانات الى المتغير argv وذلك بكتابتها بعد اسم الملف عند التشغيل كما في المثال التالي:
!python test.py 1 2 3
لا حظ ان كل شيء يكتب بعد اسم الملف حين تشغيله يتعامل معه مفسر بايثون على أنه مدخل يتم اضافته الى قائمة argv ويجب ملاحظة أن الفصل بين البيانات يتم بواسطة ترك مسافة بين كل مدخل وآخر كما هو واضح في المثال السابق. وتعتبر طريقة الادخال هذه شائعة الاستخدام للبرامج التي يتم تشغيلها من محرر أوامر النظام.

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

١- قم بكتابة برنامج يستغل خاصية ادخال البيانات عند التشغيل بحيث يقوم بجمع الأعداد المدخلة وطباعة ناتج الجمع على شاشة الكمبيوتر؟

مكتبة time

مكتبة time الداخلية تحتوي على العديد من الدوال التي تساعد المبرمج على القيام بمهام متعلقة بالوقت. فمثلا يمكن استخدام الدالة ()time لمعرفة الوقت بعدد الثوان التي مضت منذ الساعة 12 صباحاً من اليوم الاول لشهر يناير لعالم 1970 كما في المثال التالي:
import time time.time()
قد لا تكون صيغة الوقت هذه مفيدة للكثير لكن يمكن تحويل هذه الثواني لصيغة وقت مألوفة باستخدام الدالة ()ctime كما في المثال التالي:
import time t=time.time() time.ctime(t)
الدالة ()ctime تعطي صيغة الوقت المألوفة عندما نزودها بعدد الثوان التي مرت منذ ذلك التاريخ لكن عندما نستخدمها بدون أي مدخلات فإنها تعطينا الوقت الحالي بالصيغة المألوفة كما في المثال التالي:
import time print(time.ctime())
كما يمكن تأجيل تنفيذ أي سطر برمجي يقع بعد الدالة ()sleep لعدد معين من الثوان توضع بين قوسي الدالة كما في المثال التالي:
import time print(time.ctime()) time.sleep(5) print(time.ctime())
كما يجب عليك ملاحظة ان معظم دوال المكتبة time تتعامل مع كائن برمجي للوقت ينتج من تنفيذ بعض الدوال بحيث يكون تكوين هذا الكائن البرمجي مجزأ الى أجزاء الوقت المعروفة من سنة وشهر ويوم وساعة الى ...الخ. بحيث تسهل على المبرمج التعامل مع أجزاء الوقت وكتابتها بالطريقة التي يرغب بها. فعند استدعاء الدالة ()localtime يتم ارجاع كائن الوقت الخاص بالمكان الحالي وكذلك الدالة ()gmtime تقوم بارجاع كائن خاص بوقت جرينتش كما في المثال التالي:
import time Makkah_time=time.localtime() London_time=time.gmtime() print(Makkah_time) print(London_time) print(Makkah_time.tm_hour)

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

١- قم بكتابة برنامج يقوم بحساب فارق التوقيت بين مكة ولندن وطباعة الناتج على شاشة الكمبيوتر؟
كما يمكن إعادة صياغة الوقت بالطريقة التي نرغب بها باستخدام الدالة ()strftime كما في المثال التالي:
import time Makkah_time = time.localtime() formatted_time = time.strftime("%m/%d/%Y, %H:%M:%S", Makkah_time) print(formatted_time)
في المثال السابق تم وضع صيغة الوقت المطلوبة على شكل نص كمدخل أول للدالة وكائن الوقت وضع كمدخل ثان. ولحل شفرة رموز شفرة الوقت السابقة يمكن الاستعانة بالجدول التالي:
المعنىالرمز
السنة من 4 ارقام%Y
السنة في رقمين%y
الشهر%m
اليوم%d
الساعة%H
الدقيقة%M
الثانية%S

طريقة تنصيب مكتبة خارجية

في الإصدارات الحديثة من بايثون تم دمج الأداة المستخدمة لإضافة المكتبات الخارجية مع مفسر بايثون بحيث ان هذه الأداة تكون متوفرة بمجرد تنصيب اصدارة بايثون. تختلف هذه الأداة بحسب التوزيعة المستخدمة. فالأداة pip تأتي مع الاصدارة الأساسية. اما توزيعة Anaconda فلها أداة تنصيب خاصة بها تسمى conda تؤدي نفس وظائف الأداة pip. ولشرح طريقة استخدام pip لنستعرض أولا المكتبات التي تم تنصيبها داخل اصدارة بايثون وذلك باستخدام الامر pip list من محرر أوامر النظام كما في المثال التالي:
!pip list
فالمثال السابق قام بطباعة كافة المكتبات المنصبة على اصدارة بايثون وارقام اصداراتها.
فاذا كانت المكتبة التي ترغب باستخدامها ليست موجود في هذه القائمة فان بإمكانك تنصيبها عن طريق استخدام الامر pip install متبوعاً باسم المكتبة المطلوبة كما في المثال التالي:
!pip install progressbar
في المثال السابق قمنا بتنصيب المكتبة progressbar والتي تعتبر من المكتبات الصغيرة بحيث تساعد المبرمج في تكوين كائن مرئ يوضح مدى التقدم في انجاز مهمة ما. وعند اكتمال التنصيب تعطي الأداة pip رسالة بنجاح عملية التنصيب للمكتبة. المثال التالي يوضح طريقة استخدام هذه المكتبة بعد تنصيبها:
from time import sleep from progressbar import ProgressBar bar=ProgressBar() for i in bar(range(50)): sleep(0.5)
اما إذا كانت المكتبة منصبة لديك من قبل وترغب فقط بتحديثها فانه بإمكانك استخدام خيار التحديث كما في المثال التالي:
pip install --upgrade progressbar
حيث اعطانا الامر السابق ان مكتبة progressbar المنصبة على هي أحدث اصدارة موجودة ولا تحتاج الى تحديث. اما إذا كانت الاصدارة قديمة فان pip سوف يقوم بتنصيب اصدارة المكتبة الاحدث من موقع https://pypi.org. اما الأداة conda فإنها تعمل تقريبا بنفس الطريق التي تعمل بها الأداة pip. لذلك اعتقد انه لا داعي للحديث عنها هنا ويمكن استخدام محرك البحث قوقل لتعرف عليها أكثر.

طريقة انشاء مكتبة

كما ذكرنا في بداية الفصل مكتبات بايثون هي مجرد ملف بايثون اعتيادي ينتهي بالحرفين py. ويحتوي على كائنات برمجية ودوال ومتغيرات خاصة بموضوع معين. ولكي نوضح سهولة طريقة انشاء أي مكتبة لنفرض اننا بصدد انشاء مكتبة خاصة بتحويل الوحدات الطولية (متر، سنتيمتر، مليمتر، مايكرومتر) ولنفرض ان اسمها meter. للقيام بهذه المهمة سوف نفتح ملف جديد ونحفظه باسم meter.py ثم نبدأ بكتابة الكود البرمجي التالي بداخله:
'''This module has been built to convert between the different units of length''' def to_cm(number): '''This function converts meter to centimeter''' return number*100 def to_mm(number): '''This function converts meter to millimeter''' return number*1000 def to_micro(number): '''This function converts meter to micrometer''' return number*10e6 def from_cm(number): '''This function converts centimeter to meter''' return number/100 def from_mm(number): '''This function converts millimeter to meter''' return number/1000 def from_micro(number): '''This function converts micrometer to meter''' return number/10e6
الآن لنفتح ملف بايثون جديد ونحاول استدعاء المكتبة meter التي قمنا بإنشائها. يجب ملاحظة ان ملف المكتبة التي قمنا بإنشائها والملف الذي سوف نستدعيه من خلاله المكتبة يجب ان يكونا في مجلد واحد لكي يعثر مفسر بايثون على المكتبة كما تعلمنا سابقاً حين استعرضنا مكتبة sys ودالتها ()path.
import meter meter.to_cm(4)
كما تلاحظ من المثال السابق ان المكتبة التي قمنا بإنشائها تعمل كأي مكتبة موجودة داخل اصدارة بايثون. فمثلا يمكن ان نتعرف على الشروحات التي كتبناها عن المكتبة بين علامة التنصيص الثلاثية باستخدام المتغير __doc__ كما يلي:
import meter meter.__doc__
كما يمكن استعراض محتويات المكتبة meter باستخدام الدالة ()dir كما يلي:
import meter dir(meter)
لاحظ ان المتغيرات التي تبتدأ بشرطتين وتنتهي بشرطتين لم نقم بكتابتها داخل المكتبة ولكن بايثون قام بإنشائها بشكل تلقائي. كما يجب ملاحظة ان ملف المكتبة التي انشأناها ليس بالضرورة ان يكون في نفس المجلد الذي سوف نستدعي منه المكتبة. فعندما نرغب في وضع المكتبة في مكان اخر وليكن في المجلد modules الموجود في مجلد الكتاب هذا فانه يجب علينا ان نخبر مفسر بايثون بان يبحث في المجلد الذي وضعت فيه المكتبة وذلك من خلال إضافة هذا المجلد الي القائمة التي سوف يبحث فيها مفسر بايثون عن المكتبة كما في المثال التالي:
import sys sys.path.append('/units') import meter print(meter.to_cm(5))
لاحظ اننا قمنا بإضافة المجلد الذي يحتوي على المكتبة meter الى قائمة الاماكن التي يبحث فيها مفسر بايثون عن المكتبات بواسطة الدالة ()append قبل ان نقوم باستدعاء المكتبة meter.
كما يمكن أيضا إضافة المكتبة الى مجلد خاص تم تحديده من قبل مفسر بايثون ليكون خاص بمكتبات المستخدم. ولتعرف على هذا المجلد نقوم باستدعاء المتغير USER_SITE من مكتبة site الداخلية كما في المثال التالي:
import site print(site.USER_SITE)
المجلد الذي ينتج عن تنفيذ الكود السابق يختلف باختلاف اصدارة بايثون المستخدمة ويختلف أيضا باختلاف نظام التشغيل المستخدم. وفي غالب الأحيان لا يكون هذا المجلد موجود ويجب علينا انشاءه ومن ثم وضع المكتبة التي انشأناها بداخله لكي يتم التعرف عليها.

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

١- قم بتطوير مكتبة meter لكي تقوم بالتحويل من سنتيمتر الى ميليمتر والعكس ومن سنتيمتر الى مايكرومتر والعكس؟
وقبل ان نختم هذا الفصل نود نبين انه يمكن عمل رزمة من المكتبات package والتي هي عبارة عن مجموعة من المكتبات التي يحويها مجلد واحد. فعند انشاء مكتبة جديدة لتحويل درجات الحرارة وليكن اسمها مثلا temperature.py بحيث توضع هذه المكتبة الي جانب المكتبة meter السابقة في مجلد واحد وليكن اسم المجلد units فان مفسر بايثون يشترط للتعرف على هذه المكتبات ان يقوم المبرمج بإنشاء ملف فارغ داخل هذا المجلد بحيث يكون اسم هذا الملف __init__.py كما هو موضح بالشكل التالي:

image.png

كما يجب ملاحظة ان الشروط اللازمة لعثور مفسر بايثون على مكتبة معينة تنطبق على رزمة المكتبات كما وضحنا سابقاً. ويمكن استدعاء المكتبة meter من رزمة المكتبات units كما يلي:
import sys sys.path.append('units') from units import meter print(meter.from_cm(100))