تطبيقات لغة البايثون – تعلم كيف تبني إضافات plugins لبرنامج بايثون
تطبيقات لغة البايثون متعددة وكثيرة، ويُمكن الاستفادة منها في مجالات كثيرة. في هذا المقال نصطحبكم في بايثونات في رحلة تعلم كيفية عمل plugins لبرامج البايثون. كثيرًا ما نجد أنفسنا كمستخدمين لبرامج جاهزة – مهما كان تخصصها- في أعمالنا اليومية نقف و قد نكون عاجزين عن إتمام مهمة ما باستخدام البرنامج على الرغم من احترافنا له. فنبدأ رحلة البحث عن الحل في الانترنت بين المنتديات المتخصصة وفيديوهات اليوتيوب وغيرها. في أغلب الأحيان نجد الحل عبارة عن مجموعة كبيرة من الخطوات التتابعية المتسلسلة و نتيجة كل خطوة تعتمد اعتمادًا كليًا على نتيجة الإجراءات التي تمت من جميع ما قبلها والتي يجب أن تكون قد انتهت وبشكل صحيح ١٠٠٪ لنحصل بالنهاية على ما نريده كنتيجة نهائية. إنها لعملية متعبة و دقيقة وقد تستغرق وقتًا مهمًا كان طويلًا أو قصيرًا، خصوصا إذا كنا نحتاج إلى استخدام ذلك الحل بشكل كبير وقد يكون أساسي. في تلك اللحظة لابد لنا أن تساءلنا أنه لو كان هناك رز أو وظيفة تقوم بكل ذلك أوتوماتيكيا أو لو كان بمقدورنا أن نضيف وظيفة ما لبرنامجنا الذي نعمل عليه ليقوم بعمل ما بالشكل الذي نريد.
الحل في plugins
الحل لتلك الأسئلة هي الإضافات plugins والتي قد نجدها بالانترنت متاحة للجميع أو مدفوعة كما في حزمة برامج شركة أدوبي وأوتوديسك، حيث أن بعض هذه الإضافات تكون غالية الثمن بشكل كبير. الحل هنا أن بعض الشركات المصنعة للبرامج أتاحت للمستخدمين إمكانية بناء plugins خاصة بهم بأن جعلت برامجها قابلة للتطوير والإضافة scriptable بإتاحة API من البرنامج وإتاحة استخدام لغة برمجة دارجة أو خاصة بالبرنامج لعمل تلك الإضافات.
لنفترض أننا قمنا بعمل مشروع ما بلغة البايثون، والمشروع متكامل للاستخدام اليومي لأتمتة automate وظائف معينة. قد نود أن نُضيف أفكارًا جديدة لنخاع البرنامج كتطوير ولكن لانريد أن نبني إصدارًا جديدًا كليًا من البرنامج نفسة بمجرد إضافة وظيفة أو إثنتين. يمكن أن نُضيف plugins على مشروعنا دون الإخلال أو التدخل بتعديل نص البرنامج الرئيسي. سيكون الأمر أسهل وأفضل وأسرع أليس كذلك؟ إضافة ميزة جعل البرنامج scriptable ستكون أكثر من رائعة.
قبل البدء
لنفهم أولًا ماذا نريد أن نعمل و كيف للبرنامج أن يعمل. عندما نكتب برنامجًا أو مشروعا فإننا نقوم بكتابة وظائف functions متعددة تقوم كل منها بعمل ما ويتم استدعاؤها من البرنامج الرئيسي لتعمل مع بعضها بشكل متكامل يخدم الغرض من المشروع بشكل كامل.
نريد أن نجعل في مشروعنا ميزة أن يكون فيه python shell or python interpreter بحيث يمكننا أن نقوم بإنشاء ملفات تحتوي نصوص برمجية بلغة بايثون ويمكنها استدعاء واستخدام دوال المشروع واستخدام نتائجها والتعديل عليها كما نريد، بل و اضافة وظائف جديدة خاصة بنا تستخدم تلك الأصلية كـ API .
تطبيقات لغة البايثون – برنامج بايثون يُشغل مُفسر بايثون
لنبدأ بكتابة برنامج صغير يمكننا من خلاله أن نشغل بايثون شل تفاعلي python interactive shell و تنفيذ تعابير بايثون ثم تطويره ليقبل ملفات بايثون كاملة. لن يكون للبرنامج إلا وظيفتان وهما إمكانية تشغيل شل تفاعلي من خلاله ثم تطويرة ليقبل ملفات كاملة. لاحقا إن شاء الله سنقوم بكتابة مشروع متكامل يحتوي على دوال عدة والتي سنقوم باستيرادها في سكريبتات الإضافات الجديدة plugins scripts. لنكتب البرنامج التالي ونحفظه بإسم program.py:
أولا قمنا باستيراد الفئة InteractiveInterpreter من مكتبة code القياسية. هذi الفئة ماهي إلا نسخة من مُفسر بايثون نفسة -النسخة التفاعلية منه- لنستخدمه كـكائن object داخل برنامجنا.
أنشأنا فئة ترث من Interactiveinterpreter وكتبنا الدالة البانية له وهي __init__ و فيها قمنا باستدعاء الوظيفة البانية للـ InteractiveInterpreter نفسه. في البرنامج الرئيسي أنشأنا كائن باسم i من الفئة InteractiveInterpreter ثم قمنا بكتابة حلقة تكرارية بشكل لانهائي لنقرأ أوامر شل البايثون من خلال دالة input، ثم ننفذها مدخلات الدالة بشكل تفاعلي تماما مثل شل البايثون القياسي من خلال دالة runcode.
و النتيجة بعد تجربة بعض الأوامر بشكل تفاعلي هي:
عظيم جدا، لقد قمنا بتضمين شل البايثون التفاعلي داخل برنامجنا لينفذ تعابير البايثون الواحد تلو الآخر قياسيًا. والآن لنقم بالتعديل عليه ليستقبل ملفات بايثون كاملة و يشغلها .أي نقوم بتضمين المُفسر بأكمله داخل برنامجنا و إضافة تفاعل أفضل عن طريق استخدام مكتبة sys.
سنجعل البرنامج يعمل كالتالي:
- اذا كتبنا i- بعد اسم البرنامج سيقوم بتشغيل الشل التفاعلي
- اذا كتبنا f- بعد اسم البرنامج سيطلب منا البرنامج بادخال إسم ملف (لا يهم امتداده) يحتوي داخله على برنامج بايثون كامل ليتم تنفيذه.
قم بإنشاء ملف في نفس المكان الذي فيه البرنامج الرئيسي program.py والذي قمت بكتابته سابقا سمه myplugin.oss واكتب فيه التالي:
والآن قم بتعديل program.py ليكون شكلة كالتالي:
شرح program.py
- قمنا باستيراد InteractiveInterpreter , InteractiveConsole من مكتبة code
- استوردنا مكتبة sys للاستفادة منها لعمل نوع من التفاعل البسيط مع البرنامج لنستخدم منها القيمة argv وهي عبارة عن قائمة list بحيث يكون العنصر رقم صفر هو إسم البرنامج نفسه وأي شيء يليه يضاف فيها كما هو كنصstring .
- انشأنا فئتي InteractiveInterpreter , InteractiveConsole
البرنامج الرئيسي Main
- قمنا بكتابة شرح استخدام البرنامج وتخزينها في متغير USAGE وعمل list تحتوي على الاختيارات التي يتيحها البرنامج.
- تقوم العبارة الشرطية بالاستفادة من argv لتتحقق ما إذا أدخل المستخدم خيارًا غير موجودًا في قائمة options أو لم يدخل أي شيء بعد اسم البرنامج ليقوم بعرض شرح استخدام البرنامج.
- تقوم العبارة الشرطية الثانية بالتحقق اذا ما تم إدخال القيمة i- لتقوم بإنشاء كائن object من الشيل التفاعلي الذي أنشأنا منه فئة خاصة وأسميناها Interpreter.
- تقوم حلقة while الغير منتهية بالعمل بقبول مدخلات من المستخدم والتي هي عبارة عن تعليمات بايثون بشكل نصوص عن طريق دالة input و من ثم تنفيذها عن طريق الدالة ()i.runcode.
- أما بعد Else وهي ما نعنيه قياسيا بأن المستخدم قام بإختيار f- مما يعني أنه لابد له من ادخال قيمة إسم الملف الذي يحتوي بداخله برنامج بايثون كامل (oss) ليتم تخزين اسمه في المتغير fn.
- نقوم بعد ذلك بإنشاء كائن object إسمه c من فئة Console class.
- نقوم بفتح الملف الذي تم تخزين إسمه في fn بوضعية القراءة وهو الملف الـ plugin ونخزنه في متغير أسميناه plugin.
- قمنا بقراءة جميع محتويات الملف (بغض النظر عن امتداده) دفعة واحدة باستخدام الدالة ()plugin.read و تخزين محتوياته في متغير أسمه instructions
- قمنا بتمرير المتغير instructions والذي يحتوي على تعليمات برنامج بايثون كامل من الملف الذي تمت قراءة محتوياته للدالة ()runcode ليتم تنفيذه بالكامل.
عند تشغيل البرنامج و تجربة كافة احتمالاته تكون المخرجات بالشكل التالي:
رائع. لقد تعلمنا الآن كيفية جعل برامجنا ” قابلة للبرمجة” scriptable وكتابة إضافات plugins لها ضمنيا.
لقد كان ذلك مثالا عاما لشرح كيفية بناء وعمل برامج قابلة للبرمجة. سنرى لاحقا إن شاء الله كيفية إستخدام وتوظيف ما تعلمناه أعلاه في مشروع برمجي لتتضح الصورة بشكل أفضل وأكبر وأكثر احترافية.
لنبدأ، لنكتب ملف بايثون يحتوي على عدة دوال أو وظائف functions ثم نقوم باستيراده في ملف آخر يحتوي نصا لبرنامج رئيسي يستخدم الدوال التي في الملف الأول ليعمل. و من ثم نقوم بتعديل البرنامج الرئيسي ليكون قابلا للبرمجة scriptable لنستفيد من هذه الميزة لعمل إضافة plugin تستخدم الدوال الموجودة بملف الدوال و تحوير و نتائج تلك الدوال لخدمة البرنامج الرئيسي.
وصف المشروع
سنعمل على تجهيز مشروع يُمثل نموذجًا لتطبيقات لغة البايثون. قرر رئيس لفريق عمل في شركة صغيرة أن يقوم بكتابة برنامج صغير يقوم من من خلاله أن يدخل مجموعة من الأعمال اليومية بحيث يحاوره البرنامج بأن يدخل إسم العمل والشخص المسؤول بإنجازه وكل هذه القيم تخزن في قائمة تكون بمثابة مفكرة رقمية لرئيس الفريق، فقام بكتابة البرنامج على عجالة على ملفين:
- الملف الرئيسي py وهو البرنامج الرئيسي.
- ملف app_functions.py وهو ملف يحتوي على دوال قام بكتابتها وعزلها بملف خاص بها وذلك لسهولة تتبعها وصيانتها إن لزم الأمر بكل سهولة بعيدا عن سير البرنامج الرئيسي وهذا الملف ومحتوياته يتم استيراده مكتبة داخل البرنامج الرئيسي.
البرنامج يسير بشكل جيد ولكن يوجد فيه بعض النواقص والتي بدونها يكون عديم الفائدة بالنسبة لرئيس العمل. منها أن جميع ما تحتويه قائمة الأعمال سيتم مسحها ما إن يتم إغلاق البرنامج. دعت الحاجة لاستخدام وسط تخزين بسيط كالملفات لتخزين الأعمال بها. يمكننا أن نقوم بكتابة دالة في ملف الدوال واستيرادها واستخدامها كباقي الدوال ولكن لنفعل ذلك عن طريق كتابة plugin منفصل نقوم بتفعيله تفاعليا عن طريق سطر الأوامر لنستفيد من هذه المهارة التي تعلمناها بمشروعنا هنا.
لنقم بإنشاء ملف اسمه save_plugin.py و نكتب به دالة انشاء وتخزين قائمة الأعمال في ملف نصي بسيط.
أولا قم بإنشاء ملف للـ plugin الذي تريد بناءه و سمه save_plugin.py:
هنا قمنا بكتابة برنامج كامل يقوم أولا باستيراد متغير jobs والذي هو عبارة عن قائمة متغير عام في البرنامج الرئيسي بعد تعديله كما سنرى لاحقا وذلك لجعله سهل الاستيراد من قبل الملفات الخارجية. وظيفة هذا البرنامج plugin هو أن يطلب من المستخدم ان يدخل اسم الملف الذي يرغب بتخزين الأعمال فيه، وقد استخدمنا دالة ()daettime.datetimer.now التي تعطينا وقت انشاء ملف التخزين ولصقة باسم الملف ليثبت تاريخ ووقت إنشائه على وضعية الكتابة w، وأخيرا في الحلقة التكرارية الأخيرة for، قمنا بالمرور على جميع عناصر القائمة jobs والتي تحتوي على قواميس dictionaries بكل عامل و العمل الموكل له ثم قراءة كل مفتاح و قيمة لكل قاموس و تنسيقه في جملة مفيدة ليتم كتابتها في الملف النهائي الذي حدد اسم المستخدم.
أما هنا في البرنامج الرئيسي فقد قمنا بكتابة شرح عمل البرنامج. و قمنا بالإعلان عن المتغير jobs خارج جميع الدوال واستدعاءه كمتغير عام global مما سهل علينا استيراده و التعديل عليه من داخل البرنامج الرئيسي وخارجة (plugin).
نلاحظ بأن في عبارة if الأخيرة قمنا بالتحقق من أن المستخدم قد أدخل خيار تحميل الإضافات p- أولا ثم عرض عدد ملفات الإضافات التي تلي خيار التحميل حيث أننا نستطيع تحميل أي عدد نرغب به من ملفات الإضافات plugins الخارجية، ذلك لأن sys.argv هي عبارة عن قائمة يتم تعبئتها من قبل المستخدم عند بداية تشغيل البرنامج، فعندما نشغل البرنامج بكتابة:
مثلا فإن:
لذلك فإن العنصر رقم ٢ هو p- و ما بعدة هو عدد الـ plugins التي نريد تشغيلها والاستفادة منها.
و في حلقة for الأخيرة فإنها تقوم بإنشاء كائن من الكونسول و المرور على جميع ملفات الـ plugins و قراءة محتوياتها و تنفيذها.
فكرة
هذه مجموعة من الأفكار التي تساعدكم في التدرب في تطبيقات لغة البايثون في مجال جعل البرامج أكثر ديناميكية باستخدام مفهوم plugins:
- قم بكتابة plugin آخر ليقوم بطباعة رسائل تحفيزية بالألوان بحيث تكون كل رسالة بملف خاص بها ويكون اسم الملف على اسم الشخص الموكل بالعمل.
- لتكون برامجنا أكثر احترافية و للاستفادة بشكل أكبر مما تعلمنا هنا من مهارات أي كتابة برامج قابلة للبرمجة scriptable، قم ببناء واجهة رسومية متكاملة و اجعل له الامكانية لكتابة اضافاتك من داخل برنامجك نفسه :أن تفتح نافذة تقبل مدخلات نصية لتكتب فيها نصوصك البرمجية لبناء plugins خاصة بك ثم تخزنها أي كأنها نافذة محرر نصوص ضمني داخل برنامجك.
في النهاية، أتمنى أن أكون قد وفقت في تقديم محتوى مفيد والذي قد يكون نادرًا في طرحه خصوصًا على المستوى العربي. حاولت بكل ماأستطيع تبسيط المهارات التي ذكرتها وتبيان أهميتها وندرة التطرق إليها حتى باللغات الأجنبي. فماذا تنتظرون ابنوا و اكتشفوا و ابدعوا. نتمنى مشاركة مقالات السلسلة في منصات التواصل الاجتماعي مثل تويتر وفيسبوك حتى تعم الفائدة.
بارك الله فيك . المشكلة ولا قادرة استوعب وافهم هذا البرنامج . ابني عنده وحدة كاملة في المنهج على برنامج بايثون وتطبيقاته . حتى الاسئلة اختيار من متعدد لاوراق عمل وامتحان . شو الحل ما بعرف
مشكوور . الله يجازيك الخير