المحتوى عن 'بايثون'.



مزيد من الخيارات

  • ابحث بالكلمات المفتاحية

    أضف وسومًا وافصل بينها بفواصل ","
  • ابحث باسم الكاتب

نوع المُحتوى


التصنيفات

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

التصنيفات

  • PHP
    • Laravel
    • ووردبريس
  • جافاسكريبت
    • Node.js
    • jQuery
    • AngularJS
    • Cordova
  • HTML5
  • CSS
    • Sass
    • إطار عمل Bootstrap
  • SQL
  • سي شارب #C
    • منصة Xamarin
  • بايثون
    • Flask
    • Django
  • لغة روبي
    • إطار العمل Ruby on Rails
  • لغة Go
  • لغة جافا
  • لغة Kotlin
  • برمجة أندرويد
  • لغة Swift
  • لغة R
  • سير العمل
    • Git
  • صناعة الألعاب
    • Unity3D
  • مقالات عامّة

التصنيفات

  • تجربة المستخدم
  • الرسوميات
    • إنكسكيب
    • أدوبي إليستريتور
    • كوريل درو
  • التصميم الجرافيكي
    • أدوبي فوتوشوب
    • أدوبي إن ديزاين
    • جيمب
  • التصميم ثلاثي الأبعاد
    • 3Ds Max
    • Blender
  • مقالات عامّة

التصنيفات

  • خواديم
    • الويب HTTP
    • قواعد البيانات
    • البريد الإلكتروني
    • DNS
    • Samba
  • الحوسبة السّحابية
    • Docker
  • إدارة الإعدادات والنّشر
    • Chef
    • Puppet
    • Ansible
  • لينكس
  • FreeBSD
  • حماية
    • الجدران النارية
    • VPN
    • SSH
  • مقالات عامة

التصنيفات

  • التسويق بالأداء
    • أدوات تحليل الزوار
  • تهيئة محركات البحث SEO
  • الشبكات الاجتماعية
  • التسويق بالبريد الالكتروني
  • التسويق الضمني
  • استسراع النمو
  • المبيعات

التصنيفات

  • إدارة مالية
  • الإنتاجية
  • تجارب
  • مشاريع جانبية
  • التعامل مع العملاء
  • الحفاظ على الصحة
  • التسويق الذاتي
  • مقالات عامة

التصنيفات

  • الإنتاجية وسير العمل
    • مايكروسوفت أوفيس
    • ليبر أوفيس
    • جوجل درايف
    • شيربوينت
    • Evernote
    • Trello
  • تطبيقات الويب
    • ووردبريس
    • ماجنتو
  • أندرويد
  • iOS
  • macOS
  • ويندوز

التصنيفات

  • شهادات سيسكو
    • CCNA
  • شهادات مايكروسوفت
  • شهادات Amazon Web Services
  • شهادات ريدهات
    • RHCSA
  • شهادات CompTIA
  • مقالات عامة

أسئلة وأجوبة

  • الأقسام
    • أسئلة ريادة الأعمال
    • أسئلة العمل الحر
    • أسئلة التسويق والمبيعات
    • أسئلة البرمجة
    • أسئلة التصميم
    • أسئلة DevOps
    • أسئلة البرامج والتطبيقات
    • أسئلة الشهادات المتخصصة

التصنيفات

  • ريادة الأعمال
  • العمل الحر
  • التسويق والمبيعات
  • البرمجة
  • التصميم
  • DevOps

تمّ العثور على 22 نتائج

  1. ما هي لغة البرمجة التي يجب عليك تعلمها؟ بايثون، PHP أم روبي؟ ربما أكبر سؤال يواجه مطوري الويب المبتدئين هي ما هي أفضل لغة برمجة يجب تعلمها للوظيفة المستقبلية والآفاق، هنالك العديد من لغات البرمجة التي يجب عليك الاختيار منها وكل واحدة لديها نقاط القوة والضعف، ربما أهم مصدر مقلق هو المدة التي تستغرقه كل لغة للتعلم، وهذا يختلف من لغة إلى أخرى، فما الذي ينبغي تعلمه للحصول على أفضل وظيفة ناجحة في البرمجة؟ عندما بدأتُ تعلم تطوير الويب بحثتُ كثيرا حوله وجعلني هذا مرتبكًا بعض الشيء، فلم أتمكن من الحصول على إجابة نهائية حول ما هي أفضل لغة لأن كل كاتب له وجهة نظر مختلفة، وكان جميع الكتّاب يقارنون اللغات دون إعطاء استنتاج شامل. لذلك، في هذه المقالة، سأقارن بين اللغات البرمجة الحديثة الثلاثة، PHP وبايثون وروبي، وقبل كل شيء، أريد أن أظهر لك بعض البيانات القديمة التي وجدتها عندما بدأت بالتعلم حول تطوير الويب، وهذه البيانات القديمة مأخوذة من هنا وعلى الرغم من قِدَمِهَا إلا أنها تحتوي على بعض الحقائق المفيدة حول تاريخ هذه اللغات. بايثون ضد PHP ضد روبي من هذه المقارنة بين PHP وبايثون وروبي، ستجد أنه من الواضح: الطلب العالي على PHP في السوق. مبرمجي PHP مطلوبين بكثرة. قابلية استخدام PHP ضعيفة. تعلم واستخدام بايثون هو الأسهل. بايثون هي الأسرع. تعلم روبي هو الأصعب. يملك روبي أعلى قابلية استخدام. لكن كما قلت سابقًا، هذه مقارنة مختصرة، ومن هذه المقارنة لا يمكننا الاستنتاج أن PHP هو الأفضل وأن روبي هو الأسوأ، فهنالك أسئلة أخرى لم نرد عليها بعد. ما هي اللغة الأكثر أمانًا؟ ما هي القيود الأخرى على هذه اللغات؟ ما هي مزايا وأشكال الدعم الأخرى لهذه اللغات؟ ما هي نسبة وظيفة/مطور وما متوسط رواتب المطورين؟ ما هي اللغة الأكثر أمانا؟ يعتمد أمن الموقع/التطبيق في المقام الأول على المبرمج وليس لغة البرمجة، فمن المعروف أن PHP هي لغة برمجة غير آمنة، وهذا بسبب أن صياغة PHP ليست بسهولة صياغة بايثون أو روبي، وبسبب هذه الصياغة المعقدة (قابلية القراءة منخفضة) فإن فرص حدوث الأخطاء أكبر. فإذا كان المبرمج/المطور لا يخطئ، فليست PHP لغة غير آمنة، وفي الواقع، لدى PHP5 سمعة طيّبة مقارنة بالإصدارات القديمة، وكنتيجة لذلك، لا يوجد في الواقع استنتاج قوي حول مسألة أمن اللغة. ما هي قيود هذه اللغات؟ PHP: يملك الكثير من الصيغ المطولة من C++/C وبيرل، مع الكثير من الأقواس المعقوفة وعلامات الدولار و “→”. جدول مربك لأسماء الدوال، فتمتلك المكتبة المدمجة مجموعة كبيرة من اتفاقيات التسمية، ويملك الدوال في العادة على بادئة للدلالة على مصدرها (ولكنها لا تمتلك ذلك في كثير من الأحيان). تكون الدوال في العادة في أصناف لمحاكاة مساحات الأسماء (namespace). ليست مناسبة للتطبيقات الكبيرة: صعوبة الصيانة لأنها لا تتكون من وحدات بشكل جيّد. نوع ضعيف: التحويل الضمني قد يفاجئ المبرمجين الغافلين ويؤدي إلى أخطاء غير متوقعة، على سبيل المثال، تتساوى السلاسل “1000” و“1e3” عند المقارنة لأنها تحوّل ضمنيا إلى أعداد كسرية. لغة برمجة سكربتية، ليست لغة برمجة كائنية التوجه. بايثون: لا تملك بيان ‘switch’ ولا هيكل ‘do … while’. عوامل الزيادة والنقصان والتعيين (التعيين هو بيان فقط في بايثون). العامل/البيان الثلاثي (… ? … : …). بيئة مناسبة (مثبتة عادة). لا توجد مبدلات (modifier) خاصة، محمية و عامة للخصائص والأساليب. لا تملك abstract ومبدلات نهائية للأصناف والأساليب. روبي: قد تكون صعبة التعلم. تفتقر إلى موارد المعلومات. وقت المعالج بطيء (وقت CPU) بالمقارنة مع لغات برمجة أخرى. التطوير والتحديث أبطأ. ما هي مزايا وأشكال الدعم الأخرى لهذه اللغات؟ PHP: سهلة التعلم للمبتدئين وللمطورين القادمين من لغات ذات صياغة مشابهة مثل C و C++ و C# وجافا وجافا سكربت، إلخ. تدعم جميع خوادم ويب الرئيسية مثل اباتشي، مايكروسوفت IIS، Netscape و الخوادم الشخصية و خادم iPlanet… الخ. مقبولة للغاية من قبل صناعات عديدة وهي أكثر شعبيّة من بقية لغات البرمجة. سهولة استضافة PHP مباشرة دون أي إعدادات للخادم لأن استضافة المواقع صعبة بالنسبة للمبتدئين. يعتبر إطار zend هو الأشهر في PHP، وبعض الأطر الأخرى مثل Yii وLaravel وCodeigniter أعطت قوة كبيرة لـ PHP. من السهل تطوير أي نوع من CMS بسرعة. بايثون: سهولة الصياغة والقراءة، وسهلة التعلم للذين لا يمتلكون خبرة في البرمجة. لغة برمجة أغراض عامة. لغة برمجة كائنية التوجه. بايثون مناسبة جدا لـ glue. مكتبة قياسية ضخمة، كمثال عشوائي، تملك بايثون محللين لـ XML، قراء وكتّاب لملفات zip وcsv، مكتبات لاستخدام كل بروتوكول إنترنت ونوع بيانات، الخ. هياكل بيانات متطور كالقوائم والقواميس. أطر كبيرة لتطوير الويب مثل جانغو وFlask. روبي: تعتبر روبي لغة كائنية التوجه أكثر من بايثون وPHP. تم تطوير روبي لجعل عمل المطور سهل. تسمح الإضافات الأصناف والوحدات المستدعية بالتوسع والتغيير عن طريق الشيفرة البرمجية الخاصة بالمستخدمة بعد استدعائها، فالأصناف لا تغلق في روبي، حيث يمكنك تغييرها لاحقا. كتل الشيفرة البرمجية الخاصة بروبي أقوى من lambda الخاص ببايثون. كل شيء يرجع قيمة (بما في ذلك بيان ‘if’) ، وبسبب هذا، من السهل كتابة شيفرة برمجية مشابهة للدالة مقارنة بالبايثون وأسهل عند سلسلة الأوامر. مكتبات Gem الخاصة بالروبي، فالكثير من gem المتاحة تجعل فعل أي مهمة سهلةً بأقل جهد. قوة روبي في تطوير الويب هو إطار ريلز، فهو سحري جدًا، فلن تحتاج إلى القلق بشأن الوظائف الأساسية لتطوير الويب مثل التعديل والحذف البسيط، بل يمكنك التركيز على الخوارزميات المعقّدة الأخرى. يعتقد الروبي في إعطاء المبرمج الحرية والقوة. ما هي نسبة وظيفة/مطور وما متوسط رواتب المطورين؟ هذا السؤال شخصي للغاية ولن تكون له إجابة عامة بسيطة، فأغلب الوظائف والمبرمجين يستخدمون PHP، وأدى هذا إلى ضعف الرواتب بصفة عامة، ومع ذلك، فهذا لا يعني أن رواتب جميع المطورين/المبرمجين ضعيف، فبعض المطورين يحصلون على أموالٍ كثيرةٍ. هنالك فرص عمل كثيرة لمبرمجي بايثون وروبي بما أنهم يمتلكون عدد قليل من المبرمجين، لكن الطلب أقل في العادة. استنتاج عام: دعونا نلخص كل هذا باختصار: PHP وبايثون سهل التعلم بالنسبة للمبتدئين. PHP هي الأكثر طلبًا في العمل. PHP جيّدة للمواقع الصغيرة. (على الرغم من أن هنالك الكثير من المواقع الكبيرة مثل فيسبوك و ويكيبيديا مكتوبة بلغة PHP لكن ضمّن إليها لغات أخرى. تغيير موقع من لغة برمجة إلى لغة أخرى ليست مهمة سهلة). بايثون هي أفضل لغة للأغراض العامة. تُفضل إطارات بايثون (جانغو) وروبي (ريلز) أكثر من أي إطار آخر لبرمجة الويب. يمكنك اختيار أي واحدة منهم، فإذا لم تكن تبحث عن هدف كبير فبايثون هي الأفضل ليس فقط بسهولة تعلمها بل لأنها للأغراض العامة وتملك العديد من المميزات الكبيرة مثل هياكل البيانات، لكن جميع لغات البرمجة لديها نطاقات خاصة بها مثل اللاعبين في أي لعبة. ترجمة -وبتصرّف- للمقال PYTHON vs PHP vs RUBY لصاحبه Harish Kumar
  2. تمهيد Python هي لغةٌ سهلة القراءة للغاية ومتنوعة ومتعددة الاستخدامات، واسمها مستوحى من مجموعة كوميدية بريطانية باسم «Monty Python»، وكان أحد الأهداف الأساسية لفريق تطوير بايثون هو جعل اللغة مرحةً وسهلة الاستخدام، وإعدادها بسيطٌ، وطريقة كتابتها مباشرة وتعطيك تقريرًا مباشرًا عند حدوث أخطاء، وهي خيارٌ ممتازٌ للمبتدئين والوافدين الجدد على البرمجة. لغة بايثون هي لغة متعددة الاستعمالات، وتدعم مختلف أنماط البرمجة مثل كتابة السكربتات والبرمجة كائنية التوجه (object-oriented)، وهي مناسبةٌ للأغراض العامة، واستعمالها يتزايد في سوق العمل إذ تعتمدها منظماتٌ مثل «United Space Alliance» (شركة في مجال إرسال مركبات فضائية وتتعاقد معها ناسا) و «Industrial Light & Magic» (أستوديو للتأثيرات السينمائية وللرسوم المتحركة)، وتوفِّر بايثون قدراتٍ كثيرةٍ لمن يريد تعلم لغة برمجة جديدة. طوِّرَت اللغة في نهاية الثمانينات من القرن الماضي، ونُشِرَت أوّل مرة في عام 1991، طُوِّرَت بايثون من قِبل Guido van Rossum، وهو عضوٌ نشطٌ للغاية في المجتمع. وتعتبر بايثون على أنَّها بديلٌ عن لغة ABC، وأوّل إصدار منها كان يتضمن التعامل مع الاستثناءات (exception handling) والدوال والأصناف (classes) مع إمكانية الوراثة فيها. وعدما أُنشِئ منتدى محادثة في Usenet باسم comp.lang.python في 1994، فبدأت قاعدة مستخدمي بايثون بالنمو، مما مهّد الطريق لها لتصبح واحدة من أكثر لغات البرمجة شيوعًا وخصوصًا لتطوير البرمجيات مفتوحة المصدر. لمحة عامة قبل أن ننظر إلى إمكانيات إصدارَي بايثون 2 وبايثون 3 (مع الاختلافات البرمجية الرئيسية بينهما)، فلننظر إلى لمحة تاريخية عن الإصدارات الرئيسية الحديثة من بايثون. بايثون 2 نُشِرَ هذا الإصدار في أواخر عام 2000، وأصبحت بايثون 2 لغة برمجة شاملة مقارنةً بالإصدارات التي تسبقها وذلك بعد تطبيق اقتراح PEP ‏(Python Enhancement Proposal)، وهو مواصفةٌ (specification) تقنيةٌ التي توفِّر معلومات إلى أعضاء مجتمع بايثون أو تصف ميزاتٍ جديدة في اللغة. بالإضافة إلى ذلك، تضمنت بايثون 2 ميزاتٍ برمجية جديدة مثل «cycle-detecting garbage collector» لأتمتة عملية إدارة الذاكرة، وزيادة دعم يونيكود لتدعم اللغة جميع المحارف المعيارية …إلخ. وأثناء عملية تطوير بايثون 2 أضيفت ميزات جديدة بما في ذلك توحيد الأنواع والأصناف في بايثون في بنية هيكلية وحيدة (وذلك في إصدار 2.2 من بايثون). بايثون 3 تُعتَبر بايثون 3 هي مستقبل لغة بايثون وهي النسخة قيد التطوير من اللغة، وهذا إصدارٌ رئيسيٌ نُشِر في أواخر عام 2008 لإصلاح بعض المشاكل الجوهرية في تصميم الإصدارات السابقة من اللغة، وكان التركيز أثناء تطوير بايثون 3 هو تحسين الشيفرات التي تبنى عليها اللغة وحذف التكرارات، مما يعني أنَّ هنالك طريقة وحيدة فقط لإنجاز مهمّة معيّنة. التعديلات الأساسية التي حدثت في بايثون 3.0 تتضمن تغير العبارة print إلى دالة مُضمَّنة باللغة، وتحسين قسمة الأعداد الصحيحة، وتوفير دعم إضافي ليونيكود. في البداية، انتشرت بايثون 3 ببطء نتيجةً لعدم توافقيتها مع بايثون 2، مما يعني أنَّ على المستخدمين اختيار ما هو الإصدار الذي عليهم استخدامه. بالإضافة إلى ذلك، كانت الكثير من المكتبات البرمجية متاحةً فقط لبايثون 2، لكن بعد تقرير فريق تطوير بايثون 3 أنَّه يجب أن التخلي عن دعم بايثون 2، فبدأت عملية تحويل المكتبات إلى بايثون 3. يمكننا معرفة زيادة الاعتماد على بايثون 3 من خلال عدد الحزم البرمجية التي تدعم بايثون 3، والتي هي (في وقت كتابة هذا المقال) 339 من أصل 360 من أشهر الحزم. بايثون 2.7 بعد إصدار بايثون 3.0 في 2008، أُصدِرَت نسخة بايثون 2.7 في تموز 2010 وهي آخر إصدار من سلسلة ‎2.x، الغرض من إصدار بايثون 2.7 هو جعل الطريق ممهدًا أمام مستخدمي بايثون ‎2.x لتحويل برامجهم إلى بايثون 3 بتوفير بعض التوافقية بينهما. وهذه التوافقية تضمنت دعم بعض الوحدات المُحسّنة في 2.7 مثل unittest لأتمتة الاختبارات، و argparse لتفسير خيارات سطر الأوامر، وبعض الفئات في collections. ولخصوصية بايثون 2.7 ولكونها جسرًا واصلًا بين الإصدارات القديمة من بايثون 2 وبين بايثون 3.0، فأصبحت خيارًا شائعًا بين المبرمجين بسبب توافقيتها مع الكثير من المكتبات. عندما نتحدث اليوم عن بايثون 2، فنحن نشير عادةً إلى إصدار بايثون 2.7 لأنَّه أكثر إصدار مستخدم؛ لكنه يُعتَبَر أنَّه إصدارٌ قديم، وسيتوقف تطويره (التطوير الحالي هو إصلاح العلل فقط) تمامًا في 2020. الاختلافات الأساسية بغض النظر أنَّ بايثون 2.7 وبايثون 3 تتشاركان في الكثير من الأشياء، لكن لا يجدر بك أن تظن أنَّهما متماثلتان ويمكن تبديل الشيفرات بينهما. وعلى الرغم من أنَّك تستطيع كتابة شيفرات جيدة وبرامج مفيدة في أيّ إصدار منهما، لكن من المهم أن تفهم أنَّ هنالك بعض الاختلافات في بنية الشيفرات وفي طريقة تفسيرها. سأعرض هنا بعض الأمثلة، لكن عليك أن تعلم أنَّك ستواجه المزيد من الاختلافات أثناء مسيرة تعلمك لبايثون. print في بايثون 2، تُعامَل print كتعبيرٍ برمجيٍ بدلًا من كونها دالة، وهذا كان يثير ارتباكًا لأنَّ الكثير من الأمور داخل بايثون تتطلب تمرير وسائط (arguments) بين قوسين، إذا فتحتَ مُفسِّر بايثون 2 لطباعة «Sammy the Shark is my favorite sea creature»، فستكتب تعبير print الآتي: print "Sammy the Shark is my favorite sea creature" أما في بايثون 3، فستُعامَل print()‎ كدالة، لذا لطباعة السلسلة النصية السابقة، فيمكننا استخدام شكل استدعاء الدوال التقليدي كما يلي: print("Sammy the Shark is my favorite sea creature") هذا التعديل جعل من البنية اللغوية في بايثون موحدةً وسهَّلَ من التبديل بين مختلف دوال الطباعة فيها. يجدر بالذكر أنَّ الدالة print()‎ متوافقة مع بايثون 2.7، لذا ستعمل شيفرات بايثون التي تستعمل print()‎ بشكلٍ صحيحٍ في أيّ الإصدارَين. قسمة الأعداد الصحيحة في بايثون 2، أيُّ عددٍ تكتبه دون فواصل عشرية سيُعامَل على أنَّه من النوع integer، تأتي الإشكالية عندما تحاول قسمة الأعداد الصحيحة على بعضها، فتتوقع في بعض الأحيان حصولك على عددٍ عشري (تسمى أيضًا بالأعداد ذات الفاصلة العائمة float) كما في التعبير الرياضي: 5 / 2 = 2.5 لكن الأعداد الصحيحة في بايثون 2 لن تتحول إلى أعداد عشرية عندما تتطلب العملية التي تُجرى عليها ذلك. عندما يكون العددان الموجودان على جانبَي معامل القسمة / عددين صحيحين، فإن بايثون 2 ستجري عملية القسم وستُنتِج عددًا عشريًا إلا أنها ستُعيد العدد الصحيح الأصغر أو المساوي للناتج، وهذا يعني أنَّه لو كتبتَ ‎5 / 2 فستُعيد بايثون 2.7 العدد الصحيح الأصغر أو المساوي للعدد 2.5، وهو في هذه الحالة 2: a = 5 / 2 print a 2 لإعادة عدد عشري، فيجب إضافة فواصل عشرية إلى الأرقام التي ستُجري عليها عملية القسمة كما في ‎5.0 / 2.0 لكي تحصل على النتيجة المنطقية 2.5. أما في بايثون 3، فقسمة الأعداد الصحيحة أصبحت كما نتوقع: a = 5 / 2 print a 2.5 يمكنك استخدام ‎5.0 / 2.0 لإعادة 2.5، لكن إن أردتَ تقريب ناتج القسمة فاستخدم المعامل // الموجود في بايثون 3، كالآتي: a = 5 // 2 print a 2 هذا التعديل في بايثون 3 جعل من قسمة الأعداد الصحيحة أمرًا سهلًا، لكن هذه الميزة غير متوافقة مع بايثون 2.7. دعم محارف يونيكود عندما تتعامل لغات البرمجة مع السلاسل النصية (strings، والتي هي سلسلةٌ من المحارف)، فهي تفعل ذلك بطرائق مختلفة لكي تتمكن الحواسيب من تحويل الأعداد إلى أحرف ورموز. تستعمل بايثون 2 محارف ASCII افتراضيًا، لذا عندما تكتب "Hello, Sammy!‎" فستتعامل بايثون 2 مع السلسلة النصية كمجموعة من محارف ASCII، والتي هي محدودةٌ لحوالي مئتَي محرف، أي أنَّ محارف ASCII هي طريقة غير عملية لترميز المحارف خصوصًا المحارف غير اللاتينية (كالعربية مثلًا). لاستخدام ترميز محارف يونيكود (Unicode) الذي يدعم أكثر من 128000 محرف تابع للكثير من اللغات والرموز، فعليك أن تكتب u"Hello, Sammy!‎"‎ حيث تُشير السابقة u إلى Unicode. تستعمل بايثون 3 محارف يونيكود (Unicode) افتراضيًا، مما يوفِّر عليك بعض الوقت أثناء التطوير، ويمكنك كتابة وعرض عدد أكبر بكثير من المحارف في برنامجك بسهولة. يدعم يونيكود الكثير من المحارف بما في ذلك الوجوه التعبيرية (emojis)، واستعمالها كترميز محارف افتراضي يعني أنَّ الأجهزة المحمولة ستكون مدعومةً في مشاريعك تلقائيًا. إذا كنت تحب أنَّ تكون شيفرات بايثون 3 التي تكتبها متوافقةً مع بايثون 2، فأبقِ على حرف u قبل السلاسل النصية. استمرار التطوير الفارق الرئيسي بين بايثون 3 وبايثون 2 ليس في البنية اللغوية وإنما في أنَّ إصدار بايثون 2.7 سيتوقف دعمه في 2020، وسيستمر تطوير بايثون 3 بميزاتٍ جديدة وإصلاحٍ لمزيدٍ من العلل. التطويرات الأخيرة في اللغة تتضمن تخصيصًا أبسط لإنشاء الأصناف، وطريقةً أوضح للتعامل مع المصفوفات… الاستمرار بتطوير بايثون 3 يعني أنَّ المطورين يمكن أن يعتمدوا على اللغة، وسيطمئنون أنَّ المشاكل التي قد تحدث فيها ستُحَل في فترةٍ قريبة، ويمكن أن تصبح البرامج أكثر كفاءة بإضافة المزيد من الميزات للغة. نقاطٌ أخرى يجب أخذها بعين الاعتبار عليك أن تضع النقاط الآتية بعين الاعتبار عندما تبدأ مشوارك كمبرمج بلغة بايثون، أو عندما تبدأ بتعلم لغة بايثون بعد تعلمك لغيرها. إذا كنتَ تأمل بتعلم اللغة دون أن تفكِّر بمشروعٍ معيّن، فأنصحك بالتفكير بمستقبل بايثون، فسيستمر تطوير ودعم بايثون 3 بينما سيوقف دعم بايثون 2.7 عمّا قريب. أما إذا كنتَ تُخطِّط للانضمام لفريق تطوير أحد المشاريع، فعليك أن تنظر ما هو إصدار بايثون المستخدم فيه، وكيف يؤدي اختلاف الإصدار إلى اختلاف طريقة تعاملك مع الشيفرات، وإذا ما كانت المكتبات البرمجية المستعملة في المشروع مدعومةً في مختلف الإصدارات، وما هي تفاصيل المشروع نفسه… إذا كنت تُفكّر ببدء أحد المشاريع، فيجدر بك أن تنظر ما هي المكتبات المتوفرة وما هي إصدارات بايثون المدعومة. وكما قلنا سابقًا، الإصدارات الأوليّة من بايثون 3 لها توافقية أقل مع المكتبات المبنية لبايثون 2، لكن الكثير منها قد جرى تحويله إلى بايثون 3، وسيستمر ذلك في السنوات الأربع المقبلة. الخلاصة لغة بايثون كبيرة جدًا وموثقة توثيقًا ممتازًا وسهلة التعلم، ومهما كان اختيارك (بايثون 2 أو بايثون 3) فستتمكن من العمل على المشاريع الموجودة حاليًا. صحيحٌ أنّ هنالك بعض الاختلافات المحورية، لكن ليس من الصعب الانتقال من بايثون 3 إلى بايثون 2، وستجد عادةً أنَّ بايثون 2.7 قادرة على تشغيل شيفرات بايثون 3، خصوصًا في بدايات تعلمك للغة. من المهم أن تبقي ببالك أنَّ تركيز المطورين والمجتمع أصبح منصبًّا على بايثون 3، وسيصبح هذه اللغة رائدةً في المستقبل وستلبي الاحتياجات البرمجية المطلوبة، وأنَّ دعم بايثون 2.7 سيقل مع مرور الزمن إلى أن يزول في 2020. ترجمة -وبتصرّف- للمقال [Python 2 vs Python 3: Practical Considerations] لصاحبته Lisa Tagliaferri
  3. مقدّمة بعد أن ألقينا نظرة على كيفيّة استخدام إطار العمل Flask لإنشاء تطبيقات ويب بسيطة بالاستعانة بقاعدة بيانات SQLite، سنبدأ هذه السّلسلة بالدّخول إلى عالم إضافات Flask التّي ستسهّل علينا الكثير من المهام كإعداد نظام لتسجيل الدّخول والخروج، والتّعامل مع نظام قاعدة بيانات، وكذلك التّحكم في تطوير التّطبيق عن طريق سطر الأوامر؛ وكذلك استعمال أدوات لتطوير تطبيق أكثر أمانا. سنتطرّق أيضا إلى بعض المفاهيم المتقدّمة كتشفير كلمات المرور وتهجير قواعد البيانات وغير ذلك. صحيح بأنّ هذه السّلسلة مطولة نوعا ما إلا أنّها ستكون شاملة لمُساعدتك على تطوير أي تطبيق يمر على خاطرك أو يطلبه منك أحد عملائك. وإن كنت جديدا إلى عالم تطوير الويب فستتعلّم من هذه السّلسلة ما يكفي لتبدأ مشوار العمل كمطوّر تطبيقات ويب سواء عن طريق إنجاز مشاريع لعملاء على منصّات العمل الحر كمنصّة مُستقل أو بناء مشاريعك الخاصّة. سنقوم في هذا الدّرس بالتّعرف على فكرة وبنية التّطبيق الذي سنبنيه في رحلتنا هذه. المُتطلّبات بالإضافة إلى أساسيّات إطار العمل Flask، ستحتاج كذلك إلى معرفة كيفيّة التّعامل مع نماذج HTML عبر مكتبة WTForms وإضافة Flask-WTF ويُمكنك الاطّلاع على سلسلة دروس خاصّة بهذا الموضوع على الأكاديميّة. سلاسل الدّروس التّي يجب عليك أن تطّلع عليها لفهم أفضل لهذه السّلسلة من الدّروس المُتقدّمة نوعا ما، عليك أن تطّلع وتطبّق سلاسل الدّروس التّاليّة: سلسلة مدخل إلى إطار العمل Flask درس إنشاء تطبيق لاختصار الرّوابط باستخدام إطار العمل Flask بجزئيه الأول و الثاني. سلسلة التّحقق من مُدخلات المُستخدم باستخدام مكتبة WTForms وإضافة Flask-WTF ستكون لغة جافاسكربت مُفيدة كذلك، ولا مفرّ من إتقانها إن كنت ترغب بأن تُصبح مُطور ويب أفضل، كما أنّني لن أشرح كل كبيرة وصغيرة عند التّعامل معها في التّطبيق، وهذا لأنّ الهدف من السّلسلة هو تعليمك كيفيّة إتقان التّعامل مع إطار العمل فلاسك وهذا بالطّبع لا يشمل شيفرة جافاسكربت. ستحتاج كذلك إلى تعلّم أداة Git لإدارة نُسَخ التّطبيق والتّعامل مع التّطبيق بعد نشره على منصّة Heroku. ما الذي ستتعلّمه من هذه السّلسلة؟ ستتعلم في هذه السّلسلة تقنيات متقدّمة لإدارة مشاريع تطبيقات الويب، وكيفيّة التّعامل مع قاعدة بيانات PostgreSQL وأداة SQLAlchemy لإدارة الجداول (إضافة، قراءة، تعديل وحذف البيانات)، وكذلك الطرق البسيطة لتهجير قواعد البيانات Database Migration وستتعرّف كذلك على طرق توزيع ملفّات التّطبيق على شكل وحدات وحزم لتنظيم أكثر. سنستخدم كذلك مكتبة WTForms لإدارة نماذج HTML وجعلها أكثر أمانًا للحماية من هجمات مُحتملة من المُخرّبين والمُخترقين. وسنعد كذلك نظامًا أكثر أمانًا لتسجيل الدّخول واستيثاق المُستخدمين، وسنتطرّق كذلك إلى كيفيّة نشر التّطبيق إلى منصّة Heroku لتربطه بعد ذلك باسم نطاق خاصّ إن أردت ذلك. ستتعلّم كذلك طريقة حماية كلمات المرور عن طريق تشفيرها في قاعدة البيانات باستعمال خوارزميّة Bcrypt للتّشفير، وذلك لتجنّب حفظها كنصّ مجرّد يسهل استخدامه من طرف المُخترق إذا وصل إلى قاعدة البيانات. وقد تعرّفنا سابقًا على كيفيّة استعمال الجلسات Sessions لإنشاء نظام تسجيل دخول وخروج بسيط، صحيح بأنّ ذلك النّظام يعمل بشكل جيّد، إلّا أنّه لا يعد آمنًا، ويُمكن أن يتعرّض تطبيقنا لهجمات كثيرة من قبل المُخترقين، ولحماية العضويات والبيانات في الموقع، سيتوجّب علينا أن نُدير الجلسات بطريقة أكثر تعقيدًا، لكنّ هناك إضافة لإطار العمل فلاسك لتبسيط هذا الأمر ولن نحتاج إلى العمل على ذلك بأنفسنا، وبالتّالي فسيُصبح تطبيقنا أكثر أمانًا دون عناء كبير، وكلّ هذا وأكثر سنتعلّمه بتفصيل أكبر في الدّروس القادمة. بنية التّطبيق التّطبيق الذي سنعمل عليه في هذه السّلسلة من الدّروس عبارة عن نظام إدارة محتوى ومنصّة للتّدوين الجماعي، ستكون هناك بعض الميّزات الفريدة وستكون هناك ميّزات أخرى مفقودة، إذا سبق لك وأن تعاملت مع أحد أنظمة التّدوين الأخرى كمنصّة ووردبريس WordPress، Blogger أو Tumblr أو حتى منصّة medium فستتمكّن بنهاية هذه السّلسلة من التّخلي عن هذه المنصّات وإنشاء منصّة بسيطة خاصّة بك لتكتب عليها، أو تستطيع تعديل المشروع بعد الانتهاء منه لتُضيف ميّزات أخرى أو تُطبّق فكرة فريدة لتطرح مشروعًا على أرض الواقع لتتمكّن من الاستفادة منه ماديّا إن أردت ذلك. سيتمكّن مُستخدمو المنصّة من إنشاء حساب خاصّ بهم لينشروا مقالاتهم التّي يكتبونها، إضافة المقالات ستتمّ عن طريق كتابتها بتنسيق الماركداون Markdown ومن ثمّ نشرها، سيتمكّن كلّ مُستخدم من الحصول على رابط خاصّ بمقالاته لنشرها للآخرين، سيتمكّن الكاتب من إضافة وسوم لمقالاته، وكذلك إدراجها ضمن قسم معيّن، لكل مقالة قسم للتّعليقات ليتمكّن المُستخدمون الآخرون من التّعليق على مقال معيّن. سيكون للتّطبيق نكهة اجتماعيّة، بحيث سيتمكن المُستخدمون من مُتابعة بعضهم البعض، وكذلك إضافة مقالات إلى المُفضّلة والإعجاب بها لنتمكّن من فرزها وترتيبها حسب الأكثر إعجابًا، الأكثر نشاطًا (أكبر عدد من التعليقات) وبعدها ستتمكّن من إضافة خاصيّات أخرى بنفسك باتّباع نفس الطّريقة، مثلًا بعد الانتهاء من التّطبيق ستتمكّن من تطبيق فكرة ترتيب المقالات حسب الأكثر إعجابًا لإضافة خاصيّات أخرى (الأكثر شعبيّة حسب عدد التّعليقات، الأكثر زيارة...). صحيح بأنّنا سنبني تطبيقًا مُعقّدا وكبيرًا، إلّا أنّني لن أشرح كلّ شيء بتفصيل ممل، سأشرح بالتّفصيل فقط الأفكار الجديدة وما تراه لأوّل مرّة حتى لا تكون هذه السّلسلة أطول من اللازم، خاصّة وأنّ بعض الأساليب ستكون مُشابهة جدّا لبعضها البعض، فمثلاً طريقة السّماح للمُستخدم بإضافة مقال خاص به مُشابهة جدّا لطريقة فرز المقالات حسب قسم مُعيّن (لكل مُستخدم مقالاته ولكلّ قسم مقالاته كذلك). سنضع للتّطبيق بعض الميّزات المُفيدة كنظام أرشفة لتأريخ كلّ مقال حسب تاريخ إضافته، كما سيكون لتعليقات المقال نظام مُشابه، وسنستغل نفس الطّريقة لتخصيص تاريخ انضمام للمُستخدم. في النّهاية، تذكّر بأنّ هذه السّلسلة من الدّروس ستكون تطبيقيّة بالدّرجة الأولى، وستتعلّم فيها كيفيّة بدء مشاريعك التّطويريّة الخاصّة بك بلغة بايثون وإطار فلاسك، أمّا كيفيّة الاستفادة القصوى منها فمعروفة، عليك تطبيق ما تعلّمته وتختبر مع إضافة ميّزات ولو لم أذكرها، وإن أردت معرفة معمّقة عن أي شيء تحدّثت عنه دون أن أفصّل، يُمكنك دائما العودة إلى التّوثيق الرّسمي للأدوات والمكتبات والإضافات المعنيّة بالأمر، وإن كان لك سؤال معيّن فلا تتردّد في طرحه على قسم الأسئلة والأجوبة على الأكاديميّة. هناك المزيد الدّروس التّي ستندرج تحت هذه السّلسلة لن تُغطي فقط ما قرَأتَهُ للتّو، بل أكثر من ذلك، فهدفي من كتابة سلسلة الدّروس هذه هو تغطيّة الفراغ الموجود في الويب العربي، إذ أنّ التّوثيقات الرّسميّة للمكتبات وأطر العمل المُستعملة حاليّا عادة ما تكون مكتوبة باللغة الانجليزيّة فقط، لذا بتوفير سلسلة دروس كهذه ستمتلك أكبر قدر مُمكن من المُساعدة لتتمكّن من العمل على تطبيقاتك الخاصّة دون أن تضطر إلى اتّباع سلسلة دروس أخرى أو الاطّلاع على التّوثيقات الرّسميّة التّي عادة ما تكون مُفيدة أكثر إذا ما أردت أن تُنجز شيئًا بسيطًا، وعلى العكس من ذلك، فكتابة تطبيق كامل (كما في هذه السّلسلة) طريقة أفضل للتّعلم. ختاما هذا المقال عبارة عن مُقدّمة بسيطة لما سنخوضه في قادم الدّروس، في الدّرس القادم، ستبدأ المُتعة مع استكشاف كيفيّة التّعامل مع ملفّات ومُجلّدات التّطبيقات الكبيرة والمُعقّدة بطريقة بسيطة.
  4. بعد أن تعرفنا في الدرس الأول على طريقة تثبيت Django وإنشاء مشروعنا الأول فيه، سنشرع في هذا الدرس في إنشاء تطبيقنا الأول والذي سيكون عبارة عن موقع بسيط للاقتراعات يتكون من قسمين: القسم الأول: واجهة يمكن للمستخدم أن يطلع من خلالها على الأسئلة المطروحة واختيار الإجابة التي يرغب فيها. أما القسم الثاني: لوحة تحكم يمكن من خلالها إضافة الأسئلة وتعديلها وحذفها وإضافة الأجوبة وغير ذلك من الأمور. المشاريع Projects والتطبيقات Applications قبل أن ندخل في تفاصيل إنشاء تطبيق الاقتراعات، لا بأس في الحديث بشكل موجز عن مفهومي "المشروع" Project و"التّطبيق" Application في Django. يمثّل المشروع تطبيق الويب الذي يتم إنشاؤه بواسطة Django، ويتم تعريفه من خلال ملف الإعدادات Settings، فكما رأينا في الدرس السابق فبعد تنفيذ الأمر: django-admin startproject mysite تم إنشاء حزمة بايثون تحتوي على ملفات settings.py و urls.py و wsgi.py، وعادة ما تتوسع هذه الحزمة بإضافة المزيد من الملفات مثل ملفات CSS والقوالب وما إلى ذلك من الأمور التي لا تكون مرتبطة بتطبيق معيّن. وعادة ما يكون مجلّد المشروع هذا (المجلد الذي يحتوي على الملف manage.py) حاويًا للتطبيقات التي يتم إنشاؤها بشكل مستقل، وهذه التطبيقات ما هي إلا حزم بايثون تعمل على تقديم بعض الخصائص وتؤدي بعض المهام، ويمكن استخدام هذه التطبيقات في مشاريع متعددة، وهذا ما يسمى بمبدأ قابلية إعادة الاستخدام re-usability. إنشاء تطبيق الاقتراعات ملاحظة: ابتدءًا من هذا الدرس فإن عبارة "مجلد المشروع" تعني المجلد الذي يحتوي على ملف manage.py. توجّه في سطر الأوامر إلى مجلد المشروع ثم اكتب الأمر التالي: python manage.py startapp polls يمكن الحصول على نفس النتيجة من خلال الأمر التالي: django-admin startapp polls بعد تنفيذ الأمر ستجد أنّ إطار العمل قد أنشأ مجلدًا جديدًا يحمل الاسم polls، ويتضمن عددًا من الملفات نستعرضها بشكل مختصر: init__.py__: هذا الملف مشابه للملف الموجود في مجلد المشروع، وهو ملف فارغ يعني وجوده أن هذا المجلد هو حزمة من حزم بايثون. admin.py: يمكن من خلال هذا الملف إدارة وتخصيص لوحة التحكم والتي تأتي جاهزة مع التطبيق. apps.py: يمكن من خلال هذا الملف إعداد التطبيق configuration لاستخدامه في مشاريع أخرى. models.py: سيتضمن هذا الملف النماذج التي يتعامل التطبيق معها، والتي تكون مسؤولة عن إنشاء جداول قواعد البيانات. tests.py: يمكن من خلال هذا الملف إجراء الاختبارات Tests على التطبيق. views.py: تضاف في هذا الملف العروض المسؤولة عن تحديد البيانات والمعلومات التي سيتم عرضها على المتصفح، وهي كذلك صلة الوصل بين المسارات والقوالب. مجلد migrations: سيستقبل هذا المجلد الملفات الناشئة عن عملية تهجير قاعدة البيانات. إعدادات المشروع يحتوي مجلد المشروع على ملف الإعدادات settings.py، وهو عبارة عن ملف بايثون يحتوي جميع الإعدادات الخاصة بالمشروع، وسنستعرض بعض محتويات هذا الملف بشكل موجز. BASE_DIR: متغير نصّي يقدّم مسار المجلد الأساسي للمشروع، ويمكن الاستفادة من هذا المتغير في تحديد مسارات المجلدات التي تحتوي على القوالب أو الملفات الساكنة وغيرها، وسنتعرف على طريقة استخدامه عند الحديث عن القوالب. SECRET_KEY: عبارة عن سلسلة نصية من حروف ورموز عشوائية يمكن الاستفادة منها في حماية التطبيق. DEBUG: متغير من نوع bool، ويمكن من خلاله التحكم في وضع التنقيح Debugging، حيث تظهر معلومات مفيدة عند حدوث الأخطاء، ولكن ينصح بتغيير قيمته إلى False عند نقل المشروع إلى بيئة الإنتاج. INSTALLED_APPS: عبارة عن قائمة تتضمن التطبيقات التي سيضمها المشروع الحالي، ويمكنك أن تلاحظ وجود عدد من التطبيقات المثبتة بشكل مسبق، مثل إدارة لوحة التحكم admin، والاستيثاق auth، والجلسات sessions وغيرها. TEMPLATES: عبارة عن قائمة تتضمن إعدادات القوالب المستخدمة في المشروع، وما يهمنا فيها هو العنصر DIRS والذي يتم من خلاله تعيين المسارات التي تحتوي على ملفات القالب. DATABASES: قائمة أخرى مسؤولة عن تحديد المعلومات اللازمة للتعامل مع قواعد البيانات، وسنتطرق إليها عند الحديث عن النماذج Models والاتصال بقواعد البيانات. LANGUAGE_CODE: يمكن من خلال هذا المتغير تحديد لغة واجهة لوحة التحكم، والإعداد الافتراضي هنا هو اللغة الإنكليزية، ولكن Django يدعم العديد من اللغات ومن ضمنها العربية، وإن كنت ترغب في استخدام اللغة العربية في عرض عناصر لوحة التحكم، فيمكنك تغيير قيمة هذا المتغير بالشكل التالي: LANGUAGE_CODE = 'ar' TIME_ZONE: يمكن من خلال هذا المتغيير تعيين المنطقة الزمنية التي سيستخدمها Django في دوال الوقت والتاريخ. ويمكن استبدال هذه القيمة حسب الرغبة. STATIC_URL: في هذا المتغير يتم تحديد مسار المجلد الذي يحتوي على الملفات الساكنة وهي ملفات CSS و Javascript والخطوط والصور وغيرها. كتابة العرض الأول العرض View عبارة عن دالة مكتوبة بلغة Python (أو صنف كما سنرى في الدروس اللاحقة) يمكن تلخيص عملها ببساطة في أنها تأخذ الطلبات Requests التي يرسلها العميل وتقوم بإرجاع الإجابة response والتي يمكن أن تكون على هيئة شيفرة بصيغة HTML، أو إعادة توجيه لصفحة أخرى، أو صفحة خطأ 404، أو ملف XML، أو صورة أو أي شي آخر. لنبدأ الآن بكتابة العرض الأول في مشروعنا، وللقيام بذلك افتح ملف polls/view.s.py في محرر النصوص المفضّل لديك، ثم امسح محتوياته واكتب الشيفرة التالية: from django.http import HttpResponse def index(request): html = "مرحبًا بك في تطبيق الاقتراعات، هذه هي الصفحة الرئيسية." return HttpResponse(html) في السطر الأول من هذه الشيفرة قمنا باستيراد الصنف HttpResponse من وحدة django.http، وهو المسؤول عن التعامل مع الاستجابة التي ترد على الطلب الذي أرسلناه إلى الخادوم من خلال الدالة index، وذلك عن طريق تمرير المعامل request عند تعريف الدالة. ستقوم هذه الدالة بإعادة العنصر HttpResponse والذي يحتوي على الإجابة، وهي في مثالنا هذا عبارة عن سلسلة نصية بسيطة. ملاحظة: في حال عدم ظهور الأحرف العربية بشكل صحيح، أضف السطر التالي إلى بداية ملف views.py: # -*- coding:utf8 -*- لنتمكن من مشاهدة النتيجة على المتصفح، يجب أن نربط هذا العرض بمسار معين؛ وللقيام بذلك توجه إلى الملف mysite/urls.py وعدّل محتوياته لتصبح بالشكل التالي: from django.conf.urls import url from django.contrib import admin from polls import views urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^polls/', views.index), ] يتضمن هذا الملف جميع المسارات التي سنستخدمها في المشروع، وهو بمثابة جدول لمحتويات الموقع. في البداية قمنا باستيراد محتويات ملف views.py الموجود في مجلد polls من خلال الشيفرة التالية: from polls import views من خلال هذه الشيفرة يمكنك أن تلاحظ أن Django يتعامل مع المجلد polls باعتباره حزمة من حزم بايثون، وذلك لاحتواءه على ملف init__.py__ كما ذكرنا سابقًا. بهذا الطريقة يمكننا الوصول إلى دالة index التي أنشأناها قبل قليل في ملف views.py الموجود في مجلد polls (أو حزمة polls لنكون أكثر دقة) وذلك تمهيدًا لربطها بالمسار الذي نرغب فيه. أضفنا كذلك الشيفرة التالية إلى قائمة urlpatterns: url(r'/polls', views.index), وهي عبارة عن دالة وظيفتها ربط المسار الذي نحدده في المعامل الأول بالعرض الذي نحدده في المعامل الثاني. لاحظ أن المسار عبارة عن سلسلة نصية مسبوقة بحرف r صغير وذلك لإخبار بايثون بأن يتعامل مع هذه السلسلة النصية على أنّها سلسلة خام raw، بمعنى أنه سيتم تجاوز جميع العلامات الخاصة المستخدمة في هذه السلسلة، وهذا ضروري جدًّا، لأن Django يستخدم التعبيرات النظامية Regular Expressions في تحديد المسارات وتمرير المتغيرات، وهذه التعبيرات تستخدم الكثير من الرموز التي يجب تجاوزها لتعمل الشيفرة بالشكل الصحيح. سنتعرف على المسارات وآلية عملها وكيفية استخدام التعبيرات النظامية، في الدروس اللاحقة. يمكنك الآن التوجه إلى مجلد المشروع وتشغيل الخادوم الخاص بـ Django عن طريق سطر الأوامر من خلال الأمر التالي: python manage.py runserver انتقل في المتصفح إلى العنوان التالي: http://127.0.0.1:8000/polls لتشاهد عبارة الترحيب في واجهة الموقع. يمكننا استخدام شيفرة HTML ضمن السلسلة النصية التي ترجعها دالة العرض، وللقيام بذلك افتح ملف polls/view.py وعدّله ليصبح بالشكل التالي: from django.http import HttpResponse def index(request): html = """ <html dir="rtl"> <head> <title>تطبيق الاقتراعات</title> </head> <body> <h1>تطبيق الاقتراعات</h1> <p>مرحبًا بك في تطبيق الاقتراعات، هذه هي الصفحة الرئيسية.</p> </body> </html> """ return HttpResponse(html) من المؤكد أن التطبيقات التي نراها على صفحات الإنترنت لا تتمتع بهذه البساطة الشديدة، وهذا يعني أن استخدام شيفرة HTML ضمن دالة العرض أمر غير عملي على الإطلاق، وهنا تظهر الحاجة إلى فصل هذه الشيفرات عن العروض وهذه هي وظيفة القوالب Templates والتي سنتعرف إليها في الدروس اللاحقة. خاتمة تعرفنا في هذا الدرس على مفهومي المشروع والتطبيق في Django، وقمنا بكتابة العرض الأول وتعرفنا بشكل مختصر على المسارات Urls. سنتعرف في الدرس القادم على كيفية التعامل مع قواعد البيانات من خلال النماذج Models، وكذلك سنتعرف على كيفية تهجير قواعد البيانات، وكذلك الاستعلام عن البيانات برمجيًا، وذلك لتهيئة قاعدة البيانات التي سنستخدمها في تطبيق الاقتراعات.
  5. Django هو إطار عمل مجّاني ومفتوح المصدر، مكتوب بلغة Python، وتتبع المشاريع فيه بنية Model-View-Template (عادة ما تختصر إلى MVT). يؤكّد Django على قابلية إعادة الاستخدام Reusability للمكونات وكذلك على التطوير السريع، بالإضافة إلى مبدأ عدم التكرار. تستخدم لغة Python في جميع مفاصل إطار العمل هذا، كالإعدادات ونماذج قواعد البيانات وغيرها. ومن أشهر المواقع التي تستخدم Django هي: Pinterest ،Instagram ،Mozilla ،The Washington Times ،Disqus ،National Geographic وغيرها الكثير. طوّر Django سنة 2003 على يدي المبرمجين Adrian Holovaty و Simon Willson اللذين يعملان في صحيفة Lawrence Journal World، وذلك عندما انتقلا إلى لغة Python لبناء التطبيقات. ثم أطلق Django سنة 2005 تحت رخصة BSD، وقد سمّي بهذا الاسم تيمنًا بعازف الغيتار Django Reinhardt. بنية MVT تنقسم بنية المشاريع في Django إلى ثلاثة أقسام مرتبطة ببعضها البعض، ولكنّها مختلفة عن أطر العمل الأخرى التي تتبع بنية (MVC - Model, View, Controller) مثل Laravel في PHP وغيرها، حيث تتكون المشاريع في Django من النموذج Model والعرض View والقالب Template. يتولى قسم النموذج معالجة البيانات والتعامل معها واسترجاعها، ويدعم Django العديد من قواعد البيانات، مثل: SQlite ،MySQL، و PostgreSQL. أما العرض فعبارة عن مجموعة من دوال Python التي تستجيب لعنوان URL معين، ووظيفة العرض هي تحديد البيانات والمعلومات التي يجب عرضها. أما القالب فهو عبارة عن ملف بصيغة HTML يتم من خلاله تحديد الطريقة التي ستظهر بها المعلومات التي يعرضها قسم العرض. أين المتحكم Controller إذًا؟ المتحكم هنا هو إطار العمل نفسه، أي الآلية التي يتم من خلالها إرسال الطلب إلى العرض المناسب بالاعتماد على عنوان URL محدّد. تثبيت Django إطار العمل Django هو إحدى الحزم الخاصة بلغة البرمجة بايثون، وتوفّر هذه اللغة مدير حزم خاصّ يدعى pip يتم من خلاله تثبيت وتحديث وإزالة الحزم بسهولة ويسر؛ لذا ستكون الخطوة الأولى في تثبيت Django هي التأكد من وجود مدير الحزم pip وتثبيته إن لم يكن متوفّرًا. تنصيب pip لتنصيب إطار العمل Django ستحتاج إلى مدير الحزم الخاصّ بـ Python وهو pip، ولحسن الحظّ فإن pip متوفّر في نسخة Python 2.7.9 وما بعدها، وفي نسخة Python 3.4 وما بعدها. في حال عدم توفّر pip في نسخة Python المنصّبة لديك يمكنك تنصيبه باتباع الخطوات التالية: حمّل الملفّ get-pip.py. توجه في سطر الأوامر إلى المكان الذي حملت فيه الملف السابق، ثم اكتب التعليمة التالية: python get-pip.py استخدام سطر الأوامر لنجرب الآن استخدام مدير الحزم في بايثون لتنصيب Django، توجّه الآن إلى سطر الأوامر ثم اكتب الأمر: pip install django==1.9 هل ظهرت لك رسالة خطأ؟ ما المشكلة، ألم نقم بتنصيب pip قبل قليل؟ هذا صحيح، ولكننا لم نخبر سطر الأوامر بأن يوجّه أي تعليمة تبدأ بكلمة pip إلى مدير حزم بايثون، وللقيام بذلك اتبع الخطوات التالية: في أوبنتو: يجب تنصيب حزمة python3-pip إن كنت تستخدم الإصدار الثالث من بايثون أو python-pip للإصدار الثاني من بايثون، لتتمكن من استخدام pip في سطر الأوامر في أبونتو، وللقيام بذلك اكتب الأمر التالي في سطر الأوامر: sudo apt-get install python3-pip أدخل كلمة المرور الخاصة بك، وستبدأ عملية التثبيت، وبعد الانتهاء يمكنك تنصيب أي حزمة خاصة بلغة بايثون عن طريق سطر الأوامر مباشرة. في نظام Windows: أما في نظام Windows فيجب إضافة السطر التالي: C:\Python34\scripts; إلى مسار النظام System path، وللقيام بذلك اتبع الخطوات التالية: انقر بزر الفأرة الأيمن على أيقونة Computer واختر Properties من القائمة المنسدلة: انقر على أيقونة Advance system settings، وفي مربع الحوار المنبثق اضغط على أيقونة Environment Variables. انقر نقراً مزدوجًا على متغير النظام Path في الجزء السفلي من مربع الحوار المنبثق. أضف السطر السابق إلى نهاية السلسلة النصّية، بعد الفاصلة المنقوطة (;) (إن لم تكن هناك فاصلة منقوطة في نهاية السطر فقم بإضافتها). اضغط Ok ثم أغلق بقية النوافذ بالضغط على Ok. يمكنك الآن استخدام pip من سطر الأوامر مباشرة. البيئة الافتراضية Virtual Environment قبل البدء بتنصيب Django سنعمل على تنصيب أداة مفيدة جدًّا من شأنها المساعدة على ترتيب البيئة البرمجية على حاسوبك. يمكن تجاوز هذه الخطوة، ولكن ينصح بها بشدّة. تعمل البيئة الافتراضية على عزل مشاريع Python أو Django الخاصّة بك عن بعضها البعض، وهذا يعني أن إجراء التعديلات على موقع إلكتروني معيّن لن تؤثّر على المشاريع الأخرى التي تعمل عليها. ستحتوي البيئة الافتراضية على الملفات التنفيذية الخاصة بـ Python بالإضافة إلى نسخة من مكتبة pip يمكنك استخدامها في تنصيب حزم Python المختلفة. سننشئ مجلدًا سيحتوي على البيئة الافتراضية التي سوف ننشئها بعد قليل. mkdir mysite cd mysite يتطلب إنشاء البيئة الافتراضية تنصيب حزمة virtualenv وسنستعين بـ pip للقيام بذلك: pip install virtualenv لاستخدام virtualenv من سطر الأوامر مباشرة في أوبنتو يجب تنصيب الحزمة virtualenv، وللقيام بذلك اكتب الأمر التالي في سطر الأوامر: sudo apt-get install virtualenv بعد اكتمال عملية التنصيب يمكنك إنشاء البيئة الافتراضية بالشكل التالي: virtualenv myvenv ستنشئ هذه الشيفرة بيئة افتراضية وهي عبارة عن مجموعة من المجلدات. لتفعيل البيئة الافتراضية الجديدة في نظام Windows استخدم الشيفرة التالية: myvenv\Scripts\activate أما في نظامي Linux و OS X فاستخدم: source myvenv/bin/activate ملاحظة: قد لا تحصل على النتيجة المرجوّة من الشيفرة السابقة، لذا يمكنك استخدام هذه الشيفرة: . myvenv/bin/activate سيتغيّر سطر الأوامر وذلك بإضافة كلمة (myvenv) إلى بداية السطر، وهذا يعني أن الأمور تسير على ما يرام. ولإغلاق البيئة الافتراضية يمكنك استخدام التعليمة التالية: deactivate تنصيب Django بعد اكتمال الخطوتين السابقتين يمكننا الآن تنصيب Django وذلك بتنفيذ الأمر التالي (انتبه إلى وجود علامتي مساواة لا علامة واحدة): pip install django==1.9 بعد اكتمال عملية التنصيب، وللتأكد من أن الأمور تجري على ما يرام، اكتب الأمر التالي في سطر الأوامر: python3 -c "import django; print(django.get_version())" إن حصلت على رقم النسخة (1.9 في حالتنا هذه) التي قمت بتنصيبها، فقد أصبحت جاهزًا لإنشاء مشروعك الأول على Django. إنشاء المشروع الأول مشروعنا الأول سيكون عبارة عن تطبيق استطلاع بسيط، يتألف من جزئين: موقع عام يتيح مشاهدة الاستطلاعات والتصويت عليها. لوحة تحكم تتيح لنا إضافة وحذف وتعديل الاستطلاعات. هذا المشروع سيكون مبنيًا على الإصدار 1.9 من Django والإصدار 3.4 من Python. في حال كنت تستخدم الإصدار 2.7 من Python فيتوجب عليك حينها إضافة بعض التعديلات على الشيفرة التي تكتبها، وسنشير إلى ذلك في محلّه. انتقل إلى سطر الأوامر وتوجه من خلاله إلى المجلد الذي ترغب استخدامه لإنشاء المشروع، وبإمكانك استخدام أي مجلد تحت أي تسمية وفي أي موقع في القرص الصلب، فلا مشكلة لدى Django في ذلك. لإنشاء المشروع نفّذ الأمر التّالي في سطر الأوامر (انتبه إلى النقطة في نهاية السطر): django-admin startproject mysite . سيعمل هذا الأمر على إنشاء مجلد باسم mysite داخل مجلد المشروع. انتبه كذلك إلى كتابة النقطة في نهاية السطر، فهي توجّه الشيفرة إلى تنصيب Django في المجلد الحالي. البنية الأولية للمشروع يحتوي مجلد mysite الذي أنشأته التعليمة السابقة، على مجموعة الملفات التالية: manage.py /mysite __init__.py settings.py urls.py wsgi.py manage.py، يُوصف هذا الملف بالسكين السويسري، وهو الأداة التي سنستعين بها للقيام بالكثير من الأشياء في إدارة الموقع، وفي تهجير قواعد البيانات وتشغيل الخادوم الخاص بـ Django، وغير ذلك الكثير. المجلد mysite هو حزمة بايثون الخاصة بمشروعنا، وسنستخدم هذا الاسم عندما نرغب في استيراد أي شيء داخله. (مثال mysite.urls). mysite/__init__.py ملف فارغ، ووجوده يعني أن هذا المجلّد هو حزمة من حزم بايثون. mysite/settings.py ملف الإعدادات الخاصة بمشروعنا. mysite/urls.py يحتوي على عناوين URL الخاصة بموقعنا، وهو أشبه ما يكون بجدول المحتويات الخاص بالموقع. mysite/wsgi.py نقطة الولوج إلى الخواديم المتوافقة مع WSGI. تشغيل الخادوم توجه في سطر الأوامر إلى المجلد الذي يحوي الملف manage.py ثم اكتب الأمر التالي: python manage.py runserver وستظهر العبارات التالية في سطر الأوامر: Performing system checks... System check identified no issues (0 silenced). You have unapplied migrations; your app may not work properly until they are applied. Run 'python manage.py migrate' to apply them. February 01, 2016 - 15:50:53 Django version 1.9, using settings 'mysite.settings' Starting development server at http://127.0.0.1:8000/ Quit the server with CONTROL-C. ملاحظة: لا تستخدم هذا الخادوم في المشاريع الإنتاجية على الإطلاق، فالهدف من هذا الخادوم هو استخدامه لأغراض التطوير فقط. أدخل العنوان التالي في متصفح الإنترنت: http://127.0.0.1:8000 ستظهر الصفحة التالية لتشير إلى نجاحنا في إنشاء أول مشروع في Django.
  6. تمهيد تتألف السلاسل النصية عادةً من النص المكتوب، وهنالك عدِّة حالات نحتاج فيها إلى تحكمٍ أكبر بكيفية إظهار النص وجعلها أسهل قراءةً للبشر عبر وضع علامات الترقيم والسطور الجديدة والمحاذاة. سنشرح في هذا الدرس كيفية التعامل مع السلاسل النصية في بايثون لكي يظهر النص الناتج بتنسيقٍ صحيح. القيم الحرفية لنفرِّق أولًا بين القيم الحرفية للسلاسل النصية (string literal) والسلاسل النصية نفسها (string value)، فالقيم الحرفية هي ما نراه في الشيفرة المصدرية للبرنامج، بما في ذلك علامتَي الاقتباس. أما السلسلة النصية نفسها فهي ما نراها عندما نستدعي الدالة print()‎ عند تشغيل البرنامج. ففي برنامج «Hello, World!‎» التقليدي، تكون القيمة الحرفية هي "Hello, World!‎" بينما السلسلة النصية هي Hello, World!‎ دون علامتَي الاقتباس. أي أنَّ السلسلة النصية هي ما نراه في نافذة الطرفية عندما نُشغِّل برنامج بايثون. لكن بعض السلاسل النصية قد تحتوي على علامات اقتباس، مثل اقتباسنا لمقولةٍ ما. ولأنَّ القيم الحرفية والقيم الفعلية للسلاسل النصية غير متساوية، فمن الضروري في أغلب الحالات إضافة تنسيق إلى القيم الحرفية لعرض السلاسل النصية كما ينبغي. علامات الاقتباس بسبب إمكانيتنا استخدام علامات الاقتباس المفردة أو المزدوجة في بايثون، فمن السهل تضمين الاقتباسات بوضعها بين علامتَي اقتباس مزدوجتين في سلسلةٍ نصيةٍ محاطةٍ بعلامتَي اقتباس مفردتين كما في السلسلة الآتية: 'Sammy says, "Hello!"' أو يمكننا استخدام علامة اقتباس فردية (أو كما يسمونها «فاصلة عليا» [apostrophe]) في سلسلةٍ نصيةٍ محاطةٍ بعلامتَي اقتباس مزدوجتين: "Sammy's balloon is red." إذًا، يمكننا التحكم بطريقة عرض علامات الاقتباس والفواصل العليا في سلاسلنا النصية عبر استخدام النوع الصحيح من علامات الاقتباس لإحاطة كامل السلسلة النصية. كتابة النص على أكثر من سطر طباعة السلاسل النصية على أكثر من سطر ستجعل منها واضحةً وسهلة القراءة. إذ يمكن تجميع النصوص المكتوبة بعدِّة أسطر لزيادة وضوحها، أو لتنسيقها كرسالة، أو للحفاظ على تعدد الأسطر في الأشعار. نستخدم ثلاث علامات اقتباس فردية ''' أو ثلاث علامات اقتباس مزدوجة """ للإحاطة بالسلسلة النصية التي تمتد على أكثر من سطر: ''' This string is on multiple lines within three single quotes on either side. ''' """ This string is on multiple lines within three double quotes on either side. """ يمكنك الآن طباعة السلاسل النصية في عدِّة أسطر لجعل النصوص سهلة القراءة –خصوصًا الطويلة منها– وذلك عبر استخدام ثلاث علامات اقتباس متتالية. «تهريب» المحارف طريقة أخرى لتنسيق السلاسل النصية هي استخدام «محرف التهريب» (escape character). فجميع عمليات تهريب المحارف تبدأ بالخط المائل الخلفي (backslash، أي \) متبوعًا بمحرفٍ آخر الذي له معنى خاص يفيد في تنسيق السلسلة النصية. هذه قائمة بأكثر محارف التهريب شيوعًا: \: سطرٌ جديدٌ في سلسلةٍ نصيةٍ متألفةٍ من عدِّة أسطر. \\: طباعة رمز الخط المائل الخلفي. ‎\'‎: طباعة علامة اقتباس فردية. ‎\"‎: طباعة علامة اقتباس مزدوجة. ‎\‎n‎: طباعة محرف الانتقال إلى سطرٍ جديد. ‎\t: طباعة محرف الجدولة (Tab). لنستخدم محرف التهريب لإضافة علامات الاقتباس إلى سلسلتنا النصية السابقة، لكن هذه المرة سنُحيط السلسلة النصية بعلامتَي اقتباس مزدوجتين: print("Sammy says, \"Hello!\"") Sammy says, "Hello!" تمكننا عبر محرف التهريب ‎\"‎ من استخدام علامات الاقتباس المزدوجة للإحاطة بالسلسلة النصية التي تحتوي على نصٍ مقتبسٍ ومحاطٍ بعلامتَي اقتباس مزدوجتين. نستطيع أيضًا استخدام محرف التهريب ‎\'‎ لإضافة علامة اقتباس مفردة ضمن السلسلة النصية المحاطة بعلامتَي اقتباس مفردتين: print('Sammy\'s balloon is red.') Sammy's balloon is red. ولأننا نستخدم الآن محرف التهريب فنستطيع وضع علامات الاقتباس المفردة حتى لو كانت السلسلة النصية كلها موجودة بين علامتَي اقتباس مفردتين. عندما نستخدم علامات الاقتباس الثلاثية –كما فعلنا أعلاه– فسنجد فراغًا في أعلى وأسفل النص عند طباعته. نستطيع حذف تلك الفراغات عبر استخدام محرف التهريب \ في بداية ونهاية السلسلة النصية مع الإبقاء على النص مقروءًا بسهولة في الشيفرة. """\ This multi-line string has no space at the top or the bottom when it prints.\ """ وبشكلٍ شبيهٍ بما سبق، يمكننا استخدام محرف التهريب ‎\n لوضع أسطر جديدة دون الحاجة إلى الضغط على زر Enter أو Return: print("This string\nspans multiple\nlines.") This string spans multiple lines. يمكننا الدمج بين محارف التهريب، إذ سنطبع في المثال الآتي سلسلةً نصيةً على أكثر من سطر، ونستعمل فيها مسافة جدولة (tab) بين الترقيم ومحتوى السطر: print("1.\tShark\n2.\tShrimp\n10.\tSquid") 1. Shark 2. Shrimp 10. Squid علامة الجدولة الأفقية التي وضعناها عبر محرف التهريب ‎\t ستؤدي إلى محاذاة الكتابة في العمود النصي الثاني في المثال أعلاه، مما يجعل قراءتها سهلةً جدًا. وصحيحٌ أنَّ محرف التهريب ‎\n يعمل عملًا جيدًا في النصوص القصير، لكن لا نُغفِل أهمية أن تكون الشيفرة المصدرية مقروءةً بسهولةٍ أيضًا. فلو كان النص طويلًا، فأرى أنَّ من الأفضل استخدام علامات الاقتباس الثلاثية. رأينا أنَّ محارف التهريب تُستعمَل لإضافة تنسيق إلى السلاسل التي كان من الصعب (أو حتى المستحيل) عرضها عرضًا سليمًا دونها. فهل تستطيع مثلًا أن تطبع السلسلة النصية الآتية دون استخدام محارف التهريب Sammy says, "The balloon's color is red.‎"‎؟ السلاسل النصية «الخام» ماذا لو أردنا تجاهل كل محارف التنسيق الخاصة في سلاسلنا النصية؟ فلربما أردنا مقارنة أو التحقق من صحة بعض الشيفرات الحاسوبية التي تستخدم الخط المائل الخلفي، ولا نريد من بايثون تفسيره على أنها محرف تهريب. أتت «السلاسل النصية الخام» (raw strings) في بايثون لتحل هذه المشكلة، وتتجاهل جميع محارف التنسيق داخل سلسلة نصية، بما في ذلك محارف التهريب. يمكننا إنشاء سلسلة نصية خام بوضع الحرف r في بداية السلسلة النصية، قبل علامة الاقتباس الأولى مباشرةً: print(r"Sammy says,\"The balloon\'s color is red.\"") Sammy says,\"The balloon\'s color is red.\" سنستطيع الإبقاء على محارف التهريب كما هي في السلاسل النصية إن أسبقناها بالحرف r لتحويلها إلى سلاسل نصية خام. الخلاصة شرحنا في هذا الدرس عدِّة طرائق لتنسيق النص في بايثون 3؛ وعرفنا كيف نُظهِر السلاسل النصية كما نريد عبر استخدامنا لمحارف التهريب أو السلاسل النصية الخام، لكي يستفيد المستخدم من النص الناتج ويقرأه بسهولة. ترجمة -وبتصرّف- للمقال [How To Format Text in Python 3] لصاحبته Lisa Tagliaferri
  7. تمهيد سنشرح في هذا الدرس كيفية إعداد بيئة برمجية محليّة للغة بايثون 3 في توزيعة أوبنتو 16.04 أو دبيان 8. بايثون هي لغةٌ سهلة القراءة للغاية ومتنوعة ومتعددة الاستخدامات، واسمها مستوحى من مجموعة كوميدية بريطانية باسم «Monty Python»، وكان أحد الأهداف الأساسية لفريق تطوير بايثون هو جعل اللغة مرحةً وسهلة الاستخدام، وإعدادها بسيطٌ، وطريقة كتابتها مباشرة وتعطيك تقريرًا مباشرًا عند حدوث أخطاء، وهي خيارٌ ممتازٌ للمبتدئين والوافدين الجدد على البرمجة. إصدار بايثون 3 هو الإصدار الحالي من اللغة ويُعتَبَر أنَّه مستقبل بايثون. سيُرشِدُك هذا الدرس خطوةً بخطوة إلى كيفية تثبيت بايثون 3 على نظام لينكس المحلي عندك وذلك عبر سطر الأوامر، وصحيحٌ أنَّ هذا الدرس يشرح عملية التثبيت لتوزيعة أوبنتو 16.04 أو دبيان 8، إلا أنَّ المفاهيم الأساسية فيه تنطبق على أيّة توزيعة أخرى. المتطلبات المسبقة يجب أن يكون لديك حاسوبٌ يعمل بتوزيعة أوبنتو 16.04 أو دبيان 8 (أو أيّ إصدار آخر من دبيان)، وأن تكون لديك امتيازات إدارية على النظام، بالإضافة إلى اتصالٍ بالإنترنت. الخطوة الأولى: إعداد بايثون 3 سنُثبِّت ونضبط بايثون عبر سطر الأوامر، والذي هو طريقةٌ غيرُ رسوميةٍ للتعامل مع الحاسوب، فبدلًا من الضغط على الأزرار فستكتب نصًا وتعطيه للحاسوب لينفذه وسيُظهِر لك ناتجًا نصيًا أيضًا. يمكن أن يساعدك سطر الأوامر على تعديل أو أتمتة مختلف المهام التي تنجزها على الحاسوب يوميًا، وهو أداةٌ أساسيةٌ لمطوري البرمجيات، وهنالك الكثير من الأوامر التي عليك تعلمها لكي تتمكن من الاستفادة منه. هنالك مقالات في أكاديمية حسوب (كدرس مدخل إلى طرفيّة لينكس Linux Terminal) ستعلمك أساسيات سطر الأوامر، وهنالك كتاب «سطر أوامر لينكس» الذي يُعتَبر مرجعًا تفصيلًا لطريقة التعامل مع سطر الأوامر. ستجد تطبيق «Terminal» (البرنامج الذي تستعمله للوصول إلى سطر الأوامر) بالضغط على أيقونة Dash في الزاوية العليا اليسرى من الشاشة ثم كتابة «terminal» في شريط البحث، ثم الضغط على أيقونة التطبيق التي ستظهر بعدئذٍ. يمكنك بشكلٍ بديلٍ أن تضغط على Ctrl+Alt+T في لوحة المفاتيح بنفس الوقت لتشغيل تطبيق Terminal. أما على دبيان 8 فيمكنك فتح القائمة الموجودة أيضًا في الزاوية العليا اليسرى من الشاشة ثم البحث عن «terminal» في شريط البحث، ثم النقر على أيقونة التطبيق. يمكنك أيضًا أن تضغط على Ctrl+Alt+T في لوحة المفاتيح بنفس الوقت لتشغيل تطبيق Terminal. تأتي توزيعات أوبنتو 16.04 ودبيان 8 وإصدارات دبيان الأخرى مثبتةً مسبقًا مع بايثون 3 وبايثون 2. للتأكد أنَّك تملك آخر الإصدارات منها فحدِّث نظامك باستخدام apt-get: sudo apt-get update sudo apt-get -y upgrade الخيار ‎-y يعني أنَّك توافق على تثبيت جميع الحزم القابلة للتحديث، لكن قد تحتاج إلى تأكيد ذلك عند تحديث النظام وذلك اعتمادًا على الحزم التي ستُحدَّث ونسخة نظامك. بعد إكمال العملية، يمكننا التحقق من إصدار بايثون 3 المُثبّت في النظام بكتابة: python3 -V ستحصل على مخرجات في نافذة الطرفية والتي ستريك ما هو إصدار بايثون المثبّت. قد يختلف الرقم بناءً على النسخة المثبتة في توزيعتك، لكن يجب أن يكون شبيهًا بما يلي: Python 3.5.2 لإدارة الحزم البرمجية الخاصة ببايثون، فثبّت pip: sudo apt-get install -y python3-pip الأداة pip هي أداةٌ تعمل مع لغة بايثون تُثَبِّت وتدير الحزم البرمجية التي قد نحتاج إلى استخدامها في تطوير مشاريعنا. يمكنك تثبيت حزم بايثون بكتابة الأمر: pip3 install package_name حيث عليك وضع اسم الحزمة أو المكتبة التابعة لبايثون مكان package_name مثل Django لتطوير الويب أو NumPy لإجراء حسابات علمية. لذا إن شئتَ تنزيل NumPy فيمكنك تنفيذ الأمر pip3 install numpy. بعد أن انتهينا من ضبط بايثون وتثبيت pip، فيمكننا الآن إنشاء «بيئة وهمية» (virtual environment) لمشاريعنا. الخطوة الثانية: إعداد بيئة وهمية تُمكِّنك البيئات الوهمية من إنشاء مساحة معزولة في حاسوبك مخصصة لمشاريع بايثون، مما يعني أنَّ كل مشروع تعمل عليه يملك مجموعة من الاعتماديات (dependencies) والتي لن تؤثِّر على غيره من المشاريع. يوفِّر لنا ضبط بيئةٍ برمجيةٍ تحكمًا أكبر بمشاريع بايثون وإمكانية التعامل مع إصداراتٍ مختلفةٍ من حزم بايثون. وهذا مهمٌ كثيرًا عندما تتعامل مع الحزم الخارجية. يمكنك ضبط أيُّ عددٍ تشاء من البيئات الوهمية، وكل بيئة تُمثِّل مجلدًا في حاسوبك الذي فيه عددٌ من السكربتات. علينا أولًا تثبيت وحدة (module) برمجية باسم venv، وهي جزءٌ من مكتبة بايثون3 القياسية، وذلك لكي نتمكن من استخدام الأمر pyvenv الذي سيُنشِئ البيئات الوهمية لنا. لنثبِّت venv على نظامنا بكتابة: sudo apt-get install -y python3-venv سنتمكن الآن من إنشاء بيئات وهمية بعد إتمام التثبيت، لنختار ما هو المجلد الذي سنضع فيه بيئات بايثون، أو لننشِئ مجلدًا جديدًا باستخدام الأمر mkdir كما يلي: mkdir environments cd environments بعد أن انتقلتَ إلى المجلد الذي تريد احتواء البيئات فيه، فتستطيع الآن إنشاء بيئة جديدة بتنفيذ الأمر الآتي: pyvenv my_env سيُنشِئ الأمر pyvenv مجلدًا جديدًا فيه بعض الملفات التي يمكننا عرضها باستخدام الأمر ls: ls my_env bin include lib lib64 pyvenv.cfg share تعمل هذه الملفات مع بعضها لضمان أنَّ مشاريعك معزولةٌ عن بقية النظام، لكي لا تختلط ملفات النظام مع ملفات المشاريع. وهذا أمرٌ حسنٌ لإدارة الإصدارات ولضمان أنَّ كل مشروع يملك وصولًا إلى حزمٍ معيّنة التي يحتاج لها. تتوافر أيضًا Python Wheels والتي هي صيغة بناء حزمٍ لبايثون والتي يمكن أن تُسرِّع من تطوير البرامج بتقليل عدد المرات التي تحتاج فيها إلى بناءٍ (compile) للمشروع، وهي موجودةٌ في مجلد share في توزيعة أوبنتو 16.04 لكنها ستكون في دبيان 8 في أحد مجلدات lib وليس في share. عليك تفعيل البيئة لاستخدامها، وذلك بكتابة الأمر الآتي الذي سيُنفِّذ سكربت التفعيل: source my_env/bin/activate يجب أن تظهر الآن سابقةٌ (prefix) في المِحث (prompt) والتي هي اسم البيئة المستخدمة، وفي حالتنا هذه يكون اسمها my_env، وقد يكون مظهر المِحَث مختلفًا في توزيعة دبيان، وذلك اعتمادًا على الإصدار المستخدم؛ لكن يجب أن تشاهد اسم البيئة بين قوسين في بداية السطر: (my_env) sammy@sammy:~/environments$ السابقة ستسمح لك بمعرفة أنَّ البيئة my_env مفعلة حاليًا، وهذا يعني أننا سنستخدم إعدادات وحزم هذه البيئة عند إنشائنا لمشاريع جديدة. ملاحظة: يمكنك داخل البيئة الوهمية أن تستخدم الأمر python بدلًا من python3 والأمر pip بدلًا من pip3 إن شئتَ. أما إذا كنتَ ستستخدم بايثون 3 خارج البيئة الوهمية، فيجب عليك حينها استخدام python3 و pip3 حصرًا. يجب أن تكون بيئتك الوهمية جاهزةً للاستخدام بعد اتباعك للخطوات السابقة. الخطوة الثالثة: إنشاء برنامج بسيط بعد أن أكملنا ضبط بيئتنا الوهمية، لننشِئ برنامجًا بسيطًا يعرض العبارة «Hello World!‎»، وبهذا سنتحقق من أنَّ البيئة تعمل عملًا صحيحًا، وستصبح طريقة إنشاء برامج بايثون مألوفةً لديك إن كنتَ وافدًا جديدًا على اللغة. علينا أولًا تشغيل محرر ملفات نصية لإنشاء ملف جديد، وليكن المحرر nano الذي يعمل من سطر الأوامر: (my_env) sammy@sammy:~/environments$ nano hello.py بعد فتح الملف في نافذة الطرفية، فاكتب البرنامج الخاص بنا: print("Hello, World!") أغلق محرر nano بالضغط على Ctrl+x ثم اضغط على y عندما يسألك عن حفظ الملف. بعد أن يُغلَق محرر nano وتعود إلى سطر الأوامر، فحاول تشغيل البرنامج: (my_env) sammy@sammy:~/environments$ python hello.py سيؤدي برنامج hello.py الذي أنشأتَه إلى طباعة الناتج الآتي في الطرفية: Hello, World! للخروج من البيئة، فاكتب الأمر deactivate وستعود إلى مجلدك الأصلي. الخلاصة تهانينا! لقد ضبطتَ الآن بيئة تطوير للغة بايثون 3 في جهازك الذي يعمل بتوزيعة أوبنتو أو دبيان، حان الآن الوقت للتعمق بلغة بايثون وإنشاء برامج رائعة! بالتوفيق. ترجمة -وبتصرّف- للمقال How To Install Python 3 and Set Up a Local Programming Environment on Ubuntu 16.04 لصاحبته Lisa Tagliaferri
  8. بعد أن تعرّفنا في الدّرس السّابق على طريقة التّعامل مع البيانات مثل المُتغيّرات وأنواعها كالأرقام وإسناد القيم، سنكمل في هذا الدّرس الثّالث مشوار تعلّم هذه اللغة بتعلّم كيفيّة التّعامل مع كل من القوائم والسّلاسل النّصيّة. تذكير: الشيفرات التّي تكون مسبوقة بعلامة "<<<" يجب أن تُنفّذ على مُفسّر بايثون. القوائم تعتبر القوائم طريقة رائعة للتّعامل مع البيانات في لغة بايثون، وتتعلّق القائمة بمتغيّر معيّن بحيث يحمل أكثر من قيمة، ويمكن الوصول إلى هذه القيم باستعمال رقم كل قيمة. لتفهم أكثر، اعتبر أنّ لك 5 أبناء، بحيث تكون قائمة الأبناء: 0، عمر 1، خالد 2، حسن 3، زيد 4، يوسف في بايثون، ننشئ القائمة بالطّريقة التاليّة: >>> children = ['Omar','Khaled','Hassan','Zaid','Youssef'] لنسمّي القائمة أعلاه باسم children، وتحتوي على خمس عناصر، ولكل عنصر رقم خاص به، بحيث يبدأ العدّ من الصّفر، فمثلا إذا أردنا مناداة الابن "عمر" فسيتوجّب علينا مناداته برقمه (أي الرقم 0)، وطريقة مناداة باقي الأبناء تكون بالشّكل التّالي: >>> print 'Come here ' + children[0] Come here Omar >>> print 'Come here ' + children[1] Come here Khaled >>> print 'Come here ' + children[2] Come here Hassan >>> print 'Come here ' + children[3] Come here Zaid >>> print 'Come here ' + children[4] Come here Youssef الآن، لننتقل إلى تطبيق مبادئ القوائم على بايثون، يُمكننا إسناد قائمة إلى متغيّر كالتّالي: >>> x = [1, 2, 3] ويُمكنك إنشاء قائمة سلاسل نصيّة عوضا عن الأرقام: >>> x = ["hello", "world"] يُمكن أن تجمع بين أنواع القيّم المُختلفة، هذا المثال يجمع بين الأرقام والسّلاسل النّصيّة: >>> x = [1, 2, "hello, "world"] ويُمكن أن تحتوي القائمة على قائمة أخرى: >>> x = [1, 2, "hello, "world", ["another", "list"]] أو بالطّريقة التّاليّة: >>> a = [1, 2] >>> b = [1.5, 2, a] >>> b [1.5, 2, [1, 2]] يُمكن أن نستخدم الدّالة len المعرّفة مُسبقا لنقيس طول قائمة ما (عدد مكونات القائمة): >>> x = [1, 2, 3] >>> len(x) 3 نصل إلى عناصر قائمة ما بكتابة اسم المُتغيّر الذي يحمل القائمة، ثمّ رقم العنصر بين رمزي []: >>> x = [1, 2, 3] >>> x[1] 2 >>> x[1] = 4 >>> x[1] 4 مع ملاحظة أنّ التّرقيم يبدأ بالصّفر، بحيث يكون العنصر الأوّل من القائمة يحمل الرّقم 0 والعنصر الثّاني يحمل رقم 1 وهكذا دواليك. يُمكن إنشاء قائمة تحتوي على أعداد صحيحة من مجال معيّن بالدّالة Range، في المثال التّالي قُمنا بإنشاء قائمة تحتوي على أربعة عناصر من 0 إلى 3، ثمّ قائمة تحتوي على ثلاثة عناصر بين العددين 3 و 6، ثمّ في السّطر الأخير قُمنا بإنشاء قائمة مُتكوّنة من 3 عناصر بين العددين 2 و 10 مع زيادة بقيمة 3 : >>> range(4) [0, 1, 2, 3] >>> range(3, 6) [3, 4, 5] >>> range(2, 10, 3) [2, 5, 8] يُمكن كذلك استخدام الدّالة len لحساب عدد عناصر قائمة ما: >>> a = [1, 2, 3, 4] >>> len(a) 4 كما يُمكنك التّعامل مع القوائم بالرموز الرّياضيّة * و + لتكرار أو الجمع بين عناصر قائمة ما: >>> a = [1, 2, 3] >>> b = [4, 5] >>> a + b [1, 2, 3, 4, 5] >>> b * 3 [4, 5, 4, 5, 4, 5] للوصول إلى عناصر قائمة مُعيّنة نستعين برقم العنصر، مع ملاحظة بأنّ التّرقيم يبدأ من الصّفر إلى ( عدد العناصر-1 ). >>> x = [1, 2] >>> x[0] 1 >>> x[1] 2 إذا استخدمت فهرسا (ترقيما) خاطئا، فسيُرجِع مفسّر بايثون خطأ: >>> x = [1, 2, 3, 4] >>> x[6] Traceback (most recent call last): File "<stdin>", line 1, in ? IndexError: list index out of range يُمكنك كذلك استخدام التّرقيم السّلبي للوصول إلى عناصر القائمة من الآخر إلى الأول ( آخر عنصر يحمل القيمة -1 والعنصر الأول يحمل الرقم السّلبي لعدد العناصر): >>> x = [1, 2, 3, 4] >>> x[-1] 4 >>> x[-2] 3 >>> x[-4] 1 يُمكننا تشريح قائمة (تقسيمها إلى أجزاء)، بالطّريقة التّاليّة: >>> x = [1, 2, 3, 4] >>> x[0:2] [1, 2] >>> x[1:4] [2, 3, 4] ويمكن استخدام الأرقام السلبيّة في التّقسيم كذلك: >>> x[0:-1] [1, 2, 3] إذا تركت مكان الرقم الأول فارغا، فالقيمة الافتراضيّة هي الصّفر، و القيمة الافتراضيّة للشّطر الثاني تكون عدد عناصر القائمة: >>> x = [1, 2, 3, 4] >>> a[:2] [1, 2] >>> a[2:] [3, 4] >>> a[:] [1, 2, 3, 4] يُمكن استخدام رقم ثالث لتحديد الخطوة (يعني المقدار الذي نضيفه في العنصر الحالي مقارنة بالعنصر السّابق)، والذي يكون الرّقم واحد افتراضيّا: >>> x = range(10) >>> x [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] >>> x[0:6:2] [0, 2, 4] يُمكننا عكس عناصر القائمة بتحديد -1 كقيمة للزيّادة بالشّكل التّالي: >>> x = range(10) >>> x [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] >>> x[::-1] [9, 8, 7, 6, 5, 4, 3, 2, 1, 0] يُمكن كذلك تغيير قيم عناصر القائمة بتعيين قيمة أخرى: >>> x = [1, 2, 3, 4] >>> x[1] = 5 >>> x [1, 5, 3, 4] يُمكن استعمال العامل in للتحقق من تواجد عنصر في القائمة، فإن أرجع القيمة True فهذا يعني أن القيمة موجودة، أما إن أرجع False فهذا يعني بأنّ القيمة غير موجودة في القائمة: >>> x = [1, 2, 3, 4] >>> 2 in x True >>> 10 in x False يُمكن إضافة قيم أخرى إلى قائمة بدالّة الإلحاق append، في المثال التّالي نلحق (نضيف) القيمة 3 إلى القائمة a: >>> a = [1, 2] >>> a.append(3) >>> a [1, 2, 3] السلاسل النصية السّلاسل النّصيّة أو Strings هي التّقنيّة المُستخدمة لكتابة النّصوص في بايثون، وهي سلاسل من الحروف (والتّي بدورها تُشكل جملا فنصوصا)، فمثلا الكلمة "مرحبا" عبارة عن سلسلة نصيّة تحتوي على 5 عناصر، ويمكن الوصول إلى كلّ عنصر كالآتي: العنصر رقم 0 => م العنصر رقم 1 => ر العنصر رقم 2 => ح العنصر رقم 3 => ب العنصر رقم 4 => ا مع ملاحظة أنّ المسافات تُحسَبُ كذلك في السّلاسل النّصيّة فمثلا السّلسلة "مرحبا " تحتوي على 6 عناصر (لاحظ المسافة بعد الألف). وتكون السلاسل النّصية ضمن علامتي تنصيص مزدوجتين "" أو علامتي تنصيص مُفردتين ''. >>> x = "hello" >>> y = 'world' >>> print x, y hello world مع ملاحظة أنّ هناك فرقا بين علامات التّنصيص المزدوجة والمنفردة، ويُمكن استعمالهما بشكل تبادلي. أمّا السّلاسل النّصيّة التي تحتوي على أكثر من سطر، فيُمكن تعيينها لمُتغيّر باستعمال ثلاثة رموز إمّا ''' أو """، انظر المثال التّالي (لكي يعمل بشكل جيّد، من المُفضّل وضعه في ملفّ باسم example1.py وتنفيذه بالأمر python example1.py): x = """This is a multi-line string written in three lines.""" print x y = '''multi-line strings can be written using three single quote characters as well. The string can contain 'single quotes' or "double quotes" ''' print y في المثال أعلاه قمنا بتعيين سلسلة من ثلاثة أسطر للمُتغيّر x بحيثُ يكون المُخرج عند طباعة المُتغيّر x: This is a multi-line string written in three lines. يُمكن كذلك إنشاء سلسلة نصيّة متعدّدة الأسطر بإضافة \n إلى نهاية كلّ سطر، انظر المثال: >>> x = 'This is a multi-line string\nwritten in\nthree lines.' >>> print x مُخرجات المثال أعلاه: This is a multi-line string written in three lines. يُمكن الاستعانة بدّالة المُعرّفة مُسبقا في بايثون لقيّاس عدد أحرف سلسلة نصّية، وهذه الدّالة تُدعى len ويُمكن استخدامها على النّحو التّالي: >>> len("Abdelhadi") 9 السّلاسل النّصيّة في بايثون تتصرّف تماما كالقوائم، بحيث تكون السّلسلة بمثابة قائمة تحتوي على عدّة أحرف، ويمكن فهرسة (الوصول إلى عناصر السّلسلة) وتقطيع السّلاسل النّصيّة بتتبع نفس مبدأ القوائم، انظر المثال: >>> a = "helloworld" >>> a[1] 'e' >>> a[-2] 'l' >>> a[1:5] "ello" >>> a[:5] "hello" >>> a[5:] "world" >>> a[-2:] 'ld' >>> a[:-2] 'hellowor' >>> a[::-1] 'dlrowolleh' يُمكن استعمال العامل in للتحقق فيما إذا كانت السّلسلة النّصيّة جزءا من سلسلة أخرى، في المثال التّالي نقوم بالتحقق من أنّ كلّا من hell و full و el ضمن hello: >>> 'hell' in 'hello' True >>> 'full' in 'hello' False >>> 'el' in 'hello' True عندما يكون المخرج True (صحيح) فهذا يعني بأنّ السّلسلة الصغيرة جزء من السّلسلة النّصيّة الكبيرة. هناك العديد من العمليّات التّي يُمكن تطبيقها على السّلاسل النّصيّة، وسنتعرّف على بعض منها فيما يلي من الأسطر: split: فصل سلسلة نصّية إلى أجزاء يفصل بينها أي رمز (شرط أن يكون في السّلسلة) نقوم بتمريره إلى هذه الدّالة، إذا لم تُحدّد أي فاصل فاستعمل split على فصل السّلسلة النّصيّة اعتمادا على مسافة بيضاء (أي تقسيم الجملة إلى كلمات)، لتفهم أكثر ما الذي أقصده تمعّن في المثال التّالي فبه سيتّضح المقال: >>> "hello world".split() ['hello', 'world'] >>> "a,b,c".split(',') ['a', 'b', 'c'] join: هذه الدّالة تعكس مفعول split حيث تجمع بين عناصر القائمة وترجعها سلسلة نصّية: >>> " ".join(['hello', 'world']) 'hello world' >>> ','.join(['a', 'b', 'c']) 'a,b,c' strip: تقوم بإرجاع سلسلة نصية مع حذف المسافات الزائدة. >>> ' hello world\n'.strip() 'hello world' في المثال أعلاه، يدّل الرّمز \n على "سطر جديد" بحيث يطبع السّطر التّالي سطرين الأول hello والثّاني world: >>> print 'hello\nworld' hello world يُمكن كذلك تمرير قيمة نصيّة لـstrip بحيث تُرجع الدّالة سلسلة نصيّة بدون القيمة المُمَرّرَةِ، لاحظ بأنّها تحذف فقط العناصر الموجودة في بداية وآخر السّلسلة، انظر المثال (لاحظ بأنّ d لم تُحذف، وذلك لأنّها وسط السّلسلة): >>> 'abcdefgh'.strip('abdh') 'cdefg' replace: تقوم باستبدال جزء من السّلسلة أو كامل السّلسلة بقيمة أخرى: >>> 'Hsoub Academy'.replace('Academy', 'I/O') 'Hsoub I/O' تمارين تمرين 1 ما مُخرجات البرنامج التّالي (اُكتبه في ملفّ باسم exercise1.py ثمّ قم بتنفيذه بالأمر python exercise1.py): x = [0, 1, [2]] x[2][0] = 3 print x x[2].append(4) print x x[2] = 2 print x تمرين 2 كم عدد عناصر القائمة x في المثال التّالي (لا تقم بالأمر يدويّا، بل استعن بما تعلّمته): x = [1, 2, "hello, "world", ”Hi”, 4, 8, 3, 0, “Abdelhadi”, “Hsoub Academy”] تمرين 3 أزل القيمة "bad" من السّلسلة التاليّة: >>> 'python is awesome bad' ترجمة -وبتصرف- للكتاب Python Practice Book لصاحبه Anand Chitipothu.
  9. بعد أن تعرّفنا في الدّرس السّابق على طريقة تنصيب بايثون وكيفيّة العمل معها، سنكمل في هذا الدّرس مشوار تعلّم هذه اللغة بتعلّم كيفيّة التّعامل مع البيانات مثل المُتغيّرات وأنواعها كالأرقام وإسناد القيم. ولكن قبل ذلك عليك أن تتعرّف على طريقة دعم اللغة العربيّة، ويجب عليك أن تفهم بعض المُصطلحات المتداولة في مجال البرمجة (والتّي اعتَمدتُ عليها في هذا الدّرس). تذكير: نقوم بتنفيذ الأسطر البرمجيّة مُباشرة من مُفسّر بايثون، لمزيد من المعلومات عن المُفسّر راجع الدّرس السّابق. دعم اللغة العربية في بايثون قد تواجه خطأ إذا حاولت تنفيذ أمر طباعة جملة "مرحبا بالعالم" مُستخدما حروفا عربية، لذلك يجب عليك أن تكتب السّطر التّالي، قبل كتابة أي أمر يحتوي على كلمات عربية: # -*- coding: utf-8 -*- المصطلحات مخرج Output: تعني الجواب أو النّتيجة الذي يُقدّمها مُفسّر بايثون، فمثلا إذا طلبت من مُفسّر بايثون طباعة كلمة Hello، فستستخدم السّطر التّالي: >>> print "Hello" Hello هنا نُسمّي Hello المُخرج الذي يُرجعه البرنامج (أي نتيجة الأمر). مُتغيّر: وهو الاسم الذي نُطلقه على حرف أو “كلمة” تحمل قيمة مُعيّنة، مثلا: >>> name = "abdelhadi" هنا قُمنا بإنشاء مُتغيّر name وأسندنا له القيمة abdelhadi. وإذا أردنا إظهار القيمة abdelhadi فيكفي أن نكتب اسم المُتغيّر في مُفسّر بايثون: >>> print name كما يُمكن أن نضيف تحّية على الشّكل التّالي: >>> print "Hello " + name تُفسّر الشيفرة أعلاه وتكون مُخرجاتها: Hello Abdelhadi يُمكن أن يحمل المُتغيّر عدّة أنواع من القيم، كالأرقام والنّصوص والأحرف… تعيين القيم يُعتبر تعيين قيمة لاسم معيّن من أهمّ أساسيّات البرمجة، وهذا الاسم معروف في البرمجة بالمُتغيّر، وإليك مثالا على ذلك: >>> x = 4 >>> x * x 16 قمنا في المثال أعلاه بوضع القيمة 4 للمتغيّر x، بعبارة أخرى المُتغيّر x يحمل القيمة 4. بحيث يُمكننا استعمال x عوضا عن 4 في باقي الأسطر في برنامجنا. وبعدها قمنا بالعمليّة الحسابيّة x * x أي 4 * 4 وحصلنا على 16 كنتيجة. إذا حاولت أن تستخدم مُتغيّرًا لم يُعرّف من قبل في برنامجك، فستحصل على خطأ كالتّالي: >>> foo Traceback (most recent call last): File "<stdin>", line 1, in ? NameError: name 'foo' is not defined >>> foo = 4 >>> foo 4 حاولنا أعلاه أن نقوم باستخدام المُتغيّر foo الذي لم نعرّفه أساساً، فحصلنا على رسالة من مُفسّر بايثون مفادها بأنّ المُتغيّر foo ليس موجودا. وبعد تعريفه وتعيين القيمة "4" له أصبح بإمكاننا استدعاؤه بدون أي مشكلة. إذا وضعت قيمة مُغايرة لمتغيّر يحمل مُسبقاً قيمة ما، فالقيمة القديمة تُستَبدَل بالقيمة الجديدة، بحيث يحمل المتغيّر القيمة الجديدة. >>> x = 4 >>> x 4 >>> x = 'hello' >>> x 'hello' في المثال أعلاه، قمنا بتحديد القيمة "4" للمتغيّر x ثمّ بعد ذلك قمنا بتحديد "hello" لنفس المُتغيّر فأصبح x يحمل القيمة hello في نهاية المطاف. ويُمكنك تعيين أكثر من قيمة لأكثر من مُتغيّر في آن واحد. >>> a, b = 1, 2 >>> a 1 >>> b 2 >>> a + b 3 ومُبادلة قيمتي مُتغيّرين (بحيث يحمل المُتغيّر قيمة الآخر) سهل جدّا في لغة بايثون: >>> a, b = 1, 2 >>> a, b = b, a >>> a 2 >>> b 1 عند تعيينِ قيمة في بايثون، تكون الأهميّة للجانب الأيمن قبل الأيسر، بحيث يقوم بايثون بالتّعرّف على القيّم في الجانب الأيمن ثمّ يقوم بتعيينها للمتغيّرات في الجانب الأيسر لعلامة = . إذ ما يقع على يسار علامة = هو المُتغير وما يقع على يمينها هو القيمة. التعليقات تُستعمل التّعليقات في البرمجة لشرح وظيفة سطر معين أو لإعطاء فكرة عن برنامجك لمن يقرأ شيفرته، وتكون التّعليقات مسبوقة بعلامة # إما في سطر مستقل أو في نفس سطر الشّيفرة، وتتميّز بأنّها لا تؤثّر على عمل البرنامج إذ يتجاهلها المُفسّر ولا تُنفّذ، وهي عموما اختيارية، لذا فأنت لست مُجبرا على كتابتها، وإليك مثالاً على التّعليقات: >>> # السّطر التّالي عبارة عن تعيين قيمة لمتغيّر >>> x = 'hello' # هذا السّطر عبارة عن تعيين قيمة لمتغيّر الأرقام لقد تعرّفنا من قبل حول كيفيّة التّعامل مع الأرقام بشكل بسيط. >>> 42 42 >>> 4 + 2 6 تدعم بايثون الأعداد العشريّة كذلك. >>> 4.2 4.2 >>> 4.2 + 2.3 6.5 وتدعم العمليّات المُختلفة مثل الإضافة والفرق وغيرهما من العمليّات الحسابيّة: + إضافة - الفرق * الضّرب / القسمة ** الأس (القوة) % باقي القسمة لنجرّب هذه العمليّات على الأعداد الصّحيحة: # عمليّة إضافة >>> 7 + 2 9 # عمليّة فرق >>> 7 - 2 5 # عمليّة ضرب >>> 7 * 2 14 # عمليّة قسمة >>> 7 / 2 3 # الأس >>> 7 ** 2 49 # باقي القسمة >>> 7 % 2 1 إذا تمعّنت في النّظر ستجد أنّ ناتج قسمة 7 على 2 يُساوي 3 وليس 3.5 وهذا لأنّ الرّمز / يُرجع الأرقام الصحيحة فقط عندما يعمل معها، لننظر مالذي سيحدث إذا جرّبنا نفس الأمر لكن بأعداد عشريّة هذه المرّة: >>> 7.0 / 2.0 3.5 >>> 7.0 / 2 3.5 >>> 7 / 2.0 3.5 يُمكن القيّام بالعمليّات الحسابيّة بالاعتماد على أكثر من عامل: >>> 7 + 2 + 5 - 3 11 >>> 2 * 3 + 4 10 هذا مهمّ جدّا وذلك لفهم كيفيّة تعامل لغة بايثون مع العمليّات الحسابيّة، حيث هناك أولويّات للعمليّات وذلك كالقائمة التّالية، من الأقل أولويّة إلى الأه: + - * / % ** ولفهم ذلك أكثر، إليك هذا المثال: عند تنفيذ العمليّة 2 + 3 * 4 في بايثون فالعمليّة الأولى التّي تُنفّذ هي 3 * 4 ، لأن العامل * أكثر أولويّة من عامل +، وبعد ذلك تضاف القيمة إلى 2. >>> 2 + 3 * 4 14 يُمكننا أن نعتمد على الأقواس () لتحديد أولويّات العمليّات، انظر المثال التّالي: >>> (2 + 3) * 4 20 في المثال أعلاه، قمنا بوضع العمليّة 2+3 بين قوسين لإخبار مُفسّر بايثون بأنّ لهذه العملية الأولويّة ويجب حسابها أوّلا، فإن لم نقم بوضع القوسين لقام المُفسّر بحساب العمليّة 4*3 ثم إضافة العدد 2. جميع العمليّات باستثناء ** يبدأ تطبيقها من اليسار ثمّ اليمين. 1 + 2 + 3 * 4 + 5 ↓ 3 + 3 * 4 + 5 ↓ 3 + 12 + 5 ↓ 15 + 5 ↓ 20 تمارين تمرين 1 ما هي مُخرجات (القيّم التّي سيطبعها) البرنامج التّالي: x = 4 y = x + 1 x = 2 print x, y تمرين 2 ما هي مُخرجات (نتيجة) البرنامج التّالي: x, y = 2, 6 x, y = y, x + 2 print x, y تمرين 3 ما هي مُخرجات البرنامج التّالي: a, b = 2, 3 c, b = a, c + 1 print a, b, c ترجمة -وبتصرف- للكتاب Python Practice Book لصاحبه Anand Chitipothu.
  10. python 101

    بايثون (Python) لغة برمجة تتميّز بسهولة تعلّمها، وتُعدّ مثالا جيّداً لبدء تعلّم البرمجة بالنّسبة للمبتدئين. وستجد في هذه السّلسلة من الدّروس (الذي يُمثّل هذا المقال الجزء الأوّل منها) ما تحتاج إليه لتعلّم أساسيّات هذه اللّغة. ما هي بايثون؟ لغة برمجة ابتكرها “جايدو ڤان روسم”، وقد خرجت أول نسخة من بايثون في عام 1991. لغة بايثون لغة برمجة تفسيريّة. إذا سبق وأن اطّلعت على البرمجة ولو قليلا فستعرف أنّ لهذه اللغة بنية جميلة. فالمبرمجون دائما ما يبحثون عن أفضل الطّرق لكتابة الأسطر البرمجيّة. ما الغرض من لغة بايثون؟ تتميّز لغة بايثون بالقوّة والبساطة، فتُخوّل لك كتابة برمجيّات بسيطة جدّا، كما تمتلك مكتبات مُتعدّدة تسمح لك بالعمل على مشاريع أكثر تعقيداً. الويب: في أيامنا هذه تعتبر بايثون مع إطار العمل Django من أفضل الأدوات لتطوير مشاريع ضخمة على الويب تتمثّل أساسا في مواقع الأنترنت. الأنظمة: تعتبر بايثون كذلك من أحسن اللغات التي يستعملها مدراء الأنظمة لإنشاء برمجيّات للمُساعدة في إنجاز مهام مُتكرّرة وكذلك لصيّانة النظام، وإذا كنت ترغب في كتابة تطبيقات Java باستعمال بايثون فيُمكنك ذلك بفضل مشروع Jython. لماذا بايثون؟ تعدّ بايثون لغة سهلة الفهم وشيفرتها سهلة القراءة كذلك، وبالتّالي فهي أفضل خيّار للمُبتدئين الذين يريدون تعلّم البرمجة. وهي موجزة جدّا وشيفرتها قصيرة، ما يُساهم في زيادة إنتاجيّة المُبرمج ويُقلّل من نسبة الأخطاء في البرنامج كما يُساعد على إصلاح الأخطاء بسهولة وسرعة. تُستعمل بايثون كذلك في الميادين العلميّة، مثل ميدان المعلوماتيّة-الحيويّة. وهناك مكتبات متوفّرة لمثل هذه الأغراض كمكتبة biopython. كما هناك مكتبات خاصّة لإنشاء ألعاب 2D (وكذلك 3D)، ومكتبة PyGame مثال على ذلك. من يستعمل بايثون؟ شركة جوجل (وقد كان مؤسّس بايثون يعمل لصالح الشّركة منذ 2005 إلى 2012)،كما أنّ ياهوو، مايكروسوفت وناسا كلّها مؤسّسات تعتمد على بايثون وهذه الشركات على سبيل المثال فقط لا الحصر. الفرق بين إصداري بايثون 2 وبايثون 3 كان هناك العديد من التّغييرات عند خروج الإصدار الثّالث من بايثون، وكان أكبر تغيير يتمثّل في تغيير جملة الطباعة print من: print "مرحبا" إلى: print ("مرحبا") هذا التّغيير سيسبب مشاكل كثيرة عند مُحاولة تنفيذ ملفّات بايثون 2 على بايثون 3، وخاصّة مع كثرة استعمال هذه الجملة في التّطبيقات. لكن لا تقلق فبعد تعلّمك لأساسيّات اللغة لن تجد مشاكل كبيرة مع الإصداراين، وسنعتمد في هذه الدّروس على بايثون 2. تنصيب بايثون تنصيب بايثون على نظام Linux أو MacOS إذا كان لينكس أو ماك أو إس هو نظامك تشغيلك، فهذا أمر جيّد لأنّ بايثون مُثبّتة مُسبقا على هاذين النّظامين. تنصيب بايثون على نظام Windows يُمكنك تحميل بايثون من الموقع الرّسمي. أي نسخة أختار؟ حاول اختيّار النّسخة الأكثر حداثة واستقرارا، وسنعمل بنسخة Python 2.7 لأنّها النّسخة الأكثر استخداما. ملاحظة: يوجد بعض المشاكل المتعلّقة بالتّوافق بين النّسختين 2 و 3 وقد سبق وأن سردنا جانبا من الاختلافات بينهما أعلاه. ويُنصح بالاعتماد على النسخة الثّانية أولّا ثمّ التّعرّف على الفروقات بين النّسختين، وبهذا ستكون قادراً على فهم المشاكل التي قد تحدث عند التبديل بينهما وسيسهل عليك حلّها. مفسر بايثون لاستعمال بايثون على Ubuntu مثلا، شغّل الطرفيّة Terminal: ثمّ نفّذ الأمر python: أمّا على نظام ويندوز فيمكنك الوصول إلى المُفسّر من قائمة "ابدأ". يُمكن ملاحظة الرّمز "<<<" الذي يعني بأنّ مُفسّر لغة بايثون جاهز لاستقبال الإرشادات والأوامر. وبشكل عام في دروس بايثون يعني الرّمز السّابق إذا كان ملحقا بأيّ شيفرات، بأنّك يجب أن تُنفذ الشّيفرات على الطّرفيّة. ويُمكن القيّام بذلك عبر كتابته ثمّ الضغط على زر Enter. يُمكننا الآن أن نجرّب كتابة شيفرة بسيطة عبارة عن عمليّة حسابيّة "3+1": بهذا نكون قد فهمنا أساس مُفسّر بايثون وماهيّته. في بعض المُحرّرات (مثل المحرّر Wing IDE) يكون المُفسّر الخاصّ ببايثون مُضمّناً في البرنامج، وسنتحدّث عن الأمر في القسم التّالي من الدّرس. المحرر محرر Wing IDE يعد مُحرّر Wing IDE في نُسخته المجانيّة من أفضل المُحرّرات للمبتدئين لكتابة شيفرات بايثون خاصّة وأنّه يأتي مع مُفسّر بايثون. وهو محرّر مصمّم من مطوّري بايثون لمُطوّري بايثون، ويُعدّ من أفضل المُحرّرات لمن يرغب في تعلّم اللغة، النّسخة المجانيّة منه توفّر خيّارات أقلّ لمستخدميه مقارنة بالنّسخة المدفوعة (وتُباع بحوالي 45$). يُمكنك تحميل النّسخة المجانيّة منه عبر هذا الرّابط. إذا كنت تعمل على نظام Ubuntu فحمّل الملفّ بامتداد deb.، اضغط مرّتين على الملف ثم اضغط على "تنصيب". إذا واجهتك أي مُشكلة فحاول تنفيذ الأمر التّالي من الطّرفيّة: sudo apt-get install -f هذه بعض اللقطات من البرنامج: محرر Sublime Text الآن لننتقل إلى هذا المُحرّر الرّائع الذي يجمع بين الخفّة والقوّة. يمتلك Sublime Text العديد من الإضافات التّي ستعجب بها من النّظرة الأولى والتّي ستجعل عملك سهلا وأسرع. النّسخة الأساسيّة من المحرّر مجانيّة، يُمكن أن تستقبل بعض الرّسائل التّي تطلب منك شراء البرنامج لدعم المشروع، لكنّ ذلك لا يعدّ إجباريّاً. من المُفضل أن تُثبّت أداة packagecontrol، التّي تُمكّنك من تنصيب الإضافات المُتطلّبة لمشروعك. وإليك بعضا من اختصارات المحرّر الأكثر استخداما: Ctrl + X حذف سطر Ctrl + P تصفّح الملفّ Ctrl + R تحريك المؤشّر إلى الدّالة في الملفّ Ctrl + L تظليل السّطر الحالي Ctrl + D تظليل الكلمة الحاليّة Ctrl + Shift + D مُضاعفة السّطر الحالي Ctrl + M تحريك المؤشّر إلى نهاية الدّالة Ctrl + G تحريك المؤشّر إلى السّطر رقم X في الملف Ctrl + Shift + T إعادة فتح آخر ملف أُغلِق مؤخّراً CTRL + SHIFT + F البحث عن ملفّ في مجلّد ما CTRL + ALT + P التبديل بين المشاريع محرر VIM يعتبر محرّر VIM من أخفّ وأقوى المُحرّرات، ويعمل من الطّرفيّة مباشرة ما يتيح لك إمكانيّة التّعديل على الملفّات وتشغيلها بسرعة، كما يتميّز بعدم استهلاكه لموارد الجهاز. ويُمكنك معرفة المزيد عن هذا المُحرّر بالاطّلاع على سلسلة VIM التّي قُمت بكتابتها منذ مُدّة. تنفيذ سكريبتات بايثون بعد أن تعرّفنا على الأساسيّات، حان الوقت لبدأ التعلم، افتح ملفّا جديدا بمحرّر من اختيّارك واكتب السّطر التّالي: print "hello, world!" واحفظ الملف باسم hello.py، لا يهم اسم الملف هنا المهمّ امتداده (py.) الذي يخبر نظام التّشغيل بأنّ الملف مكتوب بلغة بايثون. يُمكنك الآن تنفيذ (أو تشغيل) الملفّ الذي قمت بإنشائه بكتابة السّطر التّالي في الطّرفيّة ثمّ الضّغط على مفتاح ENTER، فقط تأكد من أنّ الطّرفيّة والملفّ يشيران إلى نفس المجلّد: python hello.py سترجع الطّرفيّة قيمة كالتالي: hello, world! النّص الذي يكون مبدوءا برمز # لا يُنفّذ ويسمّى تعليقا (سنتطرّق للأمر لاحقاً): # هذا برنامج بايثون يقوم بطباعة جملة مرحبا بالعالم # شغّل هذا البرنامج بالأمر التّالي: # python hello.py print "hello, world!" والآن حان دورك. لكي تتعلّم البرمجة بشكل جيّد فيجب عليك أن تتمرّن باستمرار. مسألة 1: أنشئ ملفّ بايثون يقوم بطباعة hello, world أربع مرّات. مسألة2: أنشئ ملف بايثون يحتوي على السّطر التّالي: 1 + 2 قم بتنفيذه. ما هي النّتيجة التي حصلت عليها؟ إذا لم يقم البرنامج بطباعة أي شيء، فما التّغييرات التّي يجب عليك القيّام بها لطباعة النتيجة المُتوقّعة؟ ترجمة -وبتصرف- للدرس Apprendre le langage de programmation Python لصاحبه Olivier ENGEL.
  11. تعرّفنا إلى الآن على كيفيّة إنشاء تطبيق بسيط بلغة بايثون وإطار العمل Flask، يُمكن للتّطبيق الاتّصال بقاعدة بيانات، إضافة عناصر، عرضها وحذفها، لكنّ هذا التّطبيق لا يعتبر محميّا، إذ يُمكن لأي كان أن يُضيف مقالات أو يحذفها، لذا من المفضّل أن نقوم بإضافة نظام لتسجيل دخول بحيث تتمكّن وحدك (كمُدير للتّطبيق) من إجراء العمليّات الحسّاسة، بنهاية هذا الدّرس سنمتلك تطبيقا محميا باسم للمُستخدم وكلمة مرور، ولن يتمكّن أحد من حذف المقالات أو إضافتها إلّا إذا حصل على معلومات تسجيل الدّخول. مفهوم الجلسة في إطار العمل Flask الجلسة عبارة عن كائن يتصرّف تماما كقاموس يحتوي على مفاتيح وقيم، الجلسة تكون مرتبطة بنافذة المُتصفّح افتراضيّا، ما يعني بأنّ المفتاح والقيمة ستُسجّلان طيلة مدّة فتح المُتصفّح، وبمجرّد إغلاق نافذة المُتصفّح فإنّ الجلسة تُحذف (أو تدمّر). فكرة تسجيل الدّخول والخروج في درسنا ستكون كالتّالي: سنضع نموذج HTML في أعلى الصّفحة الرّئيسيّة، سيحتوي النّموذج على حقلين، حقل لكتابة اسم المُستخدم، وآخر لكلمة المرور مع زرّ لإرسال طلب الدّخول (أو طلب الاستيثاق Authentication)، عندما يُدخل المُستخدم كلمة "admin" في حقل اسم المُستخدم، وكلمة "password" في حقل كلمة المرور (يُمكن تغيير هذه المعلومات ببساطة)، سيتأكّد التّطبيق من أنّ البيانات صحيحة، وإذا كانت صحيحة فسنستخدم القاموس session المتواجد في حزمة flask لإنشاء مفتاح باسم logged_in وسنضع القيمة المنطقيّة True للمفتاح، بعدها يُمكننا أن نوجّه المُستخدم إلى الصّفحة الرّئيسيّة مع إخفاء نموذج تسجيل الدخول وعرض رابط لتسجيل الخروج عوضا عن النّموذج، أمّا إذا أدخل المُستخدم بيانات استيثاق خاطئة فسنوجّهه إلى الصّفحة الرّئيسيّة مع عرض نموذج تسجيل الدّخول مُجدّدا. تسجيل الدخول سنقوم أولا بإضافة نموذج HTML لتمكين الزّائر من إدخال بيانات الاستيثاق، سنضيف الشيفرة التّالية في ملفّ index.html مُباشرة بعد وسم body: <form action="{{ url_for('login') }}" method='POST'> <input type="text" placeholder="اسم المُستخدم" name="username"> <input type="password" placeholder="كلمة المرور" name="password"> <input type="submit" value="اُدخُل"> </form> الشيفرة أعلاه عبارة عن نموذج لحقلي اسم المُستخدم وكلمة المرور، سنتمكّن من الحصول على القيمتين في ملفّ app.py كالآتي: username = request.form['username'] password = request.form['password'] لاحظ بأنّنا حدّدنا مُوجّها باسم login في النّموذج، لذا فسيتوجّب علينا إنشاؤه في ملفّ app.py والأمر شبيه بما فعلناه في الدّرس السّابق، بحيث يقبل المُوجه طريقة POST لاستقبال البيانات التي يُرسلها المُتصفّح. سيكون موجّه login كالتّالي: # Login Route @app.route("/login", methods=['GET', 'POST']) def login(): if request.method == 'POST': username = request.form['username'] password = request.form['password'] if username == "admin" and password == "password": session['logged_in'] = True else: return redirect(url_for('home')) return redirect(url_for('home')) يستقبل الموجّه اسم المُستخدم وكلمة المرور ويُنفّذ جملة شرطيّة للتحقق من أنّ البيانات صحيحة، لنفرض بأنّ اسم المُستخدم هو admin وكلمة مروره هي password. إذا تحقّق الشّرط وتأكّدنا من أن البيانات التّي أدخلها المُستخدم صحيحة نقوم بإنشاء جلسة باسم logged_in ونعطيها القيمة المنطقيّة True ونقوم بعد ذلك بتوجيه المُستخدم إلى الصّفحة الرّئيسيّة، أمّا إن لم تكن البيانات صحيحة فنقوم بتوجيه المُستخدم إلى الصّفحة الرّئيسيّة دون إنشاء جلسة. لاستخدام الجلسات سيتوجّب علينا استيرادها من Flask في بداية الملفّ، ليُصبح السّطر كالتّالي: from flask import Flask, render_template, redirect, url_for, request, session سيتطلّب استخدام الجلسات تخصيص مفتاح سريّ كذلك، ويُمكن أن نقوم بذلك بإضافة السّطر التّالي مُباشرة بعد تعريف المُتغيّر app. app = Flask(__name__) app.config['SECRET_KEY'] = "Secret" تنبيه: من المهم أن تُغيّر Secret إلى مفتاح لا يُمكن التّنبؤ به ويجب أن يكون سريّا للغاية، يُمكنك استخدام دالة urandom من الوحدة os لتوليد سلسلة عشوائيّا كالتّالي: >>> import os >>> os.urandom(24) '\xee\x9dA\x81\x19\x17\xdd\x04\xae9\xc1\x1a-\xf2\xf8\xda\x9a\x99u\x90\x96]\xbaT' يُمكنك بعد ذلك استعمال السّلسلة المولّدة كقيمة للمفتاح السرّي. وهكذا سنكون قد انتهينا من نظام تسجيل دخول المُدير، الخطوة التّالية هي تسجيل خروجه، وذلك بتدمير الجلسة عند الوصول إلى المُوجّه logout. تسجيل الخروج لتسجيل الخروج يكفي إضافة مُوجّه باسم logout إلى الملفّ app.py، وسيكون دور الموجّه حذف المفتاح logged_in من الجلسة: # Logout Route @app.route("/logout") def logout(): session.pop('logged_in', None) return redirect(url_for('home')) لاحظ بأنّ الموجّه بسيط للغاية، كلّ ما يقوم به هو حذف المفتاح logged_in باستخدام التّابع pop وبعدها يعيد توجيه المُستخدم إلى الصّفحة الرّئيسيّة. الآن إذا قمت بتسجيل دخولك فسيُنشئ التّطبيق جلسة جديدة، أما إذا قمت بزيارة الموجّه logout عبر العنوان http://127.0.0.1:5000/logout فستُدمّر الجلسة. إضافة زر لتسجيل الخروج عوضا عن نموذج HTML رغم أنّنا قُمنا بإضافة نظام لتسجيل الدّخول والخروج إلا أنّ ذلك لا يظهر في الصّفحة، ولا يُمكن لنا أن نعرف تسجيل الدّخول من عدمه. سنقوم في هذا الجزء بتحويل الصّفحة الرّئيسيّة إلى صفحة مُتجاوبة، أي أنّنا سنتأكّد ممّا إذا كان المُستخدم قد سجّل دخوله، فإن كان ذلك صحيحا فسنعرض له زرّا لتسجيل الخروج، أمّا إن لم يكن قد سجّل دخوله فسنعرض نموذج HTML لتسجيل الدّخول. يُمكن القيام بالأمر بإضافة شرط للتأكّد من أنّ المفتاح logged_in موجود في الكائن session، والتّالي تطبيق للأمر في ملفّ index.html: {% if 'logged_in' not in session %} <form action="{{ url_for('login') }}" method='POST'> <input type="text" placeholder="اسم المُستخدم" name="username"> <input type="password" placeholder="كلمة المرور" name="password"> <input type="submit" value="اُدخُل"> </form> {% else %} <a class="logout" href="{{ url_for('logout') }}">خروج</a> {% endif %} يُمكن الآن التمييز بين تسجيل الدخول وتسجيل الخروج؛ الخطوة التّالية هي حماية الموجّهين create و delete لنمنع من لم يسجّل دخوله من حذف وإنشاء المقالات والسّماح بذلك للمُدير فقط. حماية الموجهين create و delete لحماية موجّه ما يجب أن نحمي الدوال التي التّي تقوم بالعمليّة، ما يعني بأنّنا يجب أن نحمي الدّالتين create و delete. وللقيام بالأمر يُمكن الاستعانة بميّزة المُزخرفات في لغة بايثون، يُمكنك الحصول على المزيد من المعلومات بالرّجوع إلى درس المُزخرفات. . سننشئ مُزخرفا باسم login_required، سنحتاج إلى المُزخرف wraps من الوحدة functools وهو مُزخرف مُساعد ويعتبر استعماله من أفضل المُمارسات. سيكون المُزخرف login_required كالتّالي: from functools import wraps def login_required(function): @wraps(function) def wrapper(*args, **kwargs): if 'logged_in' in session: return function(*args, **kwargs) else: return redirect(url_for('home')) return wrapper نقوم أولا باستدعاء wraps من الوحدة functools ونزخرف الدّالة بشرط أن يكون المفتاح logged_in في الجلسة، ما يعني بأنّ الدّالة ستُنفّذ إذا كان المُستخدم قد سجّل دخوله فقط، أمّا إن لم يكن قد سجّل دخوله فسنقوم بتوجيهه إلى الصّفحة الرّئيسيّة دون تنفيذ الدّالة. يُمكن الآن تطبيق المُزخرف على الدّالتين create و delete لمنع الزوار من إنشاء المقالات أو حذفها. لتطبيق المُزخرف يكفي كتابة اسمه مسبوقا بالرّمز @ مُباشرة فوق الدّالة. ما يعني بأنّ الموجّه create سيصبح كالتالي: # Create Post Page @app.route("/create", methods=['GET', 'POST']) @login_required def create(): if request.method == 'POST': title = request.form['title'] content = request.form['content'] manage_db.create(title, content) return redirect(url_for('home')) أما موجّه delete فسيصبح كالتّالي: # Delete Post @app.route("/delete/<post_id>") @login_required def delete(post_id): manage_db.delete(post_id) return redirect(url_for('home')) يمكنك تصفّح ملفّات الأمثلة على Github. ختاما إلى هنا نكون قد تعرّفنا على طرق بسيطة لحماية تطبيقنا ويُمكنك الآن نشر التّطبيق على الأنترنت، لكن تذكر بأنّ هذه الطّرق ليست آمنة بما فيه الكفاية، لذا إن كان تطبيقك حسّاسا فمن المُفضّل استعمال إضافة لإدارة أنظمة الاستيثاق مثل إضافة Flask-login أو Flask-Security.
  12. بعد أن تعرّفنا على طريقة تمرير قيم المُتغيّرات من بايثون إلى ملفّات HTML أصبح بإمكاننا أن نستعمل قاعدة بيانات تحتوي على جدول للمقالات عوضا عن استعمال قائمة أو قاموس. ما هي قاعدة البيانات قاعدة البيانات ببساطة مخزَن للبيانات المُختلفة كأسماء المستخدمين، كلمات المرور، وباقي القيم التي يُمكن أن تحصل عليها ممن يستخدم تطبيقك، ويُمكن كذلك جلب، تعديل وحذف البيانات منها بسهولة. يُمكن أن تكون قاعدة البيانات عبارة عن ملفّ نصي بسيط، بحيث يمثل كل سطر منه قيمة مُستقلّة، ويُمكن أن تكون عبارة عن جدول، بحيث يكون لهذا الجدول أعمدة وخانات، في كلّ عمود نوع محدد من القيم، وفي كلّ خانة القيمة الخاصّة بهذا النوع. سنستخدم في هذا الدّرس نظام SQL لقواعد البيانات، وهو نظام يعتمد على الجداول، وسنستخدم في هذا الدّرس جدولا لتخزين المقالات كالتّالي: رقم المُعرّف عنوان المقال مُحتوى المقال 1 عنوان المقال الأول مُحتوى المقال الأول 2 عنوان المقال الثّاني مُحتوى المقال الثّاني بنية تطبيق "مدونتي" سنعمل في هذا الدّرس على بناء تطبيق مُتكامل يُمكن أن يعمل كنظام إدارة مُحتوى بسيط، ستكون بنية التّطبيق كالآتي: الصّفحة الرّئيسيّة: هنا تُعرض عناوين ومحتويات المقالات المُتواجدة في قاعدة البيانات، بالإضافة إلى زر لحذف كل مقال. صفحة المقال: هنا ستتمكن من قراءة المقال مع رابط تحت المقال لحذفه. إضافة مقال جديد: ستتمكّن من إضافة مقال جديد إلى قاعدة البيانات في الصّفحة الرّئيسيّة مباشرة بعد عرض المقالات الموجودة. وهذه صور للتّطبيق النّهائي: الصفحة الرئيسية صفحة المقال إنشاء قاعدة البيانات وإنشاء جدول المقالات سنستعمل في الدّرس قواعد البيانات Sqlite لإدارة قاعدة البيانات، وذلك لسهولة التّعامل معها وسهولة نقل ملفّات قاعدة البيانات إلى أجهزة أخرى، كما أنّها لا تعمل على خادوم كما هو الحال مع MySQL أو Postgresql. تنويه: من المُفضّل عدم استخدام Sqlite في التّطبيقات التي ستنشرها على الأنترنت أو المشاريع الرّسميّة، ومن المُفضّل استخدام Postgresql أو MySQL في هذه الحالة. سننشئ قاعدة بيانات باسم database. في قاعدة البيانات هذه سنضيف جدولا للمقالات باسم posts. سيتكون جدول المقالات من ثلاثة أعمدة: رقم المقال/المعرّف (ID) عنوان المقال (Title) مُحتوى المقال (Content) لإنشاء قاعدة البيانات وجدول المقالات يُمكنك تنفيذ الشيفرة التّالية، ضعها داخل ملفّ باسم create_db.py وقم بتنفيذه: # -*- coding: utf-8 -*- import sqlite3 # الاتّصال بقاعدة البيانات db = sqlite3.connect('database.db') # إنشاء مُؤشّر في قاعدة البيانات لنتمكّن من تنفيذ استعلامات SQL cursor = db.cursor() # إنشاء الجدول cursor.execute(""" CREATE TABLE posts( id INTEGER PRIMARY KEY, title CHAR(200), content TEXT )""") # إدخال القيم إلى الجدول cursor.execute('''INSERT INTO posts(title, content) VALUES(?,?)''', (u'عنوان المقال الأول', u'محتوى المقال الأول')) cursor.execute('''INSERT INTO posts(title, content) VALUES (?,?)''', (u'عنوان المقال الثّاني', u'مُحتوى المقال الثّاني')) # تطبيق التغييرات db.commit() لاحظ بأنّنا نستدعي الوحدة sqite3 في البداية، وذلك لتنفيذ شيفرة لغة SQL، والشيفرة الممرّرة كمُعاملات للدّالة execute هي شيفرة SQL خاصّة بقاعدة البيانات Sqlite. بعد تنفيذ الشيفرة سنحصل على ملف database.db وهو الذي سيكون قاعدة بيانات التّطبيق، يوجد داخل قاعدة البيانات جدول مقالات باسم posts يحتوي بدوره على 3 أعمدة (رقم مُعرّف المقال، عنوان المقال ومحتواه)، مُعرّف المقال سيزيد بواحد تلقائيّا في كلّ مرّة نُضيف فيها عنوانا ومحتوى جديدين وهذا لأنّه من النّوع PRIMARY KEY، ما يعني بأنّنا نستطيع توفير قيمتين فقط دون الاهتمام بخانة رقم المعرّف. نضيف بعد ذلك مقالين: المقال الأول: عنوانه "عنوان المقال الأول"، مُحتواه "محتوى المقال الأول" المقال الثاني: عنوانه "عنوان المقال الثاني"، مُحتواه "محتوى المقال الثّاني" بعد الانتهاء من إضافة القيم، نقوم باستدعاء الدّالة commit لحفظ التّغييرات إلى قاعدة البيانات. الحصول على المقالات للحصول على رقم مُعرّف وعنوان ومحتوى المقالات يُمكننا تنفيذ الاستعلام التّالي: SELECT * FROM posts; النّجمة عبارة تعني all أو الكل. يُمكننا كذلك الحصول على قيم عمود واحد فقط: SELECT title FROM posts; ويُمكن الحصول على أكثر قيم أكثر من عمود: SELECT title, content FROM posts; لوضع القيم في مُتغيّر وإرجاعه في دالة في بايثون يُمكنك كتابة دالة كالتّالي: import sqlite3 BASE_DIR = path.dirname(path.realpath(__file__)) DB_PATH = path.join(BASE_DIR, 'database.db') def get_posts(): db = sqlite3.connect(DB_PATH) cursor = db.cursor() query = cursor.execute('''SELECT * FROM posts''') posts = query.fetchall() return posts السّطر الأول يستورد مكتبة sqlite3. السّطر الثّاني مسؤول عن الحصول على مسار المُجلّد الحالي، بعدها نقوم بإيصال مسار المُجلّد الحالي مع ملفّ قاعدة البيانات لنحصل على المسار الكامل للملفّ كقيمة للمُتغيّر DB_PATH، وهذا لتفادي بعض الأخطاء التّي قد تحدث عند نقل ملفّات التّطبيق إلى مكان آخر كاستضافة ما أو نظام تشغيل مُختلف. أما الدالة فتقوم أولا بالاتصال بقاعدة البيانات بالدّالة connect ومعامل DB_PATH الذي يُمثّل مسار ملف قاعدة البيانات database.db، بعدها نُنشئ مؤشّرا بالدّالة cursor، ثمّ ننفّذ الاستعلام كمُعامل مُمرّر للدّالة execute، بعدها نُطبّق الدالّة fetchall على نتيجة الاستعلام للحصول على القيم في قائمة من المجموعات، بحيث تحتوي القائمة على مجموعة بثلاثة عناصر العنصر الأول هو رقم المعرّف والعنصر الثّاني يمثّل عنوان المقال والعنصر الثّالث يمثّل محتوى المقال. وبالتّالي فإنّنا سنتمكن من الوصول إلى محتويات المقال كعناصر في مجموعة داخل قائمة، والقائمة تحتوي على العديد من المجموعات. قائمة المقالات ستكون كالتّالي: posts = [(1, u'عنوان المقال الأول', u'محتوى المقال الأول'), (2, u'عنوان المقال الثّاني', u'محتوى المقال الثّاني') ] ما يعني بأنّنا نستطيع الوصول إلى مُعرّف كل مقال، عنوانه ومحتواه بحلقة For بسيطة: posts = get_posts() for post in posts: post[0] # رقم المعرّف post[1] # عنوان المقال post[2] # محتوى المقال احفظ الدّالة get_posts في ملفّ باسم manage_db.py لنستعملها لاحقا كوحدة مع تطبيقنا (انظر درس الوحدات والحزم في لغة بايثون). الحصول على مقال حسب معرفه/رقمه للحصول على مقال حسب رقم مُعرّفه يكفي أن نُضيف جملة WHERE إلى استعلام SQL: SELECT title, content FROM posts WHERE id=1 ستُمكّننا الجملة أعلاه من الحصول على عنوان ومحتوى المقال الذي يمتلك رقم المُعرّف 1. لاستغلال الأمر في لغة بايثون بمُساعدة وحدة sqlite يُمكننا أن نكتب دالة باسم get_post_by_id لنحصل على مقال حسب رقم مُعرّفه، وبالطّبع سيكون للدّالة مُعامل واحد باسم post_id ليحمل قيمة رقم المُعرّف. def get_post_by_id(post_id): db = sqlite3.connect(DB_PATH) cursor = db.cursor() post_id = int(post_id) query = cursor.execute('''SELECT title, content FROM posts WHERE id=?''',(post_id,)) post = query.fetchone() return post بعد الاتّصال بقاعدة البيانات وإنشاء مؤشّر، نقوم أولا بتحويل قيمة رقم المُعرّف إلى عدد صحيح لأن الدّالة رقم المعرّف في قاعدة البيانات عبارة عن عدد صحيح. بعدها نُنفّذ الاستعلام الذي سبق وأن ذكرناه، لكن هذه المرّة قُمنا بتمرير مجموعة من عنصر واحد، وهذا العنصر هو مُعامل الدّالة، بعدها عرّفنا مُتغيّرا باسم post ليحمل بيانات المقال التي حصلنا عليها بتنفيذ الدّالة fetchone على الاستعلام، بعدها نُرجع المُتغيّر post. إذا استدعيت الدّالة مع تمرير قيمة بالعدد 1 فسيكون المُخرج كالتّالي: (u'عنوان المقال الأول', u'محتوى المقال الأول') أضف الدالة get_post_by_id إلى ملفّ manage_db.py واحفظه. حذف مقال حسب رقم المقال طريقة حذف المقال مُشابهة لطريقة الحصول عليه، فقط استبدل SELECT بالأمر DELETE. DELETE FROM posts WHERE id=? ما يعني بأنّنا نستطيع كتابة دالة في لغة بايثون لحذف مقال حسب رقم مُعرّفه: def delete(post_id): db = sqlite3.connect(DB_PATH) cursor = db.cursor() cursor.execute('''DELETE FROM posts WHERE id=?''', (post_id,)) db.commit() الاختلاف هنا هو أنّنا سنحتاج إلى تنفيذ الدّالة commit لتأكيد العمليّة. وكما العادة، أضف دالة الحذف إلى ملفّ manage_db.py. إضافة مقال تعرّفنا في بداية هذا الدّرس على طريقة إضافة مقال إلى قاعدة البيانات. INSERT INTO posts(title, content) VALUES('Title 1','Content 1') يُمكننا في بايثون إدخال قيم المُتغيّرات إلى قاعدة البيانات بالطّريقة التّالية: import sqlite3 db = sqlite3.connect('database.db') cursor = db.cursor() title_variable = 'Title 3' content_variable = 'Content 3' cursor.execute('''INSERT INTO posts(title, content) VALUES(?,?)''', (title_variable, content_variable)) db.commit() لا تنس أن تقوم باستدعاء الدّالة commit لتأكيد العمليّة. إذا قُمت بتنفيذ الشّيفرة أعلاه، وقُمت بعدها بتنفيذ الدّالة get_posts التي أنشأناها سابقا، ستتمكّن من رؤية القيمتين Title 3 و Content 3 كعنصرين من قائمة المقالات. لنضع هذه الشّيفرة في دالة باسم create لإضافتها إلى الوحدة manage_db، ستقبل الدّالة مُعاملين، مُعامل للعنوان، ومُعامل آخر لمُحتوى المقال. def create(title, content): db = sqlite3.connect('DB_PATH') cursor = db.cursor() cursor.execute('''INSERT INTO posts(title, content) VALUES(?,?)''', (title, content)) db.commit() الحصول على القيم وتمريرها إلى القالب بعد أن أنشأنا وحدة تحتوي على أربعة دوال تؤدّي أربعة أوامر أساسيّة: get_posts: الحصول على المقالات على شكل قائمة من المجموعات يُمكن الدّوران حولها get_post_by_id: الحصول على عنوان ومُحتوى مقال حسب رقم مُعرّفه delete: حذف مقال create: إنشاء مقال جديد إذا اطّلعت على الدّرسين السّابقين، ستعرف كيفيّة الحصول على قائمة المقالات وكيفيّة تقديمها في ملفّ HTML دون قراءة الجزء الموالي، لذا فمن الأفضل أن تُحاول ذلك الآن، وعد إلى هنا إذا واجهتك أية مشاكل. مبدأ التطبيق سيحتوي التّطبيق على 4 موجّهات: موجّه الصّفحة الرّئيسية / موجّه إضافة المقال create/ موجّه صفحة المقال الواحد <post/<post_id/ موجّه حذف المقال <delete/<post_id/ موجها إضافة المقال وحذفه لن يقدّما صفحة HTML بل سيُنفّذان دالّة وبعدها سيعيدان التّوجيه إلى الصّفحة الرّئيسيّة مباشرة. الصفحة الرئيسية ستحتوي الصّفحة الرّئيسية على عناوين ومحتويات المقالات لذا سنستخدم الدّالة get_posts من الوحدة manage_db في المُوجّه الرّئيسي ما يعني بأنّنا يجب علينا استدعاء الوحدة، كما سنُقدّم المقالات في ملفّ HTML باسم index.html. في ملّف app.py ضع ما يلي: # -*- coding:utf8 -*- from flask import Flask, render_template import manage_db app = Flask(__name__) # Home Page @app.route("/") def home(): posts = manage_db.get_posts() return render_template('index.html', posts = posts) if __name__ == "__main__": app.run(debug=True) لاحظ بأنّنا استدعينا الدّالة get_posts وأسندنا قيمتها إلى المُتغيّر posts وبعدها نُقدّم الملفّ index.html مع تمرير المُتغيّر posts. بما أنّ المُتغيّر الذي مرّرناه عبارة عن قائمة سنقوم بالدوران حول هذه القائمة والوصول إلى كل عنصر في المجموعة على حدة. الجزء المسؤول عن عرض المقالات في ملفّ index.html: {% for post in posts %} <a href="post/{{ post[0] }}"> <h2> {{ post[1] }} </h2> </a> <a href="delete/{{ post[0] }}"><span class="delete">حذف</span></a> <p> {{ post[2] }} </p> {% endfor %} الشّيفرة أعلاه هي الجزء المسؤول عن عرض المقالات فقط، وقد تجاهلت العناصر الأخرى التي لا تهمّنا مثل الشّعار والتّنسيق وغير ذلك. يُمكنك الحصول على ملفّ index.html كاملا من على Github بعد حلقة For سنحصل على مجموعة بثلاثة عناصر، العنصر الأول عبارة عن رقم مُعرّف المقال، وسنستخدمه لوضع رابطين للمقال، رابط عرض المقال ورابط حذفه، ما يعني بأنّنا نستطيع الوصول مثلا إلى المقال الأول كالتّالي: post/{{ post[0] }} => http://127.0.0.1:5000/post/1 ويُمكن حذفه بالرّابط التّالي: delete/{{ post[0] }} => http://127.0.0.1:5000/delete/1 الرّوابط لن تعمل حاليّا لأنّنا لم ننشئ المُوجّهات بعد. سيُعرض عنوان المقال داخل وسم h2 بالسّطر التّالي: <h2> {{ post[1] }} </h2> سيُعرض مُحتوى المقال داخل وسم p بالسّطر التّالي: <p> {{ post[2] }} </p> صفحة عرض المقال لعرض المقال الواحد، سنستخدم ملفّ HTML آخر وسنسمّيه post.html، أمّا الموجّه المسؤول عن تقديم هذا المقال فسيكون كالتّالي: موجّه post في ملفّ app.py: # Single Post Page @app.route("/post/<post_id>") def post(post_id): post = manage_db.get_post_by_id(post_id) return render_template('post.html', post = post) الشّيفرة أعلاه عبارة عن مُوجّه باسم post يقبل مُعاملا post_id لنتمكّن من تمريره كمُعرّف للمقال للدّالة get_post_by_id من الوحدة manage_db. بعدها نقوم باستدعاء الدّالة للحصول على بيانات المقال على شكل مجموعة يُمكننا أن نصل إلى عناصرها كالتّالي: post[0] # عنوان المقال post[1] # المحتوى صفحة post.html: <div class="main"> <h2> {{ post[0] }} </h2> <p> {{ post[1] }} </p> </div> <a href="{{ url_for('home') }}" class="back_to_home">عُد إلى الصّفحة الرّئيسيّة</a> في الشّيفرة أعلاه، نقوم بعرض عنوان المقال داخل وسم h2 ونقوم بعرض المُحتوى داخل وسم p. السّطر الأخير عبارة عن رابط لتمكين الزّائر من العودة إلى الصّفحة الرّئيسيّة و home اسم الدّالة المسؤولة عن تقديم الصّفحة الرّئيسية (الموجودة مُباشرة بعد الموجّه /). # Home Page @app.route("/") def home(): ... ملحوظة: نستطيع استخدام الدّالة url_for لتوليد روابط الموجّهات، وذلك بوضع اسم الدّالة كمعامل. مثال: لنفرض بأنّ لدينا مُوجّها باسم hello ودالة باسم hello_page، سنتمكّن من إنشاء رابط إلى الموجّه hello كالتّالي: <a href="{{ url_for('hello_page') }}">Link to Hello Page</a> يُمكن كذلك وضع عنوان المقال كعنوان للصّفحة داخل وسم title: <title>{{ post[0] }}</title> حذف مقال طريقة حذف المقال شبيهة بطريقة عرضه، الاختلاف هنا هو أنّنا سنستخدم الدّالة redirect لإعادة توجيه المُستخدم إلى الصّفحة الرّئيسية مُباشرة بعد حذف المقال. لاستخدام الدّالة redirect سيتوجّب علينا استيرادها من وحدة Flask في بداية الملفّ app.py. سنحتاج كذلك إلى الدّالة url_for للتوجيه إلى الرّابط الصّحيح. from flask import Flask, render_template, redirect, url_for موجّه delete سيقبل معاملا باسم post_id لتمريره إلى الدّالة delete من الوحدة manage_db لحذف المقال الذي يحمل رقم المعرّف المُمرّر. # Delete Post @app.route("/delete/<post_id>") def delete(post_id): manage_db.delete(post_id) return redirect(url_for('home')) لاحظ استخدام الدّالة redirect مُباشرة بعد حذف المقال، تقبل الدّالة مُعاملا بقيمة رّابط الصّفحة الرّئيسية والذي حصلنا عليه بالدّالة url_for، ما يعني بأنّنا نقوم بحذف المقال ثمّ توجيه المُستخدم مُباشرة إلى الصّفحة الرّئيسية. إنشاء مقال جديد تعرّفنا مُسبقا على طريقة الحصول على القيم من المستخدم بطريقة طلبات GET من عنوان URL كالآتي: /create?title=post1&content=content1 يُمكننا استخدام request للحصول على القيم كالتّالي: title = request.args.get('title') content = request.args.get('content') يُمكن استخدام هذه الطّريقة لإضافة مقال إلى قاعدة البيانات لكنّها ليست مُجديّة في هذه الحالة، لأنّنا نرغب بأن نُتيح للمُستخدم إرسال بيانات دون تعديل عنوان URL كما يجب علينا أن نُسهّل المأموريّة على المُستخدم العادي. لكي نحصل على العنوان والمُحتوى بطريقة أفضل، سنستخدم نماذج HTML أو HTML Forms، وسنستخدم طريقة POST عوضا عن GET. سنضع النّماذج في ملفّ index.html مُباشرة تحت الجزء المسؤول عن عرض المقالات. <h4>أضف مقالا</h4> <form action="{{ url_for('create') }}" method="POST"> <input class="input" type="text" name="title" placeholder="عنوان المقال"/> <br> <textarea name="content" class="input" rows="10" placeholder="مُحتوى المقال"></textarea> <br> <input type="submit" value="أضف" /> </form> في الوسم form نضع رابط الموجّه create داخل الصّفة action لنُخبر المُتصفّح بأنّ البيانات التّي سيُرسلها المُستخدم يجب أن تذهب إلى موجّه إضافة مقال جديد create. بعدها نُخصّص طريقة إرسال البيانات بوضع كلمة POST داخل الصّفة method. بعد ذلك ننشئ حقلا لعنوان المقال باسم title وحقل نصّ باسم content وبعدها نضيف زرّا لتأكيد الإرسال. بعد أن تملأ النموذج وتضغط على زر "أضف" سيُرسل المُتصفّح البيانات إلى الخادوم وسنتمكّن من الحصول عليها في المُوجّه create عبر الوحدة request، ما يعني بأنّنا سنحتاج إلى استدعاءها في بداية الملف. from flask import Flask, render_template, redirect, url_for, request سننشئ المُوجّه create مع تمرير مُعامل آخر باسم methods يحتوي على قائمة بعنصرين يُمثّلان الطريقتين GET وPOST لأنّ الإعداد الافتراضي هو GET فقط، نضع هذا العامل لكي نتمكّن من استقبال البيانات. @app.route("/create", methods=['GET', 'POST']) بعدها سنتمكّن من الحصول على البيانات وإدخالها إلى قاعدة البيانات كالتّالي: if request.method == 'POST': title = request.form['title'] # الحصول على عنوان المقال content = request.form['content'] # الحصول على مُحتوى المقال manage_db.create(title, content) # إدخال القيم إلى قاعدة البيانات لاحظ بأنّنا نضع شرطا للتأكّد من أن الطلب الذي يرسله المُتصفح من نوع POST. بعدها نحصل على القيم التي أدخلها المُستخدم في النّموذج الموجود بملفّ index.html عبر القاموس form المُتواجد داخل الوحدة request. وكما فعلنا مع الموجّه delete سنقوم بإعادة توجيه المُستخدم إلى الصّفحة الرّئيسية. return redirect(url_for('home')) الموجّه create كاملا: # Create Post Page @app.route("/create", methods=['GET', 'POST']) def create(): if request.method == 'POST': title = request.form['title'] content = request.form['content'] manage_db.create(title, content) return redirect(url_for('home')) أصبح التّطبيق كاملا الآن ويُمكنك مُشاركته مع العالم. يُمكنك إضافة تنسيق css خاصّ بك أو تحميل الملفّات الكاملة للتّطبيق من Github وإضافة ملفّ style.css إلى التّطبيق الذي أنشأته (يُمكنك كذلك تعديله). إذا كان لديك سؤال حول هذا الدّرس، يُمكنك وضعه في قسم الأسئلة والأجوبة. ختاما تعرّفنا على طريقة بناء تطبيق يتفاعل مع المُستخدم ويترك له حريّة الوصول إلى قاعدة البيانات، لكنك تُلاحظ بأنّ الحماية معدومة في التّطبيق، إذ يُمكن لأي شخص أن يحذف جميع المقالات دون أي حاجز (ككلمة مرور مثلا). سنتعلّم في الدّرس القادم على كيفيّة حماية التّطبيق وإتاحة الوصول إلى قاعدة البيانات لمُستخدم واحد فقط، بحيث يُسجّل دخوله إذا أراد حذف أو إضافة مقال، أمّا بقيّة المُستخدمين فلهم إمكانيّة القراءة فقط.
  13. flask 101

    تعرّفنا في الدّرس السّابق على كيفيّة تهيئة بيئة التّطوير وكيفيّة إنشاء تطبيق يقبل قيما من المُستخدم ويُعالجها ثمّ يُرجع النّتيجة على شكل صفحة HTML ليقرأها المُتصفّح، لكنّنا لم نستخدم لغة HTML كما يجب لأنّنا وضعنا شيفراتها داخل ملفّ app.py المكتوب بلغة بايثون. ما يعني بأنّنا جمعنا لغتين في ملفّ واحد، وهذا أمر غير مُناسب ولا يُمثّل مُمارسة جيّدة، الطريقة الأنظف هي بجعل شيفرات بايثون مُستقلّة عن شيفرات لغة HTML. وهذا بالضّبط ما سنتعلّمه في هذا الدّرس. استعمال قوالب HTML يُمكن فصل ملفّات HTML عن ملفّ لغة بايثون بوضعها داخل مُجلّد باسم templates (اسم المُجلّد مهم)، ويكون هذا المُجلّد في نفس مسار الملف app.py. بعد ذلك يُمكن تقديم الملفّ من قبل التّطبيق المكتوب بلغة بايثون عبر الدّالة render_template (يجب استيرادها في البداية) مع تمرير اسم الملفّ. أولا ادخل إلى مُجلّد flask_app ثمّ أنشئ مجلّدا جديدا باسم templates بعدها أنشئ ملفّا باسم index.html داخل هذا المُجلّد، وضع به شيفرة HTML التّاليّة: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>الصّفحة الرّئيسيّة</title> </head> <body style="direction: rtl;"> <h1>السّلام عليكم ورحمة الله</h1> </body> </html> يُمكننا الآن أن نجعل التّطبيق app.py يُقدم هذه الشّيفرة، وذلك أولا باستيراد الدالة render_template واستدعائها مُباشرة بعد جُملة return. # -*- coding:utf8 -*- from flask import Flask, render_template app = Flask(__name__) # Home Page @app.route("/") def home(): return render_template('index.html') if __name__ == "__main__": app.run(debug=True) بعد تشغيل التّطبيق زر العنوان http://127.0.0.1:5000. ستُلاحظ بأنّ مُحتوى الصّفحة هو نفسه مُحتوى الملفّ index.html، ويُمكنك مُشاهدة مصدر الصّفحة بالضّغط على زر الفأرة الأيمن واختيار الخيار View Page Source. تمرير متغير وعرض قيمته يُمكن تمرير المُتغيّرات إلى ملفّ HTML لعرض قيمها بإضافتها كمُعاملات للدّالة render_template. # Home Page @app.route("/") def home(): return render_template('index.html', page = u"الصّفحة الرّئيسيّة") لاحظ بأنّنا قُمنا بإضافة المُتغيّر page وأسندنا له القيمة "الصّفحة الرّئيسيّة"، يُمكننا الآن عرضه في ملفّ HTML بإحاطته بعلامات {{ }}، في المثال التّالي، نعرض قيمة المُتغيّر page داخل وسم h3 مُباشرة بعد الجملة الرّئيسيّة. <body style="direction: rtl;"> <h1>السّلام عليكم ورحمة الله</h1> <h3>{{ page }}</h3> </body> بعد تعديل الملفّ وحفظه ستُلاحظ بأنّ السّطر {{ page }} قد تغيّر إلى عبارة "الصّفحة الرّئيسيّة". عند مُشاهدة مصدر الصّفحة ستُلاحظ بأنّ السّطر: <h3>{{ page }}</h3> قد تحوّل إلى السّطر: <h3>الصّفحة الرّئيسيّة</h3> وهذا هو العمل الرّئيسي لمُحرّك القوالب Jinja2. يُمكن كذلك تقديم نفس ملفّ HTML عبر أكثر من توجيه، كما يُمكن أن تكون قيم المُتغيّرات المُمرّرة مُختلفة، فمثلا المُوّجه الرّئيسي / سيؤدي إلى تقديم الصّفحة index.html مع مُتغيّر يحمل القيمة "الصّفحة الرّئيسيّة". ويُمكن إضافة توجيه آخر /hello، مع تقديم نفس الملفّ ومُتغيّر page بالقيمة "صفحة التّرحيب". وبالتالي سيُصبح التطبيق الكامل كالآتي: # -*- coding:utf8 -*- from flask import Flask, render_template app = Flask(__name__) # Home Page @app.route("/") def home(): return render_template('index.html', page = u"الصّفحة الرّئيسيّة") # Hello Page @app.route("/hello") def hello(): return render_template('index.html', page = u"صفحة التّرحيب") if __name__ == "__main__": app.run(debug=True) يُمكنك كذلك عرض قيمة المُتغيّر في أكثر من موضع، مثلا يُمكنك وضعه كعنوان للصّفحة داخل الوسم title. <head> <meta charset="UTF-8"> <title>{{ page }}</title> </head> بعد تشغيل التّطبيق، سنتمكّن من الوصول إلى صفحتين تُقدّمان نفس ملفّ HTML مع اختلاف في قيمة المُتغيّر page (أي اختلاف في مُحتوى الوسم h3 وعنوان مُناسب لكلّ صفحة). الصّفحة الرّئيسيّة: http://127.0.0.1:5000 صفحة التّرحيب: http://127.0.0.1:5000/hello التعليقات يُمكن وضع تعليقات في مُحرّك القوالب Jinja2 بإحاطتها بعلامات {# تعليق #}، والتّعليق لن يظهر حتى بعد النّظر إلى مصدر الصّفحة، ويُمكن استعماله كالتّالي: <body style="direction: rtl;"> <h1>السّلام عليكم ورحمة الله</h1> {# هذا تعليق لن يظهر للزائر #} <h3>{{ page }}</h3> </body> الجمل الشرطية في محرك القوالب Jinja2 تعرّفنا إلى الآن على طريقة تقديم ملفّات HTML وكيفيّة تمرير المُتغيّرات من ملفّ بايثون إلى ملفّ HTML وكيفيّة عرض قيّمها. لكن مُحرّك القوالب Jinja2 ليس لهذا الغرض فقط، بل يُمكّننا كذلك من استعمال خصائص لغة بايثون، مثل الجمل الشّرطية وحلقة التّكرار for وغير ذلك. انتبه فقط إلى حقيقة أنّ بنية الجمل Syntax الخاصة بلغة بايثون مُختلفة عن بنية الجملة في مُحرّك القوالب Jinja2. فمثلا جملة شرطيّة في لغة بايثون ستكون كالتّالي: x = 10 if x == 10: print x أمّا في Jinja2 فستكون كالتّالي: {% set x = 10 %} {% if x == 10 %} {{ x }} {% endif %} أول فرق قد تُلاحظه هو أنّ جميع الشيفرات مُحاطة بالعلامات {% %} وعرض المُغيّر يكون داخل علامات {{}}. وبالنّسبة لتعريف مُتغيّر وإسناد قيمة له فيلزمه كلمة set. كما يجب إنهاء الجملة الشّرطية بجملة endif، كما أنّ الإزاحة ليست ضروريّة في مُحرّك Jinja2. مُلاحظة: يُفضّل عدم تعريف المُتغيّرات مُباشرة في ملفّات HTML إلا لحاجة، ومن الأفضل تعريفها داخل ملفّات بايثون. لإضافة جملتي elif و else يُمكن القيام بالتّالي: {% set x = 6 %} {% if x == 10 %} x يُساوي 10 {% elif x == 5 %} x يُساوي 5 {% else %} x يُساوي شيئا آخر {% endif %} جرّب تغيير قيمة المُتغيّر x وانظر إلى النّتيجة. حلقة for تعرّفنا على كيفيّة عرض مُتغيّر يحمل قيمة واحدة فقط، لكن ماذا لو أردنا أن نعرض عناصر قائمة ما، بحيث يعرض كلّ عنصر داخل وسم مُعيّن، يُمكن ذلك عبر حلقة for ويُمكن كتابتها كالآتي: {% for item in list %} <h1> {{ item }} </h1> {% endfor %} بحيث list هي القائمة مُتعدّدة العناصر. مثال لنفترض بأنّه لدينا قائمة مقالات لعرضها للزائر، بحيث تكون القائمة كالتّالي: posts = [ u"مُحتوى المقال الأول", u"مُحتوى المقال الثاني", u"مُحتوى المقال الثالث", u"مُحتوى المقال الرابع" ] سنقوم أولا بإنشاء توجيه جديد باسم posts إلى ملفّ app.py وسنُمرّر ملفّ index.html مع تمرير القائمة إلى الملف. # Posts Page @app.route("/posts") def posts(): posts = [ u"مُحتوى المقال الأول", u"مُحتوى المقال الثاني", u"مُحتوى المقال الثالث", u"مُحتوى المقال الرابع" ] return render_template('index.html', posts = posts, page = u"صفحة عرض المقالات") لاحظ بأنّ المُعامل الثاني للدّالة render_template هو posts = posts، الأمر يعني بأنّ القائمة المُمرّرة للقالب اسمها posts وستحمل قيّم القائمة posts المتواجدة في الأعلى. يُمكن عرض كل مقال داخل وسم p بالطّريقة التّاليّة: {% for post in posts %} <p> {{ post }} </p> {% endfor %} يُمكنك الآن زيارة مُدوّنتك المُتواضعة عبر الرّابط http://127.0.0.1:5000/posts. إذا قُمت بعرض مصدر الصّفحة فستُلاحظ ما يلي: <h3>صفحة عرض المقالات</h3> <p> مُحتوى المقال الأول </p> <p> مُحتوى المقال الثاني </p> <p> مُحتوى المقال الثالث </p> <p> مُحتوى المقال الرابع </p> لاحظ بأنّ الوسم p قد تكرّر مع عرض كلّ عنصر. تنسيق الصفحات، إضافة الملفات الساكنة الملفّات السّاكنة هي الصّور وملفّات CSS أو Javascript وتوضع في مُجلّد باسم static بجانب المُجلّد templates. في هذا القسم سنُضيف ملفّ CSS لتنسيق عرض المقالات أعلاه. أنشئ مُجلّدا باسم static داخل مُجلّد المشروع (بجانب المُجلّد templates). بعدها أنشئ 3 مُجلّدات داخل هذا المُجلّد أسماؤها كالتّالي: static ---| css # هنا توضع ملفّات التّنسيق ---| js # في هذا المُجلّد يُمكنك وضع ملفّات جافاسكريبت ---| img # ضع الصّور في هذا المُجلّد بعد إنشاء المُجلّدات أنشئ ملفّ تنسيق باسم style.css داخل مُجلّد css، وضع به ما يلي: body { text-align: center; } h3 { color:#1383EA; } p { font-size: 14px; } للرّبط بين ملفّ css وملفّ HTML، يُمكننا الاعتماد على دالة url_for التّي يُقدّمها مُحرّك القوالب Jinja2 لإعطاء مرونة أكثر في التّعامل مع ملفّات مُتعدّدة، واستخدامها يكون كالتّالي: {{ url_for('static', filename='path/to/file') }} مع تغيير path/to/file إلى مسار الملفّ. وبالتّالي لتضمين ملفّ style.css داخل ملفّ index.html فسيتوجّب علينا إضافة السّطر التّالي إلى وسم head. <link rel="stylesheet" href="{{ url_for('static', filename='css/style.css')}}"> بعد حفظ الملفّ ستُلاحظ بأنّ المُحتوى أصبح يتوسّط الصّفحة، وستُلاحظ كذلك بأنّ لون عنوان الصّفحة قد تغيّر إلى الأزرق. مُلاحظة: عند التّعديل على ملفّ التنسيق وحفظه قد تحتاج إلى إعادة تحميل الصّفحة كاملة بتركيبة المفاتيح CTRL+SHIFT+R وذلك لأنّ المُتصفّح يخبّئ الملف عند أول مرّة تزور فيها الصّفحة وبالتالي فسيعطيك نفس الملف غير المُعدّل في كلّ مرّة تعيد فيها تحميل الصّفحة، والحلّ هو بإعادة تحميل كاملة لجميع الملفّات. ربط ملفات Javascript مثلما هو عليه الحال مع ملفّات css يُمكنك ربط ملفّات جافاسكريبت بوضعها داخل وسم script واستخدام الدّالة url_for. إليك مثالا: <script src="{{ url_for('static', filename='js/main.js')}}"></script> مع مُلاحظة بأنّ ملفّ main.js يجب أن يكون داخل المُجلّد js وليس في مكان آخر. عرض الصور يُمكن كذلك استعمال الدّالة لعرض الصّور، كلّ ما عليك فعله هو وضع الصّورة داخل المُجلّد img وعرضها بالدّالة url_for داخل وسم img، مثلا ضع صورة حسب رغبتك داخل المجلّد img وسمّها logo.png. لعرضها أعلى الصّفحة يُمكن إضافة السّطر التّالي مُباشرة بعد وسم body. <img src="{{ url_for('static', filename='img/logo.png')}}" /> بهذا سيُصبح التّطبيق كالتّالي: يُمكنك تصفّح ملفّات التّطبيق من هذا الرّابط. خاتمة بعد أن تعرّفنا على طريقة تمرير قيم المُتغيّرات من بايثون إلى ملفّات HTML أصبح بإمكاننا أن نستعمل قاعدة بيانات تحتوي على جدول للمقالات عوضا عن استعمال قائمة أو قاموس، في الدّرس القادم سنتعرّف على قاعدة البيانات SQLite يُمكن استخدامها لحفظ المقالات.
  14. flask 101

    بعد أن تعرّفنا على المفاهيم الأساسيّة لتطوير الويب كماهية تطبيق الويب، وإطار العمل، سنُكمل هذه السّلسلة من الدروس وسنتعرّف في هذا الدّرس على كيفيّة تهيئة بيئة التّطوير وتنصيب الأدوات اللازمة، وكذا بعض أساسيّات التّعامل مع إطار العمل Flask. تنصيب لغة بايثون لغة بايثون مُتواجدة بشكل افتراضي على على أنظمة لينكس و OS X، أما بالنّسبة لمستخدمي نظام Windows فيُمكنك تنزيل Python 2 من الموقع الرّسمي، فقط تأكّد من تنزيل آخر نسخة ذات الرّقم x.2.7. تنصيب إطار العمل Flask إنشاء بيئة وهميّة بأداة virtualenv البيئة الوهمية تُوفّر جميع المكتبات والاعتماديات والأدوات التي نقوم بتنصيبها والتي سنحتاج إليها في المشروع في مُجلّد واحد بمعزل عن اعتماديات نظام التّشغيل العامّة، وذلك لتجنّب تصادم بين الاعتماديات، يُمكنك القيام بالتّطوير بعد تشغيل البيئة الوهميّة ولن يكون لذلك تأثير على نظام التّشغيل، وسيبقى كل شيء بداخل مُجلّد واحد، ويُمكنك كذلك إيقاف تشغيل البيئة الوهميّة متى ما تشاء. يُمكن أن تكون أداة Virtualenv مُنصّبة مُسبقا في نظام التّشغيل لديك، يُمكنك التأكد بالأمر التّالي: $ virtualenv --version إذا حصلت على رقم نُسخة فهذا يعني بأنّ الأداة مُنصّبة من قبل. أما إذا لم يكن الأمر كذلك، فيُمكنك تنصيبها بالأمر التّالي في حالة كنت تستعمل توزيعة Ubuntu. $ sudo apt-get install python-virtualenv إذا لم تكن تستعمل نظام Ubuntu فيُمكنك أن تقوم بتنصيبها عبر أداة pip، فقط نفّذ الأمرين التاليين واحدا تلو الآخر: $ pip install -U pip $ pip install virtualenv الأمر الأول معني بتحديث أداة pip والثاني يقوم بتنصيب أداة virtualenv، قد تحتاج إلى إضافة sudo إلى بداية الأمرين إن لم تكن تملك صلاحيات مُدير النّظام (خاص بأنظمة Gnu/Linux و OSX). $ sudo pip install -U pip $ sudo pip install virtualenv تنصيب Flask سنستعمل أداة virtualenv لإنشاء بيئة وهميّة، أولا قم بإنشاء مُجلّد باسم flask_app أو باسم من اختيارك، بعد إنشاء المُجلّد يُمكنك الانتقال إلى مساره بسطر الأوامر وذلك بتنفيذ الأوامر التالية على الطّرفيّة Terminal، بالنّسبة لمُستخدمي Windows فيُمكن تنفيذ هذه الأوامر باستخدام طرفيّة PowerShell: $ mkdir ~/flask_app $ cd ~/flask_app بعدها يُمكنك يُمكنك إنشاء بيئة وهميّة باسم venv (اختصارا فقط) بالأمر التّالي: $ virtualenv venv انتظر لبضع لحظات إلى أن تُلاحظ ما يلي: Installing setuptools, pip, wheel...done. ستلاحظ بأنّ مُجلّدا جديدا باسم venv يحتوي على العديد من الملفّات قد ظهر، وهناك ستبقى الاعتماديات والمكتبات التي سنقوم بتنصيبها بأداة pip. بعد إنشاء البيئة الوهمية تبقى مهمّة تشغيلها، ويُمكن القيام بذلك بالأمر التّالي: $ . venv/bin/activate بعد تنفيذ الأمر أعلاه ستُلاحظ بأنّ سطر الأوامر قد تغيّر، وأضيفت كلمة (venv) إلى بداية السّطر، هذا يعني بأنّ كلّ شيء يعمل مثلما هو مُخطّط له. إذا أردت أن تقوم بإيقاف تشغيل البيئة الوهميّة فيُمكنك تنفيذ الأمر التّالي (لا تقم بذلك الآن): $ deactivate سنقوم الآن بتنصيب إطار العمل Flask، فقط نفّذ الأمر التّالي: $ pip install flask تنبيه نجاح العمليّة سيكون كالآتي: Successfully installed Jinja2-2.8 MarkupSafe-0.23 Werkzeug-0.11.5 flask-0.10.1 itsdangerous-0.24 تطبيقك الأول، مرحبا بالعالم بعد تشغيل البيئة الوهمية، أنشئ ملفا باسم app.py وافتحه بمُحرّرك المُفضّل، وضع به الأسطر التّالية: from flask import Flask app = Flask(__name__) @app.route("/") def hello(): return "Hello World!" if __name__ == "__main__": app.run() بعد حفظ الملفّ يكفي تشغيله بتنفيذ الأمر python app.py وستُلاحظ بأنّ الخادوم قد بدأ بالاستماع للطّلبات في المنفذ رقم 3000، ما يعني أنّك تستطيع الوصول إليه من المُتصفّح عبر العنوان http://127.0.0.1:5000 وهذا العنوان خاصّ بجهازك فقط ولا يُمكن لأحد غيرك أن يصل إليه ويُسمى عنوان المُضيف المحلي أو localhost ويُمكنك الوصول إليه من المُتصفّح من العنوان localhost:5000 كذلك. بعد الدّخول إلى العنوان عبر المُتصفّح ستُلاحظ جملة "!Hello World" على الصّفحة، لإيقاف الخادوم يُمكنك الضّغط على تركيبة المفاتيح Ctrl+c. الأسطر أعلاه هي كلّ ما تحتاج إليه لعرض نصّ على المُتصفّح، وإليك شرحا لكلّ جزء من البرنامج: هذا السّطر مسؤول عن استيراد Flask من حزمة flask (لاحظ الفرق بين حالة الحرف f). from flask import Flask نقوم بإنشاء كائن باسم app (يُمكنك تغيير الاسم على شرط أن تُغيّره في بقيّة الشيفرة)، الكائن هو الذي سيُمكننا من الوصول إلى الدوال التي يُوفرها Flask. app = Flask(__name__) السّطر التّالي هو نواة التّطبيق، وفيه تُصاغ الإجابة التي تُقدّم عند طلب الصّفحة من طرف المُتصفّح. @app.route("/") def hello(): return "Hello World!" السّطر الأول عبارة عن مُزخرف يُمكّن من ضبط المُوجّه (أي مسار الجواب) وهو ما يأتي في آخر عنوان التّطبيق http://127.0.0.1:5000 ويُمثّل / المُوجّه الرّئيسي. لتغيير المُوجّه يُمكن ببساطة تغيير قيمة المُعامل، فمثلا تعديله إلى السّطر التّالي سيُمكّننا من الوصول إلى صفحة !Hello World عبر العنوان http://127.0.0.1:5000/hello بدلا من العنوان http://127.0.0.1:5000: @app.route("/hello") بالنّسبة للدالة hello فهي مسؤولة عن تنفيذ الشيفرة التي بداخلها فور طلب الصّفحة وإرجاع قيمة نصيّة. ولإنشاء أكثر من صفحة يكفي تغيير المُوجّه Router، وتغيير اسم الدّالة. @app.route("/") def home(): page = 'Home Page' return page @app.route("/hello") def hello(): return "Hello World!" يُلاحظ أنّ اسم الدالة لا يجب تكراره بين المُوجّهات وإلا فلن يعمل التّطبيق. أما الشيفرة المُتواجدة في السّطرين الأخيرين فتقوم بتشغيل الخادوم ما يُمكّنك من الوصول إلى التّطبيق عن طريق المُتصفّح عبر العنوان http://127.0.0.1:5000. if __name__ == "__main__": app.run() الأمر ()app.run يقوم بتشغيل الخادوم ويُتيح الوصول إليه عبر جهازك فقط، أي أنّك لن تستطيع الوصول إلى التّطبيق إلا من الجهاز الذي قُمت بتشغيله منه، أما إذا كنت ترغب بأن يصل إليه من يتّصل بشبكتك المحليّة (شبكة الـ WiFi مثلا) فعليك إضافة مُعامل host بالقيمة 0.0.0.0 كالتالي: if __name__ == "__main__": app.run(host='0.0.0.0') ستتمكن الآن من الوصول إلى التّطبيق من أي جهاز مُتصل بالشّبكة المحليّة عبر عنوان IP جهازك متبوعا برقم المنفذ (مثلا http://192.168.1.5:5000). ويُمكنك الحصول على عنوان IP جهازك عبر تنفيذ الأمر ifconfig على أنظمة جنو/لينكس وأنظمة OS X والأمر ipconfig خاص بمُستخدمي نظام Windows (ستجد العنوان في السّطر الذي يحتوي على IPv4). للحصول على العنوان وحده في أنظمة جنو/لينكس يُمكن تنفيذ الأمر التّالي من الطّرفيّة: $ ifconfig | grep 'inet addr:' | cut -d: -f2 | awk '{ print $1}' لتغيير رقم المنفذ، يُمكن إضافة العامل port مع تعيين رقم منفذ أكبر من 1024 لأنّ كلّ المنافذ ذات الأرقام الصغيرة تتطلّب صلاحيات المُدير، في المثال التالي سنقوم باستعمال الرّقم 1200 كمنفذ للتّطبيق. if __name__ == "__main__": app.run(host='0.0.0.0', port=1200) اللغة العربية عرض اللغة العربية سيحتاج إلى إضافة السطر: # -*- coding:utf8 -*- إلى بداية الملفّ، كما يجب على السّلاسل أن تُسبق بحرف u. @app.route("/hello") def hello(): return u""" <h1 style="direction:rtl"> مرحبا بالعالم! </h1> """ لاحظ بأنّنا أحطنا شيفرات HTML بثلاثة علامات تنصيص لأنّها مُتعدّدة الأسطر. سيُصبح التّطبيق كما يلي: # -*- coding:utf8 -*- from flask import Flask app = Flask(__name__) @app.route("/") def home(): page = 'Home Page' return page @app.route("/hello") def hello(): return u""" <h1 style="direction:rtl"> السّلام عليكم ورحمة الله وبركاته </h1> """ if __name__ == "__main__": app.run() إذا قُمت الآن بزيارة العنوان http://127.0.0.1:5000/hello فستجد صفحة تحتوي على جملة "السّلام عليكم ورحمة الله وبركاته" بخط كبير (بسبب الوسم h1). أما إذا قمت بالدّخول إلى العُنوان http://127.0.0.1:5000 فستجد عبارة Home Page. مع ملاحظة بأن استعمال هذه الطّريقة لتقديم صفحات HTML غير مُجد وغير مرن وقد يجعل التّطوير صعبا في حالة كان التّطبيق مُتعدّد الصفحات، ومن الأفضل فصل ملفّات HTML مع ملفّات لغة Python وذلك لمزيد من التّنسيق وسهولة صيانة التّطبيق، ويُمكن فصلهما بمُحرّك القوالب Jinja2 الذي سنتعرّف عليه في الدّرس القادم. تمرير المتغيرات في عنوان Url الحصول على قيمة من العنوان يُمكن الحصول على قيم مُباشرة من العنوان، ويُمكننا توظيفها في الشيفرة، فمثلا يُمكننا الذهاب إلى العنوان http://127.0.0.1:5000/say_hello/Abdelhadi وسنستطيع الوصول إلى القيمة Abdelhadi كمُعامل بحيث يُمكننا إرجاعها مع جملة ترحيب أو تنفيذ أي عمليّة أخرى. ولنقوم بالأمر سنُضيف أوّلا مُوجّها جديدا باسم say_hello ولكن مع وضع المُعامل داخل علامتي <> وسنُمرّر اسم المُعامل إلى الدّالة كذلك، انظر ما يلي: @app.route("/say_hello/<name>") def say_hello(name): return u"Hello {}".format(name) إذا قُمت الآن بالذهاب إلى العنوان http://127.0.0.1:5000/say_hello/Abdelhadi فستجد عبارة Hello Abdelhadi (جرّب تغيير Abdelhadi إلى اسمك، سواء باللغة العربيّة أو باللغة الانجليزية). بعد هذا الجزء سيُصبح التّطبيق الكامل كالآتي: # -*- coding:utf8 -*- from flask import Flask app = Flask(__name__) @app.route("/") def home(): page = 'Home Page' return page @app.route("/hello") def hello(): return u""" <h1 style="direction:rtl"> السّلام عليكم ورحمة الله وبركاته </h1> """ @app.route("/say_hello/<name>") def say_hello(name): return u"Hello {}".format(name) if __name__ == "__main__": app.run() الحصول على أكثر من قيمة من العنوان الطّريقة السابقة جيّدة في حالة أدرت الحصول على قيمة مُعامل واحد، لكن ماذا لو أردت الحصول على أكثر من مُعامل؟ يُمكننا تحقيق مُرادنا عبر طلبات الـ HTTP من نوع GET، بحيث نُرسل المُعامل وقيمته في العنوان كالتّالي: http://127.0.0.1:5000/first_last?first_name=Abdelhadi&last_name=Dyouri بحيث تُمرّر المفاتيح والقيم التّاليّة: first_name=Abdelhadi last_name=Dyouri لاحظ بأنّنا نفصل بين المُعامل والآخر برمز &. وبالطّبع يُمكنك تمرير مُعامل واحد فقط. http://127.0.0.1:5000/first_last?first_name=Abdelhadi للوصول إلى قيم هذه المُعاملات، سنستخدم الوحدة request التي يُوفّرها إطار Flask وسنستوردها جنبا إلى جنب مع Flask في السّطر الثاني من البرنامج كالتّالي: from flask import Flask, request بعد ذلك سنتمكّن من الوصول إلى قيمة مُعامل كالتّالي: request.args.get('parameter') تطبيق سنُطبّق هذا بإنشاء تطبيق لعرض الاسم الأول للشّخص بأحرف صغيرة مع تكبير الحرف الأول، والاسم الثاني سيكون بأحرف كبيرة، وسنستعمل الدوال upper و capitalize. أولا سننشئ مُوجّها جديدا باسم first_last بعدها سنقوم بالحصول على قيمتي المُعاملين first_name و last_name، ثمّ سنحولّ الاسم الأول باستخدام التّابع capitalize وسنُحوّل الاسم العائلي إلى أحرف كبيرة بالتّابع upper، سنعرضه النتيجة بعد ذلك في وسمي h3 كلّ في سطر. @app.route("/first_last") def first_last(): first_name = request.args.get('first_name').capitalize() last_name = request.args.get('last_name').upper() return "<h3>First Name: {} <br>Last Name: {}</h3>".format(first_name, last_name) يُمكنك تصفّح شيفرة هذا الدّرس وتنزيلها من موقع Github عبر هذا الرّابط تشغيل مصحح الأخطاء Debugger يأتي Flask بمُصحّح أخطاء يعرض مصدر الخطأ مُباشرة على المُتصفّح، ويُنصح باستعماله ليسهل عليك تحديد مصدر الخطأ لإصلاحه. يُمكن تشغيل مُصحّح الأخطاء عبر إضافة مُعامل debug بقيمة True إلى التّابع run. if __name__ == "__main__": app.run(debug=True) وهذه صورة لمُصحّح الخطأ بعد وقوع خطأ في تطبيق Flask. وقع الخطأ لأنّ القيمة الافتراضيّة لمُعامل مُعيّن عند عدم تحديد قيمة له هي None ما يعني بأنّك لا تستطيع تنفيذ التّابع upper الخاص بالسّلاسل النّصية. يُمكنك مُشاهدة هذا الخطأ بالذهاب إلى العنوان http://127.0.0.1:5000/first_last?first_name=abdelhadi لاحظ الجملة الأولى 'AttributeError: 'NoneType' object has no attribute 'upper هذا الخطأ وقع بعد تنفيذ التّابع upper على القيمة None وهذا لأنّنا لم نُوفّر قيمة للمُعامل last_name. خاتمة تعرّفنا إلى الآن على أساسيات التّعامل مع المُوجّهات، وكيفيّة تقديم صفحات HTML للمُتصفّح أو الزّائر، وسنتعرّف في الدّرس القادم بإذن الله على كيفيّة استعمال مُحرّك القوالب Jinja2 لتقديم ملفّات HTML مُستقلّة وكيفيّة استعمال بعض الأساليب البرمجيّة فيه.
  15. بعد أن تعرّفنا في الدّرس السابق على أساسيات البرمجة كائنية التوجّه، سنُكمل في هذا الجزء ما بدأناه وسنتعلّم بعض المبادئ المتقدّمة حول البرمجة كائنيّة التّوجه. تغيير قيمة متغير الصنف في الدّرس السّابق تعلّمنا كيفيّة تعريف مُتغيّر داخل صنف وكيفيّة الوصول إليه، في هذا الجزء من هذا الدّرس سنتعرّف على كيفيّة استخدام هذه المُتغيّرات بشكل أكثر واقعيّة، لنقل مثلا بأنّنا نمتلك صنفًا باسم Car (سيارة)، ونريد أن ننشئ كائنات من هذا الصّنف، بحيثُ يكون لكل كائن قيم مُختلفة لمُتغيّرات الصّنف، انظر ما يلي: class Car: name = None speed = 0 brand = None def specs(self): print '{} speed is {}Km/h and it\'s brand is {}'.format(self.name, self.speed, self.brand) أنشأنا أعلاه صنفا بسيطا باسم Car مع ثلاثة مُتغيّرات name لاسم السّيارة، speed لسرعة السّيارة و brand لاسم العلامة التّجاريّة، كلمة None تُشير إلى أنّ المُتغيّر مُعرّف لكنّه لا يحمل أية قيمة. بعدها عرّفنا تابعا specs (اختصار لـ specifications) لطباعة مواصفات السّيارة. لننشئ كائنات مُتعدّدة من الصّنف الذّي كتبناه للتو. # Toyota Corolla corolla = Car() corolla.name = 'Toyota Corolla' corolla.speed = 200 corolla.brand = 'Toyota' # Ford Focus focus = Car() focus.name = 'Ford Focus' focus.speed = 220 focus.brand = 'Ford' # Honda Civic civic = Car() civic.name = 'Honda Civic' civic.speed = 210 civic.brand = 'Honda' بعد أن أنشأنا الصّنف والكائنات المندرجة تحت هذا الصّنف، وقمنا بتعيين قيم المُتغيّرات التي تُعتبر مواصفات كلّ سيارة، يُمكننا أخيرا طباعة مواصفات كل سيارة (كائن) وذلك باستدعاء التابع specs. corolla.specs() focus.specs() civic.specs() وكما تتوقّع، المُخرج سيكون كالتّالي: Toyota Corolla speed is 200Km/h and it's brand is Toyota Ford Focus speed is 220Km/h and it's brand is Ford Honda Civic speed is 210Km/h and it's brand is Honda إرجاع الصنف داخل تابع يُمكنك أن تقوم بكتابة تابع داخل صنف، بحيث يقوم التابع بتنفيذ شيفرة ما ثمّ إعادة الصّنف نفسه (ما نُشير إليه بالكلمة self) وبهذا ستتمكّن من استدعاء التابع أكثر من مرّة في سطر واحد، تأمل ما يلي: class Car: def start(self): print 'Starting engine…' return self ما فعلناه في الشّيفرة أعلاه ليس بالشيء الكثير، أولا نقوم بتعريف الصّنف ثمّ بعد ذلك نُعرّف التّابع start المسؤول عن تشغيل السّيارة، وبعدها نطبع جملة تُفيد بأنّ مُحرّك السّيارة قيد التّشغيل، بعد تنفيذ الشيفرة سيُرجع التّابع الصّنف نفسه. ما سيُمكّننا من استدعاء التّابع أكثر من مرّة في سطر واحد كما يلي: corolla = Car() corolla.start().start().start() المُخرج سيكون كالتّالي: Starting engine… Starting engine… Starting engine… كما تُلاحظ لقد نُفّذت الشّيفرة الموجودة داخل التّابع start ثلاث مرّات. قد تتساءل عن أهميّة الأمر، وأتّفق معك في أنّ الأمر يُمكن أن لا يكون مُفيدا. لكنّه يكون مُفيدا إذا أردت أن تقوم بتنفيذ تابعين بشكل تسلسلي، لنقل بأنّ لدينا تابعا آخر باسم move ولنفرض بأنّه سيكون مسؤولا عن تحريك السّيارة، سيكون من الأفضل لو استطعنا أن نستدعي تابع الحركة مُباشرة بعد استدعاء تابع التّشغيل. بحيث يبدو الاستعمال كالتّالي: corolla.start().move() يُمكننا أن نقوم بالأمر ببساطة، وفي الحقيقة لن نحتاج إلا لإضافة التابع move لما كتبناه سابقا. class Car: def start(self): print 'Starting engine…' return self def move(self): print 'The car is moving…' بهذه الطّريقة سنتمكن من تنفيذ الشيفرة دون مشاكل: Car().start().move() المُخرج: Starting engine… Starting engine… The car is moving… لكن لاحظ هذه المرّة بأنّنا لم نُرجع كلمة self في التّابع move ما يعني بأنّنا لن نتمكن من القيام باستدعاء التابع أكثر من مرّة: Car().start().move().move() إذا حاولت أن تُنفّذ الأمر السّابق ستحصل على خطأ كالتّالي: AttributeError: 'NoneType' object has no attribute 'move' وهذا راجع لكوننا لم نُرجع الصنف في آخر التّابع move. الوراثة مفهوم الوراثة في البرمجة كائنيّة التوجه لا يختلف كثيرا عن مفهوم الوراثة في العالم الواقعي، الصّنف الابن يرث جميع المتغيرات والتوابع من الصّنف الأب، يُمكن التّفكير في الأمر على أنّه نسخ. أي أنّ الصّنف الابن مُجرّد نُسخة طبق الأصل من الصّنف الأصلي، الفرق هنا هو أنّك تستطيع أن تُضيف المزيد من الخصائص والتوابع للصّنف الابن. وطريقة إنشاء صنف يرث من صنف آخر هي بوضع الصّنف الأب بين قوسين عند إنشاء الصّنف الابن. انظُر المثال التّالي: class Parent: a = 1 b = 2 class Child(Parent): c = 3 في المثال أعلاه، قُمنا بإنشاء صنف باسم Parent مع مُتغيّرين a و b، وبعدها أنشأنا صنفا Child الذي يرث خصائص الصّنف السابق، وبالتّالي فسنتمكّن من الوصول إلى مُتغيّرات الصّنف Parent من خلال الصّنف Child، ما يعني بأنّ الشيفرة التّالية ستعمل دون مشاكل: child = Child() print child.a print child.b print child.c المُخرج: 1 2 3 كما تُلاحظ فإنّنا قد استطعنا الوصول إلى المتغيّرين a و b رغم أنّهما لم يُعرّفا مُباشرة داخل الصّنف Child. يُمكن أن نجعل صنفا يرث توابع من صنف آخر بنفس الطّريقة: class Person: name = 'Person' def say_hello(self): name = self.name print 'Hello my name is {}'.format(name) class Abdelhadi(Person): name = 'Abdelhadi' استدعاء التّابع say_hello من كائن من الصّنف Abdelhadi. me = Abdelhadi() me.say_hello() المُخرج: Hello my name is Abdelhadi في الشيفرة أعلاه، قُمنا أولا بتعريف صنف "شخص" باسم Person ثمّ عرّفنا المُتغيّر name داخل الصّنف، وأعطيناه قيمة افتراضيّة، بعدها عرّفنا التّابع say_hello ليطبع جُملة التّرحيب. متغيرات الصنف المبنية مسبقا توجد مُتغيّرات مبنية مُسبقا في لغة بايثون، وتُسمى هذه المُتغيّرات بمُتغيّرات الصّنف، وما نعنيه بأنّها مبنية مُسبقا هو أنّك لا تحتاج إلى تعريفها، وتمتاز هذه المُتغيّرات بأنّها مُحاطة بتسطيرين سُفليّين Underscores وإليك بعضا من هذه المُتغيّرات: __doc__ سلسلة توثيق الصنف (Documentation string) وهو ما يُكتب مُباشرة بعد تعريف الصنف، ويحتوي في الغالب معلومات حول وظيفة الصّنف. القيمة الافتراضية لهذا المتغير هي None ألق نظرة على الصّنف التالي: class Person: ''' This class does nothing ''' pass لاحظ بأنّ سلسلة التوثيق مُحاطة بثلاث علامات تنصيص إذا أردنا الوصول إلى هذا التوثيق فكلّ ما علينا فعله هو استخدام الصّفة __doc__: print Person.__doc__ المُخرج: This class does nothing __module__ الوحدة التي عُرّفَ فيها الصّنف، وقيمتها الافتراضية هي'__main__'. print Person.__module__ المخرج: __main__ __dict__ هذا المُتغيّر عبارة عن قاموس يحمل ما سبق كقيم بدئية، كما يحمل أسماء المتغيّرات التي تُنشؤها أنت وقيمها وكذلك أسماء التوابع، لاحظ المثال التالي (نفّذه مُباشرة على مُفسّر بايثون لتُلاحظ النّتيجة): >>> class Math: ... x = 1 ... y = 2 ... def x_plus_y(self): ... return self.x + self.y ... >>> Math.__dict__ {'y': 2, 'x': 1, '__module__': '__main__', '__doc__': None, 'x_plus_y': <function x_plus_y at 0x7f186e76a6e0>} كما تُلاحظ مُخرجات القاموس تحتوي على كل من قيم المُتغيرات الخاصّة بالصّنف سواء التي عرّفناها أو المبنية مُسبقا، لاحظ كذلك العنصر الأخير من القاموس: 'x_plus_y': <function x_plus_y at 0x7f186e76a6e0>} هذا العنصر يحمل مفتاحا باسم التابع x_plus_y الذي عرّفناه، وقيمة هذه المفتاح تُشير إلى أنّه دالة. __name__ اسم الصّنف، يُمكنك تطبيقه على أي صنف للحصول على اسمه، انظر المثال التالي: >>> a = Math >>> a.__name__ 'Math' كما تُلاحظ فقد حصلنا على اسم الصنف Math. الوصول إلى الصنف الخاص بكائن ما المُتغيّرات التي ذكرناها سابقا خاصّة بالصّنف فقط ولا يُمكن الوصول إليها من كائن من هذا الصّنف. تأمّل الصّنف التالي: class Person: name = 'Abdelhadi' لننشئ الآن كائنا من هذا الصّنف: me = Person() يُمكننا الآن الوصول إلى قيمة المُتغيّر name كالتالي: >>> me.name 'Abdelhadi' لكننّا لن نستطيع الوصول إلى مُتغيّرات الصّنف من الكائن، بل من الصّنف فقط: person_class = Person person_class.__name__ # الشيفرة صحيحة person_object = Person() person_object.__name__ # الشيفرة خاطئة لأنّنا نحاول الوصول إلى مُتغيّر غير مُعرّف داخل الكائن ستحصل على خطأ من نوع AttributeError عند تنفيذ السّطر الأخير: AttributeError: Person instance has no attribute '__name__' الحل الأمثل هو أن نصل إلى الصّنف انطلاقا من الكائن، وبعدها سنتمكّن من الوصول إلى مُتغيّرات/صفات الصّنف دون مشاكل، وطريقة الوصول إلى صنف كائن هي بإلحاقه بكلمة __class__، انظر المثال التّالي (سنعتمد على الصنف الذي أنشأناه أعلاه): person_object = Person() person_object_class = person_object.__class__ # إسناد صنف الكائن لمتغيّر print person_object_class.__name__ # اسم الصّنف print person_object_class.__dict__ # قاموس يحتوي على بيانات الصّنف بدأنا بإنشاء كائن person_object ثمّ استخدام جُملة __class__ للوصول إلى الصّنف. المُخرج: Person {'__module__': '__main__', 'name': 'Abdelhadi', '__doc__': None} يُمكنك كذلك القيام بالأمر داخل تابع في الصّنف: class Person: def say_hello(self): print 'Hi I am a {}'.format(self.__class__.__name__) person_obj = Person() person_obj.say_hello() لاحظ استخدام self.__class__.__name__ للوصول إلى اسم الصّنف في التّابع say_hello. المُخرج: Hi I am a Person التوابع الخاصة يُمكن استخدام بعض التّوابع الخاصّة لتنفيذ شيفرة عند القيام بإجراء معيّن، وإليك قائمة بأهم هذه التّوابع (لاحظ بأنّها مُحاطة بتسطيرين سُفليّين Underscores). التابع init: تُنفَّذُ الشيفرة التي بداخله عند إنشاء كائن من الصّنف، ويُسمّى أيضا بتابع البناء Contractor . التابع del: تُنفّذ شيفرته عند حذف كائن أو عند استدعاء دالة الخروج exit. التابع repr: تُنفّذ الشيفرة عند استدعاء الكائن، ويُستخدم هذا التابع لإرجاع معلومات حول الكائن في الوضع التّفاعلي (من مُفسّر لغة بايثون مُباشرة) مثال: # استدعاء __init__ person_obj = Person() # استدعاء __repr__ person_obj repr(person_obj) # حذف الكائن واستدعاء __del__ del(person_obj) التابع init هذا مثال بسيط على إنشاء واستدعاء هذا التّابع: class Person: def __init__(self): print 'A new object was created' me = Person() مُخرج البرنامج سيكون جُملة تُفيد بأنّ كائنا قد أنشئ، لاحظ أنّ الجملة A new object was created قد طُبعت رغم عدم استدعاء التّابع init بشكل صريح، ويُمكن الحصول على نفس المُخرج باستدعاء التّابع كالتّالي: me.__init__() حسنا تعلّمنا الآن بأنّنا نستطيع تنفيذ الشيفرة الموجودة بداخل التّابع __init__ بمُجرّد إنشاء كائن من الصّنف، ولكن ماذا عن المُعاملات؟ يُمكن تمرير المُعاملات للتّابع __init__ عند إنشاء صنف كالتّالي: me = Person('Abdelhadi') وفي التّابع سيكون الأمر كالتّالي: def __init__(self, name): name = self.name print 'Hello My name is {}'.format(name) الشيفرة الكاملة: class Person: def __init__(self, name): self.name = name print 'Hello My name is {}'.format(name) me = Person('Abdelhadi') المُخرج: Hello My name is Abdelhadi التابع repr يُستعمل هذا التّابع لإرجاع معلومات قابلة للطّباعة، ويُستخدم كثيرا في الوضع التّفاعلي (مُفسّر بايثون)، ويجب أن تكون القيمة المُرجعَةُ عبارة عن سلسلة نصيّة. وإليك مثالا لكيفيّة استخدامه: class Math: x = 1 y = 2 def __repr__(self): x = self.x y = self.y return 'x: {}, y: {}'.format(x, y) x_y = Math() print x_y المُخرج: x: 1, y: 2 يُمكننا الاستفادة من هذا التّابع للوصول إلى اسم الصنف عند الوراثة: # تعريف الصّنف الرّئيسي class Person: def __repr__(self): return 'Hi I am a {}'.format(self.__class__.__name__) # الوراثة class Writer(Person): pass class Student(Person): pass # إنشاء الكائنات omar = Student() abdelhadi = Writer() # طباعة قيّم التّابع repr print omar print abdelhadi المُخرج: Hi I am a Student Hi I am a Writer لاحظ بأنّ الصّنفين Writer و Student لا يحتويان على أية شيفرة، ومع ذلك فقد نُفّذ التّابع repr واستجاب بطريقة مُختلفة مع كلّ كائن. التابع del تُنَفّذُ الشّيفرة الموجودة بداخل هذا التّابع عند حذف كائن باستعمال الدّالة del وهي دالة تُستعمل لإنجاز ما يُسمى بعمليّة جمع القُمامة Garbage Collecting والهدف الرئيسي من هذه العمليّة هو تحرير الذاكرة، ولحذف كائن يكفي أن تقوم باستدعاء الدّالة del مع تمرير الكائن كمُعامل: class Math: x = 1 y = 2 numbers = Math() numbers.x # ==> 1 numbers.y # ==> 2 # حذف الكائن del(numbers) # خطأ numbers.x # ==> NameError: name 'numbers' is not defined بعد أن حذفنا الكائن numbers لم يعد بإمكاننا الوصول إلى قيمة المُتغيّر x، وأسفر الأمر عن خطأ من نوع NameError. يُستدعى التابع del مُباشرة بعد حذف الكائن، ما يعني بأنّنا نستطيع أن نطبع جملة تُفيد بأنّ الكائن قد حُذف: class Math: x = 1 y = 2 def __del__(self): print 'Object deleted!' numbers = Math() numbers.x # ==> 1 del(numbers) المُخرج: Object deleted! تُنفَّذ شيفرة __del__ كذلك عند استدعاء الدالة exit للخروج من البرنامج: class Math: x = 1 y = 2 def exit_program(self): exit() def __del__(self): print 'Object deleted!' numbers = Math() numbers.exit_program() مُخرَج البرنامج أعلاه سيكون نفس الشيء رغم عدم حذف الكائن. والسبب راجع لاستخدام الدّالة exit داخل التّابع exit_program. تمارين تمرين 1 عد إلى الدّروس السّابقة وحاول تحويل برنامج تسجيل الدّخول إلى برنامج سهل القراءة والاستخدام باستعمال البرمجة كائنية التوجه، فمثلا يُمكن أن يستعمل من قبل مُبرمجين آخرين بالطّريقة التّالية: user = User() user.signup('username', 'password', 'password_confirmation') user.login('username', 'password') user.say_hello() user.logout() تمرين 2 أنشئ برنامجا يطبع جميع التوابع والمُتغيّرات الموجودة داخل الصّنف الذي أنشأته كحل للتّمرين الأول.
  16. بعد أن تعرّفنا على أساسيات لغة بايثون حان الوقت للانتقال إلى مرحلة جديدة. في هذه السّلسلة من الدّروس سنتعرّف على أساسيات تطوير تطبيقات الويب بلغة بايثون، وذلك بالاستعانة بإطار العمل Flask، يعتبر Flask إطارا مُصغّرا Micro-Framework أي أنّه يُقدّم للمُبرمج أدوات مُساعدة بسيطة، وبعكس إطار Django فهو مُناسب للمُبتدئين الذين تعرّفوا على لغة بايثون حديثا. متطلبات هذه السلسلة لمتابعة هذه الدّروس وفهمها، ستحتاج إلى معرفة بسيطة بلغة بايثون. ستحتاج كذلك إلى معرفة بسيطة بلغة HTML الهيكلية، وكذلك القليل من لغة CSS لتنسيق الصّفحات إذ لن أشرح ما يتعلق بلغة HTML وCSS لأنّ ذلك ليس من اختصاص السّلسلة. يمكنك مراجعة الدروس التالية على أكاديمية حسوب لتعلم أساسيات هذه اللغات: سلسلة دروس تعلم لغة بايثون تعلّم لغة HTML ولغة CSS ما هو تطبيق الويب؟ تطبيق الويب، هو كل تطبيق يُمكن الوصول إليه عن طريق مُتصفّح للويب (Firefox ،Chrome ،Safari) ويقوم بتقديم صفحات مرئية حسب طلب الزّائر. يُمكن اعتبار موقع الأكاديمية هذا تطبيق ويب، إذ يتفاعل مع الزائر بتقديم المقالات بشكل متناسق، ويوفّر إمكانية المُشاركة للمُستخدمين عبر صندوق التّعليقات وغير ذلك من الخصائص. الصفحة التي تقرأ منها هذا المقال حاليا أصلها شيفرات لغة HTML وهي لغة أساسية في الويب. وتُستعمل لغات البرمجة مثل لغة Python لتقديم شيفرة HTML من الخادوم إلى المُتصفّح الذي يعرضها بدوره للمُستخدم. ما يعني أنّ الهدف النهائي من برمجة التّطبيق هو تقديم ملفات HTML من الخادوم إلى العميل (المُستخدم). خلاصة القول أنّك عندما تدخل إلى موقع الأكاديمية عن طريق رابط academy.hsoub.com، يرسل المُتصفّح طلبا للخادوم الخاص بالأكاديمية، عندما يستقبل الخادوم الطلب يقوم مُباشرة بتنفيذ الشيفرة المكتوبة بلغة برمجية، الشيفرة البرمجيّة تُجيب بملفات HTML ويعرضها لك المُتصفّح فور استقبالها. ما سنتعلّمه في هذه السّلسلة هو كيفيّة التعامل مع طلبات المُستخدم وكيفيّة تقديم ملفات HTML للمُتصفّح باستخدام لغة بايثون. ما هو إطار العمل؟ إطار العمل هو مجموعة من المكتبات والوحدات التي تحتوي على دوال مُساعدة تُمكّن المُبرمج من كتابة تطبيقات دون الاضطرار إلى التعامل مع التفاصيل الدقيقة التي تتطلب وقتا وجهدا كبيرين. يُمكن أن يكون إطار العمل خاصا بتطوير تطبيقات الويب مثل Flask أو Django، ويُمكن كذلك أن يكون مُخصّصا لمجالات أخرى كبناء تطبيقات سطح المكتب مثلا. تتوفّر لغة بايثون على العديد من أطر العمل الخاصّة بتطوير الويب، والتالي قائمة ببعض الأطر مع وصف مختصر لكلّ إطار. Django: إطار عمل ضخم، يتوفّر على عدد هائل من الدوال المُساعدة، كما يعتبر أنسب خيار لمن يرغب بتطوير تطبيقات كبيرة ومُعقّدة متعدّدة الوظائف، يتميّز بشهرته الواسعة وهو سهل التّعلم، يعتبر مناسبا كذلك لمن يرغب بإنشاء تطبيق بسرعة وهو شائع بين الشّركات النّاشئة. Flask: إطار عمل مُصغّر/صغير، يتوفّر على عدد لا بأس به من الدوال المُساعدة، شهرته تقريبا بنفس شهرة Django، مُناسب لتطوير تطبيقات صغيرة ومُتوسّطة (مُدونة، منتدى، موقع شخصي… ). Tornado: إطار عمل مُخصّص للتطبيقات التي تتطلب سرعة في مُعالجة الطّلبات وسرعة في التجاوب كتطبيقات الدّردشة مثلا. Bottle: إطار عمل صغير جدا، يوفّر أدنى المُتطلبات لتطوير تطبيق بسرعة، ويعتبر أصغر من إطار Flask. سبق وأن نشرنا درسا عنه. TurboGears: خصائصه تقترب من خصائص إطار Django، الاختلاف الرئيسي يكمن في الأدوات والمكتبات التي يعتمد عليها كالاتصال بقواعد البيانات وما إلى ذلك ويُعتبر خيارا آخر لمن يرغب بتطوير تطبيقات كبيرة. صحيح أن هناك أطر عمل أخرى لكنّ ما تقدّم ذكره يعتبر أبرزها. لماذا Flask؟ وقع الاختيار على إطار العمل Flask لسهولة تعلّمه بالنّسبة للمبتدئ، إذ سيبدو مألوفا لمن تعرّف حديثا على لغة بايثون، وبما أنّه إطار عمل مُصغّر فسيسهل عليك فهم خطوات إنشاء تطبيق كامل، خاصّة أنّك تستطيع أن تبني تطبيقا في ملفّ بايثون واحد. يتميّز إطار Flask كذلك بإتاحة إمكانيّة ربط تطبيقك بمُختلف مكتبات لغة بايثون، والتي يُمكنك تنصيبها بسهولة بأداة pip، وهي أداة لإدارة الحزم (مثل Gem بالنّسبة للغة روبي و Composer بالنّسبة للغة PHP). يُمكن كذلك الاعتماد على إضافات لجعل الإطار أقرب إلى الأطر الكبيرة مثل Django إذ يمتلك إطار العمل Flask العديد من الإضافات التي يُمكنك تنصيبها واستعمالها في مشروعك، ما يُمكن أن يُساعدك على إنشاء مشاريع كبيرة. Flask أم Django؟ يعتبر الاختيار بين إطار Flask وإطار Django من القرارات الصّعبة على المُبتدئ، لكنّ عليك فهم الفرق بين الإطارين لتختار ما يُناسبك، فكما قلنا سابقا فإطار Django يُوفّر عددا هائلا من الدوال والأدوات المُساعدة، أما إطار Flask فيُوفّر أدوات بسيطة وعددا أقلّ من الدوال المُساعدة. يُمكنك اختيار تعلّم إطار Django إذا كانت لديك خبرة مُسبقة بأحد أطر العمل في اللغات الأخرى مثل Laravel أو Ruby On Rails، كما يُنصح به إذا كان المشروع الذي ستعمل عليه كبيرا كتطبيق تواصل اجتماعي أو تطبيق خدمي. أما إذا لم تكن تملك أية خبرة مُسبقة فأنصح بتعلّم إطار Flask أولا، وبعد التمكن من التعامل معه وإتقان ذلك يُمكنك الانتقال إلى استعمال Django متى ما دعت الحاجة إلى ذلك، وستجد حينها بأنّ الوقت الذي استثمرته في تعلّم Flask قد أتى أكله، وسيسهل عليك تعلّم إطار Django وفهم كيفيّة عمله. كيف تستفيد من هذه السلسلة من الدروس؟ سلسلة الدروس هذه ستكون موزعة حسب المُخطّط التالي: إعداد بيئة التّطوير وإنشاء تطبيقك الأول تقديم ملفات HTML وملفات CSS والصور استخدام قاعدة بيانات مع تطبيق Flask كل درس سيكون شبه مُستقل عن الدّرس الذي يسبقه، وذلك لتكون الدروس مرجعا لك في حالة نسيان أي جزئية. في نهاية السّلسلة ستكون قادرا على استعمال لغة بايثون لتطوير تطبيق يعمل على المُتصفّح ويتصل بقاعدة بيانات. ختاما في الدّرس المُقبل سنقوم بإعداد بيئة التّطوير بتنصيب الأدوات المطلوبة، كما سننشئ تطبيقا بسيطا لعرض صفحة ويب على المُتصفّح.
  17. تعرّفنا فيما سبق من دروس هذه السلسلة على أساسيات لغة بايثون، من مُتغيّرات وحلقات تكرار إلى الدوال، وقد حان الوقتُ للدخول إلى أساسيات البرمجة كائنية التوجّه Object Oriented Programming وهي ببساطة طريقة أخرى للبرمجة بحيث تكون أجزاء الشّيفرة مجموعة داخل دوال تُسمّى التوابع methods والدوال تكون داخل صنف معيّن Class. عند إنشاء كائن object من هذا الصنف فإنّنا نستطيع أن نُنفّذ عليه مُختلف العمليات الموجودة داخل التوابع والتي بدورها توجد داخل الصنف. هناك تسميّات عربية أخرى لهذا النّوع من البرمجة، لذا لا تقلق إذا صادَفتَ أحد هذه التّسميات في أماكن أخرى، فكلّها تُشير إلى نفس المعنى: برمجة غرضيّة التوجه برمجة شيئية المنحى برمجة كائنيّة المنحى بنية الصنف Class الصنف ببساطة يحتوي على أجزاء مُختلفة من الشيفرة تماما مثل الدالة، الفرق هنا هو أنّ الصنف يحتوي على دوال كذلك، وهذه الدوال تُسمى التّوابع، ويحتوي كذلك على مُتغيّرات وتنقسم هذه الأخيرة إلى نوعين، مُتغيّر الصنف، والمُتغيّر العادي، الفرق بينهما هو أنّك تستطيع الوصول إلى مُتغيّر الصنف في أي مكان داخل الصنف (سواء داخل التوابع أو خارجها). إنشاء صنف لإنشاء صنف في لغة بايثون كلّ ما عليك فعله هو كتابة كلمة class وبعدها اسم الصنف ثمّ إلحاق نقطتين، بعدها اكتب الشيفرة بإزاحة أربع مسافات: >>> class My_class: ... pass أنشأنا أعلاه صنفًا بسيطا باسم My_class وهو لا يفعل أي شيء يُذكر (كلمة pass تُخبر بايثون بالمرور دون تنفيذ أي شيء). إذا كتبت اسم الصنف على مفسّر بايثون فستجد مُخرجا كالتّالي: >>> My_class <class __main__.My_class at 0x7fd0efc41460> لاحظ بأنّ الكلمة الأولى من المُخرج هي class أي أنّنا أصبحنا نمتلك صنفًا جديدًا، ما يتبع at هو المكان في الذاكرة الذي وُضع فيه الصنف ويتغيّر بين الحين والآخر. إنشاء كائن من صنف بعد أن أنشأنا الصنف سنتمكّن الآن من إنشاء كائن من هذا الصنف، والكائن مُجرّد اسم تماما كالمُتغيّر: my_object = My_class() الآن الكائن my_object هو من صنف My_class. تعريف المتغيرات داخل صنف يُمكننا أن نُعرّف مُتغيّرات في الصنف تماما كما نُعرّف المُتغيّرات بشكل عادي. class My_class: my_variable = 'This is my variable' للوصول إلى المُتغيّر ننشئ أولا كائنا من الصنف وبعدها نكتب اسم الكائن ثمّ نقطة ثمّ اسم المُتغيّر: my_object = My_class() print my_object.my_variable المُخرج: This is my variable يُمكن كذلك الحصول على النّتيجة ذاتها في سطر واحد: print My_class().my_variable إنشاء التوابع التوابع هي دوال خاصّة بالصنف، ويُمكننا إنشاء التابع بنفس الطّريقة التي نُنشئ بها الدالة، الإختلاف هنا هو أنّ جميع التوابع يجب أن تُعرّف مع مُعامل باسم self وذلك للإشارة إلى أنّ الدالة/التابع تابع للصنف، لننشئ تابعا داخل صنف الآن. class My_class: my_variable = 'This is my variable' def my_method(self): print 'This is my method' الآن إذا أنشأنا كائنا فإنّنا سنتمكّن من الوصول إلى التابع، وتذكّر بأنّ التابع تلحقه الأقواس: my_object = My_class() my_object.my_method() المُخرج: This is my method يُمكن كذلك الحصول على النّتيجة ذاتها في سطر واحد: My_class().my_method() كما تُلاحظ فقد نُفّذت الشيفرة الموجودة داخل التّابع my_method ويُمكننا كذلك أن نجعل التّابع يقبل المُعاملات، لكن تذكّر الحفاظ على الكلمة self كمُتغيّر أول. class My_class: my_variable = 'This is my variable' def my_method(self, my_parameter): print 'This is my method ; {} is my parameter'.format(my_parameter) يُمكنك استدعاء التّابع كالتّالي: my_object = My_class() my_object.my_method('Parameter1') my_object.my_method('Parameter2') المُخرج: This is my method ; Parameter1 is my parameter This is my method ; Parameter2 is my parameter في البرنامج السّابق، أنشأنا أولا صنفًا باسم My_class وقُمنا بتعريف مُتغيّر، ثمّ بتعريف تابع باسم my_method يقبل مُعاملين self و my_parameter، بالنّسبة لاستدعاء التّابع، فنحتاج فقط إلى تمرير المُعاملات الموجودة بعد المُعامل selfولا نحتاج إلى تعيين قيمة لهذا المُعامل. مُلاحظة: يُمكنك إعادة تسميّة المُعامل الأول كما تشاء، أي أنّ البرنامج التّالي سيعمل دون مشاكل. class My_class: def my_method(this, my_parameter): print '{} is my parameter'.format(my_parameter) ولكن رغم ذلك فالمُتعارف عليه بين مُبرمجي لغة بايثون هو استعمال self، وفي كثير من اللغات الأخرى تُستعمل this عوضا عن self، أما في برامِجك فمن المُفضّل الإبقاء على هذه التّسميّة المُتعارف عنها، وذلك لتكون شيفراته سهلة القراءة. الوصول إلى متغيرات الصنف داخل التوابع تأمّل الصنف التّالي: class Person: lastname = 'Dyouri' job = 'Writer, Developer' def say_hello(self): name = 'Abdelhadi' print 'Hello, My name is {}'.format(name) البرنامج أعلاه بسيط جدا، أولا نعرّف صنف باسم Person وبعدها نقوم بتعيين قيمتين للمُتغيّرين name و lastname، وبعدها عرّفنا تابعا باسم say_hello يطبع جملة Hello, My name is Abdelhadi. كلّ شيء جيد، لكن ماذا لو أردنا أن نصل إلى المُتغيّرات الأخرى الموجودة خارج التّابع، فلا يُمكننا مثلا أن نقوم بالأمر كالتّالي: class Person: lastname = 'Dyouri' job = 'Writer, Developer' def say_hello(self): name = 'Abdelhadi' print 'Hello, My name is {}'.format(name) print lastname print job ستحصل على الخطأ التّالي: global name 'lastname' is not defined لتفادي هذا الخطأ سنستعمل كلمة self قبل المُتغيّر. class Person: lastname = 'Dyouri' job = 'Writer, Developer' def say_hello(self): name = 'Abdelhadi' print 'Hello, My name is {}'.format(name) print 'My Last name is {} '.format(self.lastname) print 'I am a {}'.format(self.job) استدعاء التّابع: me = Person() me.say_hello() المُخرج: Hello, My name is Abdelhadi My Last name is Dyouri I am a Writer, Developer لاحظ بأنّنا قُمنا بالوصول إلى مُتغيّر lastname عن طريق استدعائه بـ self.lastname وكذا الحال مع المُتغيّر job، وهذه الطّريقة مُشابهة لاستخدام كلمة global الفرق هنا أنّ هذه الأخيرة تُمكن من الوصول إلى المُتغيّر في كامل البرنامج، أمّا كلمة self فتُشير إلى المُتغيّر المُعرّف في الصنف الحاليّة فقط. لتفهم أكثر كيفيّة عمل الكلمة self فقط تخيّل بأنّها تحمل نفس اسم الصنف، مثلا: class Person: lastname = 'Dyouri' job = 'Writer, Developer' def say_hello(self): name = 'Abdelhadi' print 'Hello, My name is {}'.format(name) print 'My Last name is {} '.format(Abd.lastname) print 'I am a {}'.format(Abd.job) لاحظ بأنّنا غيّرنا كلمة self إلى اسم الصنف واستمرّ عمل البرنامج دون مشاكل. وبنفس الطّريقة يُمكنك أن تستدعي تابعا داخل تابع آخر في نفس الصنف: class Person: def say_name(self): print 'Abdelhadi' def say_hello(self): print 'Hello My name is:' self.say_name() المُخرج: Hello My name is: Abdelhadi ما حدث هو أنّ التّابع say_hello قام بطباعة جملة :Hello My name is ثمّ قام باستدعاء التّابع say_name الذي قام بدوره بطباعة الاسم Abdelhadi. لماذا تستعمل البرمجة الكائنية، ومتى يجب علي استخدامها قد تُلاحظ بأنّ ما يُمكنك فعله بالبرمجة الكائنيّة يُمكن القيام به بالدوال والمُتغيّرات فقط. هذا صحيح، وهو أمر واضح، البرمجة الكائنيّة تُستعمل أساسا إذا كان البرنامج الذي تبنيه مُعقّدا مع العديد من الوظائف المُتعلّقة ببعضها (كمكتبة برمجيّة)، مثلا لنقل بأنّك تُطوّر برنامجا مسؤولا عن جلب بيانات من موقع مُعيّن، وبعدها التّعديل عليها، ثمّ إخراج مستند PDF يحتوي على هذه البيانات بشكل يُسهّل قراءتها، هنا ستحتاج إلى صنف لجلب البيانات والتّعديل عليها، وصنف أخرى لتحويل البيانات إلى نصّ مقروء واضح ثمّ إلى ملفّ PDF. إذا نشرت برنامجك مع صديقك وأراد أن يعمل على الجزء الثاني لإضافة وظيفة تُمكن المُستخدم من طباعة المُستند فلا يُعقل أن يضطر للمرور على كل ما يتعلّق بجلب البيانات فقط لأنّه يريد أن يضيف خاصيّة لا علاقة لها بجلب البيانات. استعمال البرمجة الكائنيّة في هذا المشروع سيسمح لك بالتّركيز على الجزء الأول، وسيسمح لصديقك بالتّركيز على تطوير الجزء الثاني. خلاصة الأمر هي أنّك لست مضطرا لاستعمال البرمجة الكائنيّة إلا إذا كان برنامجك طويلا يحتوي على وظائف تتعلّق ببعضها البعض (وظائف من نفس الصنف)، ونسبة استخدام الآخرين لشيفرتك عالية. تمارين التمرين 1 أنشئ صنفًا باسمك، وقم بتعريف مُتغيّرين lastname (الاسم العائلي) و age (العمر)، ثم أنشئ كائنا باسم me (أنا) وقم بطباعة اسمك العائلي وعمرك. التمرين 2 أنشئ صنفًا باسم Car (سيارة) وقم بتعريف مُتغيّرات لصفات السّيارة، مثلا brand لاسم الشّركة، release_date لتاريخ الإعلان عن السّيارة. التمرين 3 أضف توابع إلى الصنف Car التي أنشأتها في التّمرين الثّاني، يُمكن أن تكون التوابع عبارة عن عمليّات تقوم بها السّيارة مثلا move للحركة، stop للتوقّف، slow_down لتخفيض السّرعة، وقم بطباعة جمل تفيد بأنّ العمليّة قد نجحت. المفروض أن يتمكّن الآخرون من إنشاء كائنات خاصّة بهم بحيث تُستخدم بهذه الطّريقة: bmw = Car() bmw.move() bmw.slow_down() bmw.stop() خاتمة تعرّفنا في هذا الدّرس على بعض من أهم أساسيات البرمجة الكائنيّة التوجه في لغة بايثون وهذا الموضوع أطول من أن أشرحه في درس واحد لذلك سيكون الدّرس التّالي تكملة لما تعلّمناه في هذا الدّرس وسيغطي مفاهيم أخرى حول البرمجة كائنية التوجّه.
  18. python 101

    المُزخرفات من أعظم مميزات لغة بايثون، إذ تساعدك على بناء برنامجك باحترافية أكثر موفرة طريقة بسيطة لإضافة خاصيات جديدة للدالة. وهي ببساطة دوال تستطيع أن تعدل على دوال أخرى. تذكير ببعض المفاهيم الأساسية إذا لم تكن تعرف شيئا عن الدوال في لغة بايثون فيجب عليك العودة للدرس السابق الدوال في بايثون قبل أن تكمل قراءة هذا الدرس. تُعتبر الدوال في لغة بايثون كائنات من نوع الفئة الأولى أو First class objects. ما يعني أنّنا نستطيع القيام بالعديد من العمليات، وهي كالتالي: يُمكنك تعريف دالة داخل دالة أخرى يُمكنك أن تستدعي دالة داخل أخرى يُمكنك أن تقوم بتمرير دالة كمُعامل لدالة أخرى يُمكنك أن تُسند دالة لمُتغير يُمكنك إرجاع دالة داخل دالة أخرى بما أنّ المُزخرفات مُجرّد دوال فعلينا أن نبدأ من الأساس، لاحظ الدالة التالية: def say_hello(): print 'Hello!' عند استدعاء الدالة ستُطبع القيمة Hello على الشاشة، هذا ليس بالأمر المُعقد، الآن ماذا لو أردنا أن نعدل الدالة في جزء آخر من البرنامج لكي تطبع أشياء أخرى وتؤدي أغراضا أخرى قبل استدعاء الدالة أو بعد ذلك؟ يُمكن أن نعدّل الدالة مُباشرة، لكن هذا الأمر سيغير من طريقة سير البرنامج، إذ نريد أن نعدل الدالة في منطقة واحدة فقط من البرنامج وليس في كامل البرنامج، هذه المسألة تُحل بالمُزخرفات، وكما يدل اسمها فهي دوال تُزيّن وتُزخرف الدالة الأصلية، أي تُضيف عليها مهاما أخرى. سننشئ لهذه الدالة الآن مُزخرفا Decorator يقوم بطباعة Before قبل تنفيذ الدالة و After بعد تنفيذ الدالة، وذلك دون تعديل الدالة مُباشرة. انظر المثال التالي: def decorator(function): def function_decorator(): print 'Before' function() print 'After' return function_decorator الشيفرة أعلاه عبارة عن دالة تقبل دالة أخرى (الدالة التي نرغب بزَخرَفَتِها أو تزيينها) كمُعامل وبعدها نقوم بإنشاء دالة داخل هذه الدالة لطباعة القيمة Before ثم استدعاء الدالة الأصلية (المُعامل) بعدها طباعة After وأخيرا إرجاع الدالة الجديدة (وهي نُسخة مزخرفة من الدالة الأصلية). بعدها يُمكننا أن نستخدم هذا المُزخرف لزخرفة أي دالة مهما كانت، انظر المثال التالي: # -*- coding: utf-8 -*- def decorator(function): # إنشاء الدالة المسؤولة عن الزخرفة def function_decorator(): # إنشاء الدالة التي ستكون نسخة مزخرفة من الدالة المُمرّرة في كمُعامل print 'Before' # طباعة جملة قبل تنفيذ الدالة function() # استدعاء الدالة print 'After' return function_decorator # إرجاع الدالة مُزَخْرَفَةً def say_hello(): # إنشاء دالة عادية print 'Hello!' say_hello = decorator(say_hello) # زخرفة الدالة say_hello() # استدعاء النُسخة المُزخرفة من الدالة توفر لنا لغة بايثون طريقة أكثر مرونة لزخرفة الدوال، وهي بوضع اسم المُزخرف مسبوقا بالحرف @ قبل تعريف الدالة. أي أنّ السّطر التالي: def say_hello(): print 'Hello!' say_hello = decorator(say_hello) # زخرفة الدالة يُمكن أن يكون كالتالي: @decorator def say_hello(): # إنشاء دالة عادية print 'Hello!' وبالتالي سنتمكن من زخرفة أي دالة نرغب بزخرفتها كالتالي: @decorator def say_hello(): print 'Hello!' @decorator def say_hi(): print 'Hi!' @decorator def say_name(): print 'Abdelhadi!' say_hello() say_hi() say_name() عند تنفيذ الشيفرة أعلاه ستكون المخرجات كالتالي: Before Hello! After Before Hi! After Before Abdelhadi! After مُلاحظة: إذا كانت للدالة معاملات فما عليك إلا استخدام args* التي سبق وتحدثنا عنها في الدرس السابق. # -*- coding: utf-8 -*- def decorator(function): # إنشاء الدالة المسؤولة عن الزخرفة def function_decorator(*args): # إنشاء الدالة التي ستكون نسخة مزخرفة من الدالة المُمرّرة كمُعامل print 'Before' # طباعة جملة قبل تنفيذ الدالة function(*args) # استدعاء الدالة print 'After' return function_decorator # إرجاع الدالة مُزَخْرَفَةً لاحظ الدالتين function_decorator و function. أمثلة على المزخرفات في لغة بايثون إذا فهمت مبدأ المزخرفات فستستطيع أن تتعامل مع الدوال بمرونة عالية، وإليك بعض الأمثلة لاستخدام المُزخرفات لتأدية بعض المهام البسيطة: حساب مدة تنفيذ دالة إذا فهمت جيدا مبدأ المُزخرفات فستلاحظ بأنّك تستطيع تنفيذ مهام قبل تنفيذ الدالة ومهام بعد تنفيذها، ومما سبق نستنتج بأنّنا نستطيع أن نقوم بحفظ الوقت الحالي في مُتغير ثم تنفيذ الدالة وبعدها نقوم بحساب الفرق بين الوقت السابق والوقت الحالي، ما سيُرجع المُدة المُستغرقة لتنفيذ الدالة. البرنامج التالي مثال على مُزخرف لحساب مُدة دالة تطبع الجملة !Hello World مليون مرّة. # -*- coding: utf-8 -*- import time # جلب مكتبة الوقت لاستعمال دوال الوقت def function_time(function): def function_decorator(*args): start_time = time.time() # الحصول على وقت البداية function(*args) end_time = time.time() # الحصول على الوقت بعد نهاية التنفيذ # طباعة اسم الدالة والفرق بين وقت البداية ووقت النهاية print '%s function took %0.3f s' % (function.func_name, (end_time - start_time)) return function_decorator # إرجاع الدالة مُزَخْرَفَةً # زخرفة الدالة المسؤولة عن الطباعة مليون مرة @function_time def print_million_times(): for i in range(0, 1000000): print 'Hello World! 1,000,000 times!' print_million_times() البرنامج أعلاه سيطبع الجملة مليون مرة ثم يعرض الوقت المُستغرق لإنجاز العملية. الجملة الأخيرة ستكون شيئا كالتّالي: print_million_times function took 69.584 s ملاحظات: نستعمل التابع func_name للحصول على اسم الدالة المُمررة كمعامل، ويكون على شكل سلسلة نصية. نستعمل الجملة time.time للحصول على الوقت بالثواني، عدد الثواني الذي تنتجه الجملة هو عدد الثواني الذي مرّ منذ سنة 1970. يُمكنك استعمال هذا المُزخرف مع أي دالة تريد فقط اكتب اسم المُزخرف مسبوقا بالحرف @ ثم عرف الدالة بعده، وستحصل على الوقت المُستغرق لتنفيذ الدالة. حساب عدد مرات استدعاء دالة يُمكننا أن نستخدم المُزخرفات للحصول على عدد المرات التي استدعيت فيها دالة ما في برنامج مُعيّن، بحيث يحمل متغير قيمة العدد صفر، وفي كل مرة تستدعى فيها الدالة، فإن المُتغير يحمل القيمة مع زيادة بالعدد واحد، انظر المثال التالي. # -*- coding: utf-8 -*- # متغير العد n = 0 # المُزخرف def call_times(function): def decorated(): function() # استدعاء الدالة global n # جعل مُتغير العدّ عالميا n += 1 # زيادة قيمة المُتغير print 'Function was called', n, 'times' # طباعة قيمة المُتغير return decorated @call_times # زخرفة الدالة def func(): # إنشاء الدالة print 'Hello!' # استدعاء الدالة func() func() func() func() مُخرجات البرنامج أعلاه ستكون كالتالي: Hello! Function was called 1 times Hello! Function was called 2 times Hello! Function was called 3 times Hello! Function was called 4 times يُمكنك إصلاح الجمل من الناحية اللغوية بإضافة بعض العبارات الشرطية للبرنامج. إنشاء مزخرف لتنفيذ دالة عند تحقق شرط معين فقط يُمكنك أن تستعمل دالة تسجيل الدخول التي قُمنا بإنشائها كمُزخرف للدوال التي تحتاج لأن يكون المُستخدم مُسجلا دخوله. مثلا لنقل بأنّنا نريد أن نعرض على المُستخدم عدة خيارات بعضها يحتاج إلى تسجيل دخول المُستخدم وبعضها لا. الخيارات كالتّالي: تسجيل مُستخدم جديد (تسجيل الدخول غير مطلوب) طباعة جملة عشر مرات ( تسجيل الدخول غير مطلوب) الحصول على الوقت الحالي ( تسجيل الدخول غير مطلوب) طباعة اسم المُستخدم (تسجيل الدخول مطلوب) رؤية معلومات الحساب (تسجيل الدخول مطلوب) تعديل كلمة المرور (تسجيل الدخول مطلوب) مبدأ عمل البرنامج سيكون كالتالي: إنشاء الدوال المسؤولة عن الخيارات عرض الخيارات على المُستخدم زخرفة الدوال التي تطلب تسجيل المُستخدم بمُزخرف تسجيل الدخول المُزخرف سيتحقق من أنّ المُستخدم قد سجل دخوله، إذا كان الأمر كذلك، تنفّذ الدالة وإذا لم يتحقق الشرط فلا تنفذ. لنقل بأنّ اسم مُزخرف التحقق من تسجيل الدخول هو is_user_logged_in، ستكون الدوال التي تطلب تسجيل الدخول مُزَخْرَفَةً كالتالي: @if_user_logged_in def account_info(): print 'Username:', username, 'Password:', password تمارين تمرين 1 أنشئ دالة للجمع بين عددين، وبعدها أنشئ مُزخرفا يقوم بمُضاعفة النتيجة. تمرين 2 أنشئ دالة للحصول على قيم من المُستخدم وقم بزخرفة لطباعة جملة ترحيب قبل استدعاء الدالة وجملة توديع بعد استدعاءها. تمرين 3 أكمل البرنامج الخاص بالمثال الثالث (إنشاء مُزخرف لتنفيذ دالة عند تحقق شرط مُعين فقط). تفاصيل التمرين موجودة بالمثال.
  19. python 101

    تعلمنا إلى الآن مُعظم أساسيات لغة بايثون، تعلمنا كيفية التعامل مع أنواع البيانات المُختلفة، الحصول على مُدخلات من المُستخدم، التعابير الشرطية، حلقات التكرار واستعمال الدوال في برنامجنا لمرونة أكثر. وسنتعلم اليوم كيفيّة التعامل مع الملفات النّصية في لغة بايثون، كيفية الكتابة على ملف، وكيفية قراءة مُحتويات ملف مُعيّن. ما معنى Files I/O؟ ترجمة File هي "ملف" أما I/O فهو اختصار لـكلمتي Input و Output اللتان تعنيان المُدخل والمُخرج على التوالي. تعرفنا إلى الآن على دالتين للقيام بهاتين العمليتين الأولى هي الدالة print للإخراج والدالة raw_input للإدخال. لكنّ هذه الدوال لا تعمل إلا أثناء تشغيل البرنامج، فبعد انتهاء تنفيذه سيعود كل شيء إلى طبيعته وستفقد البيانات التي طبعتها أو التي حصلت عليها من المُستخدم. ماذا لو أردت أن تحتفظ بالبيانات في ملف ما؟ هذا بالضبط ما سنتعلمه اليوم. وإليك مُخطّطا لهذا الدرس: فتح ملف في لغة بايثون. أنماط الوصول Access modes. الكتابة على الملف. قراءة الملف. الدوال المُساعدة عند فتح ملف. إغلاق الملف. الجملة format سأستعمل في هذا الدّرس جملة جديدة لم يسبق لنا أن تحدّثنا عنها في الدروس السابقة وهي جملة format التي تُعتبر بمثابة مُحوّل لأنواع القيم المُختلفة إلى قيمة نصيّة، وتُساعد على دمج أي نوع داخل سلسلة نصّية دون الحاجة إلى تحويله بالدالة str. انظر المثال التالي: >>> '{0}, {1}, {2}'.format('a', 'b', 'c') 'a, b, c' يُمكن تبسيط الشيفرة أعلاه لتكون كالتّالي: >>> '{}, {}, {}'.format('a', 'b', 'c') إليك مثالا لطريقة الاستفادة منها في الواقع: >>> print 'Hello {} : {} : {} : {}'.format('Abdelhadi', 4, 22.4, True) Hello Abdelhadi : 4 : 22.4 : True لاحظ أنّ المُعاملات المُمرّرة للدالة قد أخذت مكان العلامات {} رغم أنّ كلّ قيمة ذات نوع مُختلف عن الأخرى. الطّريقة أعلاه أفضل بكثير من الطّريقة التّقليدية: >>> print 'Hello', 'Abdelhadi', ':', str(4), ':', str(22.4), ':', str(True) Hello Abdelhadi : 4 : 22.4 : True ويُمكنك أيضا أن تؤدي أغراضا أخرى بهذه الجملة، مثلا يُمكنك أن توزع سلسلة نصيّة على أماكن مُعيّنة في السّلسلة كالتالي: >>> '{0}, {1}, {2}'.format(*'abc') 'a, b, c' تستطيع تغيير ترتيب العناصر ببساطة: >>> '{2}, {1}, {0}'.format(*'abc') 'c, b, a' ويُمكنك أيضا أن تدمج عناصر القواميس في السلاسل النّصيّة بسهولة وذلك بالطّريقة التالية: >>> table = {'Abdelhadi': 1929, 'Ahmed': 1222, 'Omar': 1320} >>> print 'Ahmed: {Ahmed:d}; Abdelhadi: {Abdelhadi:d}; Omar: {Omar:d}'.format(**table) Ahmed: 1222; Abdelhadi: 1929; Omar: 1320 لاحظ النّجمتين ** قبل الاسم table. فتح ملف في لغة بايثون قبل أن نتعامل مع أي ملف يجب علينا أولا أن نفتحه، تماما كما تفتح أي ملف نصي للتعديل عليه بمُحرّر النّصوص. لكننا في هذا الدرس سنستعمل لغة بايثون للقيام بذلك. وتوفر لغة بايثون دالة open لفتح الملفات، والتي يُمكنك أن تستخدمها بالشكل التالي: open('filename.txt', 'Access mode') المعامل الأول المُعامل الأول هو اسم الملف، لاحظ أنّك تستطيع استبدال filename بأي اسم تريده ويُمكنك حتى أن تستبدل الامتداد، فمثلا يُمكنك أن تستعمل امتداد ملفات بايثون py بحيث تُصبح الدالة كالتالي: open('python_file.py', 'Access mode') الملف يجب أن يكون في مُجلّد العمل، إذا كنت تستعمل نظام GNU/Linux أو نظام Mac وفتحت مُفسر بايثون أو نفّذت ملفا بامتداد py فالملف يجب أن يكون في المجلد الذي قمت بالعملية منه (في الغالب يكون مجلّد المنزل home). أما إذا كنت تستخدم مُفسر لغة بايثون على نظام Windows فسيكون الملف داخل مجلّد تنصيب حزمة Python والذي غالبا ما يكون في القرص C ومجلد باسم PythonNN مع استبدال NN برقم الإصدار الخاص بلغة بايثون، فمثلا لو قمت بتنصيب الإصدار 2.7 فسيكون مسار المُجلد التالي: C:\Python27 إذا واجهت مشاكل في إيجاد مجلّد العمل يُمكنك تنفيذ الشيفرة التالية للحصول على مسار المُجلّد: >>> import os >>> os.getcwd() المُخرجات ستكون كالتالي (حسب نظام التّشغيل واسم المُستخدم لديك): '/home/dyouri' يُمكنك حفظ المُخرج في مُتغير إذا أردت ذلك. ولا تقلق إذا لم تفهم الأسطر السابقة، إذ سنتحدّث عنها في درس لاحق. المعامل الثاني بالنّسبة للمعامل الثاني (Access mode ) فهو نمط الوصول الذي ترغب بفتح الملف به وهو إما للكتابة أو للقراءة أو كليهما. انظر الفقرة التالية. أنماط الوصول Access modes عند فتح ملف في لغة بايثون، تكون مطالبا بتوفير معاملين للدالة open المُعامل الأول هو اسم الملف، والمعامل الثاني هو نمط الوصول، أي السبب الذي فتحت الملف من أجله، وهناك العديد من الخيارات لذلك، وإليك أهم الخيارات التي يجب عليك أخذها بعين الاعتبار حسب هدفك من فتح الملف: فتح الملف للقراءة r: هذا هو النمط الافتراضي إذا لم تحدد المُعامل الثاني في دالة open ويُمكنك من قراءة ملف بأحد الدوال المُتاحة لذلك (انظر فصل قراءة الملف). مثال: open('file.txt', 'r') r+: يُفتح الملف في هذا النمط للقراءة والكتابة معا، مع وضع مؤشّر الفأرة في بداية الملف. مثال: open('file.txt', 'r+') فتح الملف للكتابة w: يُفتح الملف فقط للكتابة، إذا كان الملف موجودا فإنّه يكتب عليه (Overwrite) أي أنّك ستفقد البيانات الأصلية. إذا لم يكن الملف موجودا فإنّ الدالة تنشئ ملفا جديدا للكتابة. مثال: open('file.txt', 'w') w+: فتح الملف لكل من الكتابة والقراءة، إذا كان الملف موجودا فستتم الكتابة عليه (Overwrite). إذا لم يكن الملف موجودا فإنّ الدالة تنشئ ملفا جديدا للكتابة والقراءة. مثال: open('file.txt', 'w+') a: إذا كان الملف موجودا أصلا، فسيُفتح للإلحاق Appending، أي أنّ مُكونات الملف تبقى كما هي، إذا أضفت أي نصّ فسيُضاف في آخر الملف. إذا لم يكن الملف موجودا فسيتم إنشاء ملف جديد. مثال: open('file.txt', 'a') a+: إذا كان الملف موجودا فإنّه يُفتح لكل من الإلحاق والقراءة، إذا لم يكن موجودا فسيتم إنشاء ملف جديد. مثال: open('file.txt', 'a+') الكتابة على الملف بعد فتح الملف سواء أكان موجودا من قبل أو أنّك أنشأته بالدالة نفسها، ستستطيع الكتابة على الملف وإضافة نصوصك الخاصّة، وذلك بالدالة write مع مُعامل عبارة عن سلسلة نصية، انظر المثال التالي: >>> file = open('file.txt', 'w') # فتح الملف وإسناده إلى مُتغير >>> file.write('Hello World!') # الكتابة بالملف >>> file.close() # إغلاق الملف ملاحظة: إذا كنت تستعمل المُفسّر، فلحفظ التعديلات عليك الخروج من المفسّر أو إغلاق الملف والذي يُمكنك القيام به بالدالة close، مع ملاحظة أنّك لن تتمكن من تعديل الملف بعد إغلاقه، أي أنّك ستحتاج إلى فتحه من جديد بالدالة open. لن تُلاحظ أي مُخرجات عند تنفيذك لأي أمر أعلاه، ولكن رغم ذلك فإنّك إذا فتحت الملف file.txt بأي مُحرّر للنّصوص (Notepad مثلا)، فإنّك ستُلاحظ الجملة !Hello World في بداية الملف. لاحظ بأنّنا فتحنا الملف بنمط الكتابة فقط (w)، إذا فتحت الملف بنفس النّمط مُجدّدا فإنّ التغييرات التي ستكتبها ستُغطّي محتويات الملف. أي أنّك إذا نفّذت الأوامر التاليّة فإنّ مُحتويات الملف ستُصبح الجملة !Hello Python عوضا عن جملة !Hello World # -*- coding: utf-8 -*- >>> file = open('file.txt', 'w') # فتح الملف وإسناده إلى مُتغير >>> file.write('Hello Python!') # الكتابة بالملف >>> file.close() # إغلاق الملف يُمكنك إضافة أكثر من مُدخل في كلّ مرّة، المهم أن تكتب على الملف قبل إغلاقه: >>> file = open('file.txt', 'w') >>> file.write('Abdelhadi Dyouri!') >>> file.write('Hsoub Academy!') >>> file.close() بعد تنفيذ الشيفرة أعلاه، ستكون مُحتويات الملف كالتالي: Abdelhadi Dyouri!Hsoub Academy! لاحظ بأنّ لغة بايثون لا يعود إلى سطر جديد في كل مرة، ولكي تحلّ هذه المسألة فيُمكنك ببساطة إضافة الرّمز n\ بين كل سطر، انظر المثال التّالي: >>> file = open('file.txt', 'w') >>> file.write('Abdelhadi Dyouri!\nHsoub Academy!') >>> file.close() مُحتويات الملفّ بعد تقسيم الأسطر بالرّمز n\ هي كالتالي: Abdelhadi Dyouri! Hsoub Academy! لاحظ بأنّ الشيفرة أعلاه لها نفس تأثير ما يلي: >>> file = open('file.txt', 'w') >>> file.write('Abdelhadi Dyouri!\n') >>> file.write('Hsoub Academy!') >>> file.close() كلّ ما تعلمناه إلى الآن هو كيفية إعادة كتابة الملف، ولكن ماذا لو أردت أن تُبقي على محتويات الملف وترغب بإضافة نصوص له؟ يُمكنك ذلك عن طريق تغيير نمط الوصول إلى نمط الإلحاق عوضا عن نمط الكتابة، لنضف المزيد من النّصوص إلى الملف السابق، إلى الآن مُحتوياته هي كالتالي: Abdelhadi Dyouri! Hsoub Academy! لنضف أقسام الأكاديمية إلى آخر الملف، انظر المثال التالي: >>> file = open('file.txt', 'a') >>> file.write('\nFreelance\nEntrepreneurship\nDesign\nApps\nCertificates\nDevops\nMarketing') >>> file.close() لاحظ تغيير المُعامل الثاني في دالة open من w إلى a. بعد تنفيذ الشيفرة أعلاه ستكون مُحتويات الملفّ كالتالي: Abdelhadi Dyouri! Hsoub Academy! Freelance Entrepreneurship Design Apps Certificates Devops Marketing لنُطبّق ما تعلمناه في الدّروس السابقة ولنضع لكلّ قسم عنوان Url الخاص به: افتح ملفا باسم links.py وضع فيه ما يلي: links = [] list = '\nFreelance\nEntrepreneurship\nDesign\nApps\nCertificates\nDevops\nMarketing' list = list.lower().split('\n') for item in list: list = item.replace(item , 'https://academy.hsoub.com/{}'.format(item)) links.append(list) file = open('file.txt', 'w') file.write('Academy: {}'.format(links[0])) file.write('\nFreelance: {}'.format(links[1])) file.write('\nEntrepreneurship: {}'.format(links[2])) file.write('\nDesign: {}'.format(links[3])) file.write('\nApps: {}'.format(links[4])) file.write('\nCertificates: {}'.format(links[5])) file.write('\nDevops: {}'.format(links[6])) file.write('\nMarketing: {}'.format(links[7])) file.close() أولا عرّفنا قائمة روابط فارغة باسم links بعدها أسندنا الأقسام إلى مُتغيّر باسم list ثمّ حولنا الأحرف إلى أحرف صغيرة و قسّمنا السّلسلة النّصية، بعدها استعملنا الحلقة for للدوران على عناصر القائمة، وفي كلّ مرّة نستبدل قيمة القسم برابطه ونُلحق العنصر النّاتج إلى القائمة links وبعدها فتحنا الملف ووضعنا لكل قسم رابطه الخاص وأخيرا أغلقنا الملف. بعد تنفيذ الشيفرة أعلاه ستكون مُحتويات الملف file.txt كالتالي: Academy: https://academy.hsoub.com/ Freelance: https://academy.hsoub.com/freelance Entrepreneurship: https://academy.hsoub.com/entrepreneurship Design: https://academy.hsoub.com/design Apps: https://academy.hsoub.com/apps Certificates: https://academy.hsoub.com/certificates Devops: https://academy.hsoub.com/devops Marketing: https://academy.hsoub.com/marketing يُمكنك أن تجعل البرنامج أكثر ذكاء وذلك باستبدال قائمة الأقسام بمُدخل من المُستخدم وتُضيف رابط القسم إلى الملف، على سبيل المثال سيعمل البرنامج كالتالي: Enter the name of the category: مثلا لنُدخل programming للحصول على رابط قسم البرمجة، يجب أن تكون المُخرجات شيئا كالتالي: Enter the name of the category: programming Ok! Added https://academy.hsoub.com/programming to file.txt هل رأيت حلاوة البرمجة؟ تذكّر بأنّ خيالك هو حدود ما تستطيع القيام به. قراءة الملف الدالة read بعد الكتابة على الملف سيتوجّب علينا قراءته، كما الكتابة تُوفّر لنا لغة بايثون دالة خاصة بالقراءة وهي الدالة read التي يُمكننا أن نستعملها كالتالي: file = open('file.txt', 'r') file.read() لاحظ أنّنا غيّرنا المُعامل الثاني من w إلى r وذلك لأنّنا نرغب بفتح الملفّ للقراءة. بعد تنفيذ الشيفرة أعلاه ستكون المُخرجات كالتالي: 'Academy: https://academy.hsoub.com/\nFreelance: https://academy.hsoub.com/freelance\nEntrepreneurship: https://academy.hsoub.com/entrepreneurship\nDesign: https://academy.hsoub.com/design\nApps: https://academy.hsoub.com/apps\nCertificates: https://academy.hsoub.com/certificates\nDevops: https://academy.hsoub.com/devops\nMarketing: https://academy.hsoub.com/marketing\n' إذا عاودت تنفيذ الدالة read من جديد فإنّ المُخرج سيكون سلسلة نصيّة فارغة'' وهذا يدلّ على أنّنا وصلنا إلى نهاية الملفّ، ولكي تعود إلى بداية الملف من جديد فعليك فتحه مُجدّدا بالدالة open. كما تُلاحظ فإنّ المُخرجات لا تبدو جميلة أبدا، يُمكنك أن تقرأ أسطر الملف باستخدام جملة for عوضا عن الدالة read وستكون المُخرجات نظيفة هذه المرّة. file = open('file.txt', 'r') for line in file: print line ستكون المُخرجات كالتالي: Academy: https://academy.hsoub.com/ Freelance: https://academy.hsoub.com/freelance Entrepreneurship: https://academy.hsoub.com/entrepreneurship Design: https://academy.hsoub.com/design Apps: https://academy.hsoub.com/apps Certificates: https://academy.hsoub.com/certificates Devops: https://academy.hsoub.com/devops Marketing: https://academy.hsoub.com/marketing يُمكنك أيضا تحديد كم من بايت Byte ترغب بقراءته من بداية الملف. فمثلا إذا كنت ترغب بقراءة أول 8 بايت من مُحتويات الملف، فيُمكنك تمرير العدد 8 إلى الدالة read كمُعامل: >>> file = open('file.txt', 'r') >>> file.read(8) 'Academy:' >>> file.close() المُخرجات ستكون كالتالي (أول 8 أحرف من الملف): 'Academy:' لاحظ بأنّ البايت الواحد لا يعني دائما الحرف الواحد إذ أنّ هناك استثناءات عديدة، فمثلا في اللغة العربية الحرف الواحد يشغل حوالي 2 بايت أما الأحرف الصينية فتشغل حوالي 3 بايت. في الأحرف الإنجليزية عادة ما يُساوي الحرف الواحد 1 بايت فقط. الدالة readline يُمكنك أن تقرأ سطرا واحدا من الملف في كلّ مرّة، وذلك بالاعتماد على جُملة readline عوضا عن جملة read. >>> file = open('file.txt', 'r') >>> file.readline() 'Academy: https://academy.hsoub.com/\n' >>> file.readline() 'Freelance: https://academy.hsoub.com/freelance\n' >>> file.readline() 'Entrepreneurship: https://academy.hsoub.com/entrepreneurship\n' لاحظ بأنّ المُخرج يكون مُختلفا في كلّ مرّة تُستَدعَى فيها الدالة readline إذ أنّ المُخرج يكون سطرا واحدا في كل مرة، وفي المرّة التالية تكون النّتيجة السّطر التالي إلى نهاية الملفّ. في النّهاية سيكون المخرج سلسلة نصيّة فارغة: >>> file.readline() 'Marketing: https://academy.hsoub.com/marketing\n' >>> file.readline() '' إذا أردت العودة إلى بداية الملفّ من جديد فيُمكنك ذلك إما بإغلاق الملف وفتحه من جديد أو باستعمال الدالةّ seek مع تمرير عدد البايتات الذي ترغب بتخطّيه، (أي صفرا للعودة إلى بداية الملف). >>> file.readline() '' >>> file.seek(0) >>> file.readline() 'Academy: https://academy.hsoub.com/\n' يُمكن مثلا العودة إلى أول 8 بايت من الملف بالطّريقة التالية: >>> file.seek(8) >>> file.readline() ' https://academy.hsoub.com/\n' يُمكنك أن تعتمد على الدالة tell لتعرف مركز القراءة الحالي. >>> file.seek(66) >>> file.tell() 66 تقبل الدّالة readline مُعاملا لتحديد عدد البايتات المرغوب قراءتها (تماما مثل شقيقتها read). >>> file.seek(0) # للعودة إلى بداية الملف >>> file.readline(8) 'Academy:' الدالة readlines تُعتبر الدالة readlines طريقة أخرى لقراءة الملف، وتُرجع قائمة بجميع الأسطر التي يحتويها الملف: >>> file = open('file.txt', 'r') >>> file.readlines() ['Academy: https://academy.hsoub.com/\n', 'Freelance: https://academy.hsoub.com/freelance\n', 'Entrepreneurship: https://academy.hsoub.com/entrepreneurship\n', 'Design: https://academy.hsoub.com/design\n', 'Apps: https://academy.hsoub.com/apps\n', 'Certificates: https://academy.hsoub.com/certificates\n', 'Devops: https://academy.hsoub.com/devops\n', 'Marketing: https://academy.hsoub.com/marketing'] يُمكنك مثلا حساب عدد أسطر ملفّ ما بحساب عدد عناصر القائمة بالدالة len: >>> file = open('file.txt', 'r') >>> len(file.readlines()) 8 إغلاق الملف رغم أنّ عمليّة إغلاق الملف ليست ضرورية لحفظ التّغييرات، إلّا أنّ القيام بالأمر منصوح به بشدّة، لذلك يجب عليك أن تتأكّد من أنّ الملفّ قد أُغلق بعد انتهائك من إجراء العمليّات على الملف. لقد تعرّفنا من قبل على كيفيّة إغلاق الملف: >>> file = open('file.txt') >>> file.close() للتحقق من أنّ الملف مُغلق يُمكن أن تستعين بالجملة closed والتي تُرجع قيمة منطقية (إما True أو False). إذا كان الملف مُغلقا فسترجع الجملة True أما إذا لم يكن مغلقا فستُرجع الجملة False. >>> file = open('file.txt') # فتح الملف >>> file.closed # التحقق من أنّ الملف مُغلق False >>> file.close() # إغلاق الملف >>> file.closed # التحقق من جديد True يُمكن كذلك الاستعانة بالجملة with as لفتح ملف والقيام بعمليات ثم إغلاقه آليا. with open('file.txt', 'r') as file: file.read() الملف يُغلق ذاتيا بعد انتهاء الجزء المُزاحِ (ذو الإزاحة) من الشيفرة، ويُمكنك التأكّد من الأمر بالجملة closed. الدوال المساعدة بعد فتح الملف يُمكنك الحصول على معلومات حول الملف ببعض الدوال المبنية مُسبقا Built-in functions وهي كالتالي: closed: التحقق من ما إذا كان الملف مُغلقا أو لا (انظر الفصل السابق). name: الحصول على اسم الملفّ. >>> file = open('file.txt') >>> file.name 'file.txt' mode: الحصول على نمط الوصول. >>> file = open('file.txt', 'w+') >>> file.mode 'w+' تمارين تمرين 1 اكتب برنامجا للحصول على قيم من المُستخدم وأدخلها إلى ملف نصي. تمرين 2 صحّح الخطأ في ما يلي: file = open('file.txt', 'r') file.write('Hello World!') تمرين 3 صحّح الخطأ في ما يلي: file = open('file.txt', 'w') file.write('Hello World!') file.close() file.write('Hello!') تمرين 4 اكتب برنامج تسجيل الدخول في الدروس السابقة ليقبل ملفّا كقاعدة بيانات. (احفظ اسم المُستخدم وكلمة المرور في الملف عوضا عن الذاكرة.) المصادر المعتمدة التوثيق الرّسمي للغة بايثون، فصل الدوال المبنية مُسبقا، الدالة open كتاب Python Practice Book لكاتبه Anand Chitipothu التوثيق الرّسمي للغة بايثون، فصل السلاسل النّصيّة
  20. python 101

    بعد أن تعلّمنا في الدّرس السّابق كيفيّة التّعامل مع التّعابير الشّرطية، وكيفيّة استعمال الجمل الشّرطية في برامجنا وكيفّية القيّام بإزاحة مناسبة عند التّعامل مع أجزاء متعدّدة من الشّيفرة في لغة بايثون، سنكمل مشوار تعلّم هذه اللغة الجميلة. سنتعلّم في هذا الدّرس كيفيّة التّعامل مع حلقات التّكرار مثل حلقة for وحلقة while. مع التذكير بأنّ جميع الشّيفرات التّي تبدأ بعلامة <<< يجب أن تنفّذ على مفسر بايثون. تُمكّنك الحلقات من تكرار شيفرة عددا من المرّات، يُمكنك أن تحدّد عدد مرّات التّكرار حسب إرادتك. حلقة While حلقة While تقوم بتكرار شيفرة ما عندما يكون الشّرط محقّقا ولا تتوقّف إلا عندما يكون الشّرط خاطئا، ولإنشاء حلقة while يجب تحديد عدد المرّات التّي تتكرّر فيها ووضعها كشرط ثم زيادة قيمة مُتغيّر بواحد، بحيث يزداد إلى أن يصل إلى العدد المُحدّد في الشّرط فيتوقّف. بإمكانك أيضًا تحديد شرط من نوع آخر بحيث لا ترتبط الحلقة بتنفيذ الشيفرة بعدد مُعيّن من المرّات وإنما بتحقق شرط مُعيّن (أن تصبح قيمة مُتغيّر مُخالفة لقيمة نقوم بتحديدها) لنقل بأنّنا نريد طباعة "Hello" مائة مرّة، بالطّبع قد تقول أكرّر الجملة التالية مائة مرة: print "Hello" هذه الطّريقة صحيحة لكنّها تُكلّف الكثير من الوقت، والمُبرمج دائما ما يُفكّر بطريقة أذكى (افعل أكثر عدد ممكن من المهام في أقل وقت ممكن). لذلك لا يُمكننا اعتماد هذه الطّريقة. وتُقدم لنا لغات البرمجة خاصية التكرار ببساطة وبأقل عدد من الأسطر. كمثال يُمكننا طباعة "Hello" عشر مرّات بالطّريقة التّاليّة، لاحظ بأنّ الجمل التّابعة للكلمة while مُزاحةٌ بأربع مسافات بيضاء: >>> i = 0 >>> while i < 10: ... print "Hello" ... i = i +1 Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello شرح المثال أعلاه: السّطر الأول: نقوم بوضع قيمة بدئية للمتغيّر i. السّطر الثّاني: نقوم بإضافة الشّرط وهو أن تكون قيمة المتغير أصغر من العدد عشرة فإن كان يُساوي 10 يتوقّف البرنامج. السّطر الثّالث: نقوم بطباعة الكلمة السّطر الرّابع: نقوم بزيّادة قيمة المتغير في المرّة الأولى سيقرأ المفسّر قيمة المُتغيّر فيجدها تُساوي العدد 0، ثمّ يتحقّق من أنّ شرط أن تكون القيمة أصغر من 10 صحيح، وبما أنّ الشّرط مُحقّق في المرّة الأولى (بالطّبع لأنّ 0 أصغر من 10) سيُتابع البرنامج العمل، وسيطبع جملة التّرحيب "Hello" بعد ذلك يزيد المُفسّر قيمة المتغيّر i بواحد (لتكون القيمة الجديدة هي 1) يتحقّق المُفسّر من صحّة الشّرط مُجدّدا وبما أنّه مُحقّق فقد طُبعت الجملة "Hello" مرّة ثانيّة، بعدها يزيد من قيمة المُتغيّر بواحد مجدّدا لتكون القيمة الجديدة للمُتغيّر i هي العدد 2 والذي بدوره أصغر من 10 فتُطبع الجملة مرّة ثالثة. وهكذا دواليك إلى أن تصل قيمة المُتغيّر إلى العدد 10 فيُصبح الشّرط خاطئا (لأنّ العدد 10 ليس أصغر من 10 بل مُساو له)، وبالتّالي يتوقّف التّكرار. لتستوضح الأمر بشكل أفضل، يُمكنك أن تطبع قيمة المُتغيّر i عند كلّ تكرار، انظر المثال: >>> i = 0 >>> while i < 10: ... print "Hello", i ... i = i +1 ... Hello 0 Hello 1 Hello 2 Hello 3 Hello 4 Hello 5 Hello 6 Hello 7 Hello 8 Hello 9 أمثلة تطبيقية لاستعمال حلقة While مثال 1: الوصول إلى عناصر قائمة، مجموعة أو صف هناك عدّة أمثلة تطبيقيّة لاستعمال حلقة While، وعلى سبيل المثال يُمكن أن تُستخدم حلقة التّكرار هذه للدّوران على قائمة وطباعة عناصرها، انظر المثال التّالي: >>> I = 0 >>> children = ['Omar','Khaled','Hassan','Zaid','Youssef'] >>> while i < len(children): ... print children[i] ... i = i + 1 ... Omar Khaled Hassan Zaid Youssef في المثال أعلاه، قُمنا بإنشاء قائمة باسم children تحتوي على خمسة عناصر، ثمّ قُمنا بطباعة كلّ عنصر عند كلّ تكرار، وقد وضعنا وجوب أن تكون قيمة المُتغيّر i أصغر من عدد عناصر القائمة والتّي حدّدناها بمُساعدة الدّالة len، وذلك ليتوقّف البرنامج عند وصول قيمة المتغير إلى العدد 5. مُلاحظة: هذا مجرّد مثال لكيفيّة استخدام حلقة While. وعادة ما تُستخدم الحلقة for لمثل هذه التّطبيقات (الدّوران على القوائم، المجموعات والصفوف…) وذلك لأنّها أكثر مرونة، وفي النّهاية يعود الاختيار لك (ويُمكنك استخدام الطّريقة التّي تُناسبك). مثال 2: عمل البرنامج إلى أن يجيب المستخدم بجواب معين لنقل بأنّك سألت المُستخدم سؤالا رياضيا (مثلا: "ما جمع 4 زائد 3" )، وتريد تهنأته عند إدخال الجواب الصحيح، الأمر بسيط، ولا يتعدى بضعة أسطر، افتح ملفّا وسمّه Answer.py، وضع فيه الأسطر التّالية: number = raw_input('Enter the Result of 3+4: ') if int(number) == 7: print 'Congratulation' نستخدم الدّالة int هنا لتحويل القيمة المُدخلة من طرف المُستخدم إلى قيمة من نوع integer أي عدد صحيح، وهذا مُفيد لأنّ القيمة التّي تُستقبل في الدّالة raw_input تكون عبارة عن سلسلة نصيّة. بعد أن قُمنا بجزء من المطلوب لنفترض بأنّ المُستخدم قد أدخل إجابة خاطئة، الأمر الذي قد يخطر في بالك الآن هو طباعة جملة تُفيد المُستخدم بأنّ إجابته خاطئة والخروج من البرنامج، الأمر جيّد ، ولكن ماذا لو أردنا أن نوفّر للمُستخدم حقّ المُحاولة من جديد، بحيث يطبع البرنامج جملة تفيد بأنّ الإجابة المُدخلة خاطئة ثمّ يطلب من المُستخدم أن يُحاول مجدّدا مع توفير إمكانيّة إدخال قيمة جديدة، يُمكن أن نقوم بذلك بالاستعانة بجملة else انظر المثال التّالي: number = raw_input('Enter the Result of 3+4: ') if int(number) == 7: print 'Congratulation!' else: print 'Sorry, Your Answer is not correct, please try again:' number = raw_input('Enter the Result of 3+4: ') if int(number) == 7: print 'Congratulation!' هذه الشّيفرة جيّدة لكنّها غير عمليّة بتاتا، إذ تستخدم الكثير من التّكرار الذي لا فائدة منه، كما أنّها لا توفّر للمُستخدم سوى محاولة واحدة أخرى. فماذا لو أردنا أن نوفّر للمُستخدم عددا أكبر من المُحاولات؟ قد تقول ننسخ الشّيفرة أعلاه ونكرّرها عددا من المرّات في برنامجنا، هذا الحلّ سيء جدّا وذلك لأنّه لا يلبّي رغبتنا في توفير عدد لا نهائي من المحاولات للمُستخدم (بحيث لا يتوقّف البرنامج إلا عندما يجد المُستخدم الإجابة الصّحيحة)، كما أنّ نسخ الشّيفرة وتكرارها عدّة مرّات سيجعل من البرنامج طويلا وصعب القراءة. لحلّ هذه المُسألة، يُمكننا ببساطة أن نكرّر الشّيفرة التّي تتحقّق من الإجابة كلّ مرّة تُخالف فيه الإجابة التّي أدخلها المُستخدم، يعني يُمكننا أن نُخبر البرنامج بالتّحقّق من الإجابة إذا كانت صحيحة فكل شيء جيّد ونطبع رسالة تهنئة، إذا كانت الإجابة خاطئة، فسنعيد الشّيفرة مُجدّدا، ونعيد السّؤال إلى أن يصل المُستخدم إلى الإجابة الصحيحة، والتّالي مثال على الشيفرة التي تؤدي الغرض: number = raw_input('Enter the Result of 3+4: ') while int(number) != 7: number = raw_input('Wrong answer please try again, enter the Result of 3+4: ') print 'Congratulation' السّطر الأول: يقوم البرنامج بطلب الإجابة من المُستخدم. السّطر الثاني: تتحقّق حلقة While من كون الإجابة خاطئة، إذا تحقّق الشّرط، ينتقل البرنامج إلى السّطر الثالث، إذا لم يتحقّق (أي قيمة المتغير تساوي 7)، ينتقل البرنامج إلى السّطر الرابع. السّطر الثالث: يقوم البرنامج بإخبار المُستخدم بأنّ الإجابة خاطئة ويطلب منه إعادة المُحاولة. السّطر الرابع: يطبع البرنامج جملة التهنئة. حلقة التكرار For حلقة For جملة برمجية أخرى تُمكّن من التكرار، وهي من الأساليب المُستعملة للدوران حول قيم القوائم كذلك، وتتميّز بتعريف مُتغيّر العدّ في بداية الحلقة، أي أنّك على خلاف حلقة While لا تحتاج إلى تعريف المُتغيّر قبل البدء بكتابة الحلقة، كما أنّ حلقة for لا تحتاج إلى شرط معيّن بل تُحدّد عدد مرّات التّكرار حسب عدد عناصر القائمة المُسندة. انظر المثال التّالي، لاحظ بأنّ الجمل التّابعة للسّطر (for counter in range(1, 11 مُزاحةٌ بأربع مسافات بيضاء (انظر درس الإزاحات والمساحات البيضاء). >>> for counter in range(1, 11): ... print counter, 'Hello World!' ... 1 Hello World! 2 Hello World! 3 Hello World! 4 Hello World! 5 Hello World! 6 Hello World! 7 Hello World! 8 Hello World! 9 Hello World! 10 Hello World! في المثال أعلاه أنشأنا حلقة تكرار تدور على قائمة أنشأناها باستخدام الدّالة range، وأسندنا قيم التّكرار إلى المتغيّر counter الاختلاف هنا عن حلقة while هو أنّ المُتغيّر counter يعتبر جزءا من قائمة وليس مُتغيّرا يحمل قيمة في كلّ تكرار. مُلاحظة: لدّالة range تقوم بإنشاء قائمة أعداد مرتّبة من الأصغر إلى الأكبر حسب عاملين الأول رقم البداية والثّاني يُمثّل النّهاية مع ملاحظة بأنّ الرّقم النّهائي في السّلسلة لا يحتسب (في المثال التّالي 1 هو العدد الأول والعدد النّهائي هو العدد 11 ). >>> range(1,11) [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] يُمكن إنشاء قائمة معكوسة بتمرير معامل ثالث بقيمة 1- وقلب المعاملات: >>> range(10, 0, -1) [10, 9, 8, 7, 6, 5, 4, 3, 2, 1] تُمكّنُ حلقة for من الدّوران على عناصر مجموعة ما (القوائم الصفوف، السّلاسل النّصيّة…) عن طريق تمرير اسم المُتغيّر بعد كلمة in في الشيفرة، لاحظ بأنّ الجمل التّابعة للسّطر for lettre in v مُزاحةٌ بأربع مسافات بيضاء (انظر الدّرس السّابق). >>> v = "Hello" >>> for lettre in v: ... print lettre ... H e l l o في المثال أعلاه، قمنا بتعيين القيمة "Hello" للمتغير v وبعدها استخدمنا حلقة for لكي نطبع كل حرف من هذه الكلمة والذي عيّناه للمتغير lettre. كما رأينا من قبل يُمكن كذلك استخدام for لتكرار شيفرة ما عددا من المرّات، كما فعلنا مع حلقة while بمُساعدة الدّالة range: for i in range(0,100): print i يُمكن كذلك أن نستعمل حلقة for لنقوم بالمرور على مفاتيح قاموس ما لنحصل على كل مفتاح على حدة، انظر المثال التالي: >>> a = {'x': 1, 'y': 2, 'z': 3} >>> for key in a: ... print key ... x y z وكما قلنا سابقا في الدّرس الرابع، يُمكنك الحصول على كل من مفاتيح وقيم وعناصر قاموس على شكل قائمة: >>> a = {'x': 1, 'y': 2, 'z': 3} >>> a.keys() ['x', 'y', 'z'] >>> a.values() [1, 2, 3] >>> a.items() [('x', 1), ('y', 2), ('z', 3)] ومما سبق نستنتج بأنّنا نستطيع الحصول على كل واحدة من قيم القاموس: >>> a = {'x': 1, 'y': 2, 'z': 3} >>> for value in a.values(): ... print value ... 1 2 3 وبالتّالي يُمكنك أن تستنتج بأنّنا نستطيع المرور على كل من مفاتيح القواميس وقيمها معا في نفس الوقت: >>> a = {'x': 1, 'y': 2, 'z': 3} >>> for key, value in a.items(): ... print key, value ... x 1 y 2 z 3 أمثلة تطبيقية لاستعمال حلقة For مثال 1: طباعة مفاتيح وقيم قاموس معين يُمكننا أن نستعمل حلقة for لطباعة كل مفتاح وقيمته في قاموس ما. لنقل مثلا بأنّنا نمتلك قاموسا يحتوي على أسماء الألوان وشيفرة كلّ لون بنظام hex (نظام يستخدمه مطورو الويب لإسناد لون مُعيّن لعنصر ما، فعوضا عن كتابة اسم اللون تُستخدم شيفرته)، ونُريد أن نطبع كل لون متبوعا بشيفرته، القاموس الذي نمتلكه هو كالتّالي: colors = { "red":"#f00", "green":"#0f0", "blue":"#00f", "cyan":"#0ff", "magenta":"#f0f", "yellow":"#ff0", "black":"#000" } ونريد أن نعرض هذه المفاتيح مع قيمها بشكل لطيف، هل يُمكنك أن تُفكّر في طريقة لإنجاز مرادنا؟ الحل يكون باستخدام حلقة for للمرور على كل مفتاح وقيمته ومن ثمَّ طباعتها، يُمكننا القيام بذلك بسطرين فقط من شيفرة بايثون، وذلك كالتّالي (ضعها في ملف بامتداد py ونفّذ الملف). colors = { "red":"#f00", "green":"#0f0", "blue":"#00f", "cyan":"#0ff", "magenta":"#f0f", "yellow":"#ff0", "black":"#000" } for color_name, hex_value in colors.items(): print color_name + ': ' + hex_value مُخرجات البرنامج ستكون كالتّالي: blue: #00f yellow: #ff0 green: #0f0 cyan: #0ff magenta: #f0f red: #f00 black: #000 هذا مُجرّد مثال بسيط على استخدام كل من حلقة for والقواميس على أرض الواقع، ولا يجب عليك أن تضع حدّا لإبداعك، إذ يُمكنك استخدام ما تعلّمته بطرق مُختلفة وبرمجة برمجيات تقوم بوظائف لا محدودة، لذا لا تربط علمك بهذه الأمثلة، بل فكّر في طريقة للاستفادة مما تعلّمته لإنتاج برامج أكثر تعقيدا وذات وظائف مُتعدّدة، وسيُسعدني إن شاركت برامجك معنا. إيقاف حلقة بجملة :break يُمكن أن توقف حلقة تكراريّة من نوع while عند نقطة معيّنة بالجملة break ويُمكن تحديد نقطة التوقف باستخدام جملة if الشّرطيّة، انظر المثال: >>> i = 0 >>> while i < 30: ... if i > 15: ... print "Stop the loop" ... break ... print i ... i = i + 1 ... 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 Stop the loop في المثال أعلاه، كان من المُفترض أن تُكمل الحلقة التنفيذ إلى أن يصل المُتغيّر iإلى القيمة 30، ولكنّه توقّف بمُجرّد أن وصلت قيمة المُتغيّر إلى 15 وهذا لأنّنا وضعنا شرطا لإيقاف التكرار عندما تُصبح قيمة i أكبر من 15 وبما أنّ الشّرط أصبح صحيحا فقد توقّف البرنامج لأنّنا أمرناه بالجملة break. ويُمكن كذلك أن توقف حلقة تكراريّة من نوع for عند نقطة معيّنة بالجملة break ويُمكن تحديد نقطة التوقف باستخدام جملة if الشّرطيّة: >>> list = [1,5,10,15,20,25] >>> for i in list: ... if i > 15: ... print "Stop the loop" ... break ... print i ... 1 5 10 15 Stop the loop في المثال أعلاه، توقّف الدوران على القائمة list بعد أن وصل المتغيّر إلى القيمة 15، وهذا هو الشرط الذي وضعناه في جملة if. تجاهل تنفيذ الشيفرة في حلقة بجملة :continue يُمكن أن توقف حلقة تكراريّة من نوع for عند نقطة معيّنة ثمّ تُكمل التكرار في الخطوة التّاليّة، أي قفز خطوة عند التّكرار، وذلك بالاستعانة بالجملة continue ويُمكن تحديد نقطة التوقف باستخدام جملة if الشّرطيّة، يعني أنّك تستطيع إخبار البرنامج بالانتقال إلى التنفيذ التّالي إذا ما تحقّق هذا الشّرط، انظر المثال: >>> list = range(1, 31) >>> for i in list: ... if i == 15: ... print "Continue the loop" ... continue ... print i ... 1 2 3 4 5 6 7 8 9 10 11 12 13 14 Continue the loop 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 في المثال أعلاه، كان من المُفترض أن تُكمل الحلقة التنفيذ إلى أن يصل المُتغيّر iإلى القيمة 30، ولكنّه توقّف بمُجرّد أن وصلت قيمة المُتغيّر إلى 15 وتابعت عندما وصلت القيمة إلى العدد 16 وهذا لأنّنا وضعنا شرطا لإيقاف التكرار عندما تُساوي قيمة i العدد 15 وبما أنّ الشّرط قد تحقّق فقد توقّف البرنامج عند تلك النّقطة وطبع جملة Continue the loop لأنّنا أمرناه بالجملة continue. تمارين صديقي القارئ، يجب أن تعرف بأنّ التّعلم لا يكتمل إلا بتطبيق المُكتسبات، لذلك فالتّفكير في حلول هذه التّمارين أمر فعال جدا ومُفيد لك، لذلك لا تكن كسولا، ولا تكتف بالقراءة فقط، بل عليك تطبيق ما تعلّمته وإنشاء برامجك الخاصّة، خاصّة وأنّك إلى الآن قد تعرّفت على جزء كبير من تقنيات البرمجة التي تسمح لك بإنشاء برامج مُبهرة، تُؤدي أغراضا عديدة. يُمكنك أن تنشر حلول التّمارين في صندوق التعليقات إذا كنت ترغب في ذلك، ومن المفضل أن تُحاول حل التّمارين بنفسك قبل أن تنظر إلى أجوبة زملائك. تمرين 1 اكتب برنامجين يقومان بطباعة جملة: Hello World! 1000 مرة. البرنامج الأول باستخدام حلقة While والثاني بحلقة For. تمرين 2 اكتب برنامجا يقوم بأخذ قيمة من المُستخدم ثمّ يطبعها 10 مرات. تمرين 3 ما مُخرجات البرنامج التّالي: number = 3 list = range(1, 31) for i in list: if i == number: continue if 15 < i < 21: continue print i تمرين 4 اكتب برنامجا يقوم بطباعة عناصر القائمة التّالية مع جملة ترحيب. list = ['Ahmed', 'Abdelhadi', 'Dyouri', 'Hossam', 'Mohammed', 'Khaled', 'Ibrahim', 'Othman'] يجب أن تكون مُخرجات البرنامج كالتّالي: Hello, Ahmed Hello, Abdelhadi Hello, Dyouri Hello, Hossam Hello, Mohammed Hello, Khaled Hello, Ibrahim Hello, Othman تمرين 5 عد إلى الدّرس السّابق وعدّل برنامج تسجيل الدخول لكي يقبل مُحاولة المُستخدم من جديد إذا كانت كلمة السّر خاطئة. ولا تنس أن تنشر برنامجك في قسم التّعليقات على هذا المقال إذا أردت ذلك. ترجمة -وبتصرف- من الكتاب Python Practice Book لصاحبه Anand Chitipothu.
  21. بايثون (Python) لغة ممتازة لبرمجة الويب نظرا لمرونتها وأدائها العالي. أطُرُ الويب يمكن أن تجعل برمجة تطبيقات الويب أبسط بكثير لأنها توصل العديد من المكونات الضرورية مع بعضها للحصول على تطبيق قوي. في حين تهدف بعض أطر الويب إلى توفير كل شيء يمكن أن يرغب به المستخدم لتطوير تطبيق ما، هناك أطر أخرى تحاول البقاء بعيدا والاهتمام بالأهم، Bottle إطار للغة بايثون يندرج ضمن النوع الثاني. إنه بالفعل خفيف ومصغر، لكنه يجعل تطوير التطبيقات سهلا وسريعا. في هذا المقال، سنعرض طريقة ضبط واستعمال إطار العمل المصغّر Bottle لإنشاء تطبيقات ويب بسيطة وباستعمال لغة Python. كيفية تثبيت Bottleتثبيت Pythonإطار Bottle مبني على لغة Python وهي مثبتة مسبقا على أنظمة لينكس وOS X، أما بالنسبة لنظام Windows فيمكن تنصيب Python 2 عبر تحميلها من موقعها الرسمي. الجدير بالذّكر أن هذا الدّرس خاصّ بالإصدار الثاني من بايثون (Python 2.x). تثبيت وتفعيل بيئة وهميةسنثبت حزمة virtualenv لعزل مشروع بايثون الخاص بنا من بيئة بايثون الخاصة بالنظام. يمكننا فعل هذا بسهولة عبر تنصيب أداة إدارة الحزم الخاصة ببايثون واسمها pip. لتنصيب pip على Ubuntu يكفي تنصيب virtualenv مباشرة، فهي إحدى اعتمادياته: sudo apt-get update sudo apt-get install python-virtualenv بالنسبة لأنظمة OS X و Windows يمكن تنصيبه بتنصيب pip ثم تنصيب virtualenv عبرها: أو احفظ هذا الملف على جهازك، ثم نفذ الأمر التالي على نافذة الأوامر بالنسبة لـ Windows أو Terminal بالنسبة لـِ Mac OS X، في كلا النظامين، ستحتاج أن تنفذ الأمر التالي بصلاحيات المدير: python get-pip.pyبرنامج virtualenv عبارة عن بيئة وهمية لبايثون لتنصيب مكتبات بايثون في معزل عن بيئة بايثون الحقيقية على النظام، هذا مهم جدا لعزم اعتماديات مشروع الويب الخاص بك وما يحتاجه من حزم عن الحزم العامة المنصبة على كافة النظام، تحتوي بيئة مشاريع بايثون الخاصة بنا على حزمنا فقط، لكي لا تؤثر على نظام التشغيل ككل. سننشئ مجلد المشاريع projects في مجلد Home أو ماشابه، ثم نقوم بإنشاء بيئة وهمية في هذا المجلد، بالنسبة لـ Windows يمكن تنفيذ هذه الأوامر باستخدام طرفية PowerShell: mkdir ~/projects cd ~/projects virtualenv --no-site-packages venv هذا سينشئ مجلدا باسم venv داخل مجلد المشاريع. لقد تُبِّتت بعض أدوات بايثون داخل هذا المجلد وأنشِئَت بنية مجلد لتثبيت أدوات إضافية. يجب علينا تفعيل البيئة الوهمية قبل بداية العمل على مشروعنا : source venv/bin/activateالأمر المُخرَج سيتغير لعكس حقيقة أننا نقوم بعمليات داخل بيئة وهمية الآن. وسيكون كالتالي: (venv)user@Hostname:~/projects$إذا أردت الخروج من البيئة الوهمية، يمكنك في أي وقت كتابة الأمر التالي : deactivateملاحظة: لا تخرج من البيئة الوهمية حاليا. تثبيت Bottleأداة pip تُمكنك من تثبيت حزم بايثون بسهولة من دليل حزم بايثون Python package index، وهو مستودع مُفهرس لمكتبات بايثون. إذا أردنا البحث عن حزم بايثون المتعلقة بـِ Bottle، يمكن تنفيذ: pip search bottleسنبدأ بتثبيت حزمة Bottle فقط: pip install bottleبعد إنتهاء العملية، سنتمكن من استخدام إطار Bottle داخل تطبيقاتنا. إنشاء أول تطبيق باستخدام Bottleكمعظم الأطر، Bottle يطبق نسخة من النمط البرمجي MVC .MVC اختصار لـِ Model, view, controller نموذج،عرض،هيكل؛ وهو أمر للفصل بين عوامل مختلفة بين واجهة المستخدم والمنطق البرمجي. النموذج model تمثيل لمجموعة من البيانات وهو مسؤول عن تخزين، استعلام، وتحديث البيانات.العرض view مسؤول عن كيفية تقديم المعلومة للمستخدم. ويُستخدم لتشكيل وضبط عرض البيانات.الهيكل controller هو مركز العمليات الرئيسي للتطبيق، والذي يقرر كيفية الإجابة لطلبات المستخدم.تطبيقات bottle يمكنها أن تكون بسيطة للغاية. في شكلها البسيط يمكنها تنفيذ جميع المكونات في ملف واحد. سنقوم بإنشاء تطبيق "مرحبا بالعالم" لعرض كيفية العمل. باستعمال محررك المفضل (في هذه الحالة سنستعمل محرر سطر الأوامر nano، بالنسبة لنظام Windows يمكنك استعمال محرر مرئي)، أنشئ تطبيق بايثون باسم hello.py: nano hello.pyفي هذا الملف، سنقوم أولا باستدعاء بعض الوظائف من حزمة Bottle. الأمر الذي سيمكننا من استخدام أدوات الإطار داخل تطبيقنا: from bottle import route, runهذا السطر يخبر برنامجنا بأننا نحتاج إلى استيراد المسار route وتشغيل النماذج modules من حزمة Bottle. نموذج run الذي قمنا باستيراده يمكن أن يُستعمل لتشغيل التطبيق في خادوم التطوير، الشيء الذي يعتبر جيداً لرؤية نتائج برنامجك بسرعة. نموذج route مسؤول عن إخبار التطبيق بالتعامل مع أي من طلباتURL باستخدام أي من دوال بايثون.تطبيقات Bottle تنفّذ التوجيه routing باستدعاء دالّة بايثون واحدة لكلّ طلب من طلبات URL. وتقوم بعد ذلك بإرجاع نتائج الدالة للمُستخدم. نستطيع إضافة توجيه سيُوافق رابط URL /hello from bottle import route, run @route('/hello')هذا التوجيه سيوافق رابط URL /hello عندما يتمّ طلب هذا المسار على الخادوم. ستُنفّذ الدّالة التّابعة مباشرة: # -*- coding: utf-8 -*- from bottle import route, run @route('/hello') def hello(): return u"<h1>مرحباً بالعالم</h1>"ملاحظات: السطر # -*- coding: utf-8 -*- مسؤولٌ عن دعم اليونيكود وبالتالي اللغة العربية، فهو يخبر مفسر بايثون أن هذا الملف به أحرف unicode غير الأحرف الانجليزية.حرف u (اختصارًا لـ unicode) قبل النص العربي مهم أيضا لإخبار بايثون أن هذه السلسلة النصية بالضبط تحتوي على أحرف يونيكود وبالتالي يعامل السلسلة النصية بطريقة خاصة.هذه الدّالة بسيطة جدّاً، لكنّها كافية لإكمال المتطلّب الوحيد لدالّة توجيه: تقوم بإرجاع قيمة يُمكن عرضها على المتصفّح. في هذه الحالة، القيمة عبارة عن نص HTML. يمكننا حذف وسم h1 وستُعرض نفس القيمة بشكل غير منسّق. أخيراً، نحتاج إلى تشغيل تطبيقنا باستعمال خادوم التّطوير development server: # -*- coding: utf-8 -*- from bottle import route, run @route('/hello') def hello(): return u"<h1>مرحباً بالعالم</h1>" run(host='0.0.0.0', port=8080)هذا السطر سيُشغل الخادوم. بتمرير المعامل 'host='0.0.0.0 الأمر سيقوم بإرجاع المحتوى لأي حاسوب، وليس فقط الحاسوب المحليّ. هذا مهم بما أن تطبيقنا مستضاف عن بعد. معامل port يقوم بتحديد المنفذ الذي سنستخدمه. يُمكننا تشغيل التطبيق بتنفيذ الأمر: python hello.pyيمكنك زيارة التطبيق بمتصفح الويب عن طريق الذهاب إلى عنوان IP الخاصّ بك (إن كنت تعمل على خادوم) أو localhost إن كنت تعمل محليا، متبوعاً برقم المنفذ الذي قمنا باختياره (8080)، متبوعا بالتوجيه الذي أنشأناه (hello/): http://localhost:8080/helloسيظهر لك التالي: يُمكن إيقاف الخادوم في أي وقت بالضغط على CTRL-C في نافذة الطرفيّة أو سطر الأوامر. تطبيق مبدأ MVCلقد نفّذنا الآن تطبيقنا الأول. لقد كان بسيطاً بالتأكيد، ولكنّه لا ينفّذ مبادئ MVC، أو لا يقوم بشيء مثير للاهتمام. لنحاول جعله تطبيقاً أكثر تعقيداً هذه المرّة. إنشاء النموذجلنبدأ بنموذجنا، هذا هو الجزء الخاص بالتّعامل مع تخزين البيانات في برنامجنا. يمكن لـ Bottle بسهولة استخدام مجموعة من الواجهات الخلفية backends للبيانات باستعمال الإضافات. سنستخدم ملف SQLite لقاعدة بيانات التطبيق. هذه قاعدة بيانات بسيطة للغاية مُصمّمة للعمليّات الخفيفة التي يُمكن أن يقوم بها برنامجنا. ثبّت أولا SQLite، على Ubuntu يمكن ذلك عبر الأمر التالي: sudo apt-get install sqliteبالنسبة لـ Windows و OS X يمكن تثبيتها من على موقعها الرسمي. نحتاج كذلك إلى تحميل وتثبيت إضافة Bottle التي تُخوّلنا لاستعمال قواعد البيانات هذه: pip install bottle-sqliteالآن نحن نمتلك المكوّنات الأساسية، نستطيع أن ننشئ قاعدة بيانات بسيطة لتخزين بياناتنا فيها. سنقوم بإنشاء ملفّ بايثون لتوليد قاعدة بيانات SQLite مع بعض البيانات بداخلها عندما ننفّذ الملفّ. يُمكننا فعل الأمر على مترجم بايثون، لكنّ هذه الطريقة تجعل الأمر أسهل للتكرار. سننشئ ملفا باسم picnic_data.py. nano picnic_data.pyهنا نقوم باستيراد حزمة SQLite. بعد ذلك، يمكننا تنفيذ أمر يُنشئ جدولا ويدخل بيانات فيه. وفي الأخير، ننّفذ التغييرات: # -*- coding: utf-8 -*- import sqlite3 db = sqlite3.connect('picnic.db') db.execute("CREATE TABLE picnic (id INTEGER PRIMARY KEY, item CHAR(100) NOT NULL, quant INTEGER NOT NULL)") db.execute("INSERT INTO picnic (item,quant) VALUES ('خبز' , 4')") db.execute("INSERT INTO picnic (item,quant) VALUES ('جبن', 2)") db.execute("INSERT INTO picnic (item,quant) VALUES ('عنب', 30)") db.execute("INSERT INTO picnic (item,quant) VALUES ('كعك', 1)") db.execute("INSERT INTO picnic (item,quant) VALUES ('مشروبات', 4)") db.commit()احفظ الملفّ وأغلقه يُمكننا تنفيذ الملفّ، الشيء الذي سينشئ ملفّ قاعدة بيانات باسم نزهة.db داخل المُجلّد: python picnic_data.py نموذج تطبيقنا الآن مكتمل. يمكننا الآن استنتاج أن النموذج يملي على التطبيق كيفية تعامل جزء التحكم مع البيانات. إنشاء هيكل التّطبيقبعد أن أنشأنا قاعدة بيانات التّطبيق، يمكننا البدء في تطوير تطبيقنا الرئيسي. هذه العمليّة ستكون وظيفة الهيكل بشكل أساسي. وسيكون الملفّ الأكثر شبها بتطبيقنا الأول. أنشئ ملفّا باسم picnic.py لحفظ تطبيقنا الرئيسي: nano picnic.pyداخل هذا الملفّ، نحتاج إلى استيراد بعض الأشياء من حزمة Bottle، تماما كما سبق. نحتاج إلى بعض النّماذج الإضافية التي لم يسبق لنا أن استخدمناها. إضافة إلى ذلك، نحتاج إلى استيراد وظيفة SQLite: # -*- coding: utf-8 -*- import sqlite3 from bottle import route, run, templateتالياً، سنقوم بتعريف توجيه يوافق مسار URL على الشكل التالي picnic/: # -*- coding: utf-8 -*- import sqlite3 from bottle import route, run, template @route('/picnic')سنضيف دالّة للاتصال بقاعدة البيانات، لتحضر البيانات من الجدول، والاتصال مع العرض View لتقديم الصفحة. وفي الأخير، ستُرجع المخرج إلى المُستخدم. # -*- coding: utf-8 -*- import sqlite3 from bottle import route, run, template @route('/picnic') def show_picnic(): db = sqlite3.connect('picnic.db') c = db.cursor() c.execute("SELECT item,quant FROM picnic") data = c.fetchall() c.close() output = template('bring_to_picnic', rows=data) return outputبعد ذلك سنضيف أمر run لكي نقوم بتشغيل التطبيق: # -*- coding: utf-8 -*- import sqlite3 from bottle import route, run, template @route('/picnic') def show_picnic(): db = sqlite3.connect('picnic.db') c = db.cursor() c.execute("SELECT item,quant FROM picnic") data = c.fetchall() c.close() output = template('bring_to_picnic', rows=data) return output run(host='0.0.0.0', port=8080)احفظ وأغلق الملفّ. نقوم بالاتصال مع قاعدة البيانات باستعمال: db = sqlite3.connect('picnic.db')نقوم باستعلام قاعدة البيانات وجلب جميع القيم بالأسطر الأربعة الموالية. السطر الذي نقوم فيه بالإتصال إلى "العرض" لتشكيل البيانات هو: output = template('bring_to_picnic', rows=data)السطر يقوم بالاتصال بقالب (عرض) باسم bringtopicnic.tpl لتشكيل البيانات وتقديمها. حيث يقوم بتمرير المتغير data لمتغير القالب rows. سنقوم بإنشاء ملفّ القالب هذا في المرحلة التالية. إنشاء العرضالآن نحن نمتلك كلّا من النموذج والهيكل، الشيء الوحيد المتبقّي هو إنشاء العرض. يُمكن القيام بهذا بسهولة بالاستعانة بمحرك القوالب المُدمج مع Bottle. سيبحث التطبيق عن قالب موافق للاسم الذي عرّفناه في الدّالة السابقة، الملفّ يجب أن ينتهي ب .tpl يُمكن للملفّ أن يكون إمّا في مجلّد المشروع، أو داخل مجلّد باسم "view”. أنشئ ملفّا باسم يوافق الاسم الذي عرّفناه في دالّة القالب: nano bring_to_picnic.tplفي هذا الملفّ، يُمكننا دمج HTML والبرمجة معاً. سيكون ملفّنا بسيطا جدّاً. سنقوم باستعمال حلقة تكرار لإنشاء جدول يقوم بعرض بيانات النّموذج: <html dir="rtl" style="font:droid arabic naskh"> <body> <h1>أشياء لإحضارها إلى النّزهة</h1> <table> <tr><th>المكوّن</th><th>الكميّة</th></tr> %for row in rows: <tr> %for col in row: <td>{{col}}</td> %end </tr> %end </table> </body> </html>هذه الأسطر ستقوم بتقديم صفحتنا بصيغة HTML. لغة القالب التي رأينها هي ببساطة لغة بايثون. متغيّر row الذي قمنا بتمريره إلى القالب مُتاح للاستخدام عند تصميم المُخرجات. يُمكننا كتابة أسطر بايثون بتقديم علامة "%". يُمكننا الوصول إلى المُتغيّرات بداخل HTML باستخدام "{{var}}". احفظ الملفّ وأغلقه. مشاهدة النتائجتطبيقنا مكتملٌ الآن ويمكننا تشغيل الملفّ الرئيسي: python picnic.pyيمكننا رؤية النتائج بزيارة عنوان IP متبوعا برقم المنفذ، متبوعاً بالتوجيه picnic/ http://localhost:8080/picnic ختاماًإلى هذه النقطة، يجب أن تكون قادراً على رؤية كيف يُمكنك بناء تطبيقات معقّدة باستخدام الإطار المُصغر والبسيط Bottle. رغم أنّ أمثلتنا بسيطة، إلا أنّك الآن تستطيع بسهولة أن تطوّر تطبيقات إلى القيام بوظائف متقدّمة. نظام إضافات Bottle يعدّ أيضاً أصلاً مهمّاً. الإضافات مُشارَكةُ بنشاط في المجتمع وإضافة وظائف أكثر تعقيداً لتطبيقك يُمكن أن يُنفّذ بسهولة باستخدام الإضافات. هناك طريقة سهلة للبحث عن الإضافات وهي عن طريق استعمال الأمر: pip search bottleهذا سيُعطيك فكرة عن بعض الإضافات الأكثر شعبية. ترجمة -وبتصرّف- للمقال: How To Use the Bottle Micro Framework to Develop Python Web Apps.
  22. إنّ كل مكتبات بايثون (مثل حزم التّطبيقات application packages) التي نقوم بتنزيلها باستخدام مدير الحزم package manager (مثل pip) يتمّ توزيعها باستخدام أداة مساعدة مُخصصة لهذا العمل، تقوم هذه الأدوات المساعدة بإنشاء توزيعات بايثون Python distributions والتي هي أساسا عبارة عن ملفات أرشيف مرقمة بإصدار ومضغوطة، تحتوي هذه الملفّات على جميع العناصر المتعلقة بما يتم توزيعه، مثل ملفات المصادر source files وملفات الموارد resource files. سنقوم في هذا الدرس بالتحدث عن الأدوات الضرورية للتوزيع، وسنتطرق إلى الخطوات الأساسية التي تسمح لنا بحزم المكتبات المفيدة الخاصة بنا، الوحدات modules، أو حتى التطبيقات applications والتي ستكون مفيدة لنا عند توزيع المشروع الخاص بنا على خادوم أو مشاركته على الإنترنت. توزيعات وحزم بايثونحتى ولو كنا قد عملنا قليلًا فقط مع بايثون، فنحن متآلفون مع مفهوم استخدام مدير الحزم (مثل pip ،easy_install) لتنزيل الوحدات والمكتبات (مثل هياكل تطوير التطبيقات application development frameworks) والتي يتم بعدها استيرادها واستخدامها لإنشاء واحدة جديدة. تقوم أدوات إدارة الحِزَم هذه -والتي تعمل محليا- بالاتصال إلى مصدر بعيد source (مثل دليل حزم بايثون Python Package Index – PyPI) وتنفيذ الإجراء المطلوب (كالبحث والتنصيب). تتكوّن طريقة توزيع تطبيق ما من تغليف الدليل directory الخاص به ببعض الملفّات الضّروريّة (مع القليل من الملفّات المُوصى بها)، تحديد العناصر المرتبطة (كالموارد resources والاعتماديات dependencies، إلخ) وإصدارها أو استخدامها في مكان آخر ببساطة. ملاحظة: نشجعك بشدة على العمل على بيئات افتراضيّة لعزل تنزيلات بايثون، الوحدات والتطبيقات التي تعمل عليها. 1. حزم بايثونالحزمة في بايثون هي تقنيا عبارة عن دليل قابل للاستيراد (باستخدام init__.py__ ) يحتوي على ملفات المصادر (كالوحدات)، ولا يجب الخلط بينها وبين حزم نظام التشغيل والتي هي تقنيًّا تطبيقات فعلية (مثل حزمة Debian)، ومع ذلك يجب أن نُلاحظ أنّ توزيعات بايثون في الواقع تدعى أيضًا بالحزم. مثال على بنية الحِزمة: package | |-- __init__.py2. تطبيقات بايثونعلى الرّغم من أنّه يُمكننا اعتبار أي شيء في بايثون كتطبيق وذلك ابتداء من ملف واحد وحتى مئات الملفات المُبعثرة عبر الحزم المُختلفة، فإنّ التطبيق في أغلب الحالات الواقعيّة يتكوّن من العديد من الوحدات والبعض من الاستيرادات الخارجيّة (من المكتبات). مثال على بنية التّطبيق: myapp | |-- __init__.py |-- amodule.py |-- anothermod.py |__ tests | | | |-- __init__.py | |-- .. | |-- . | ..3. مكتبات وأدوات توزيع بايثوننظرا لطبيعة شعبية لغة بايثون ووجود كميّة وافرة من مكتبات وتطبيقات الطرف الثالث third-party المكتوبة لأجلها فقد كان من الضّروري دوما إيجاد طريقة مُوحّدة وأبسط لتوزيعها، تُوجد العديد من المكتبات والأدوات المختلفة المُستخدمة لإنشاء توزيعات بايثون. تمّ إنشاء مجموعة الأدوات المساعدة لتوزيع بايثون والتي تدعى distutils من أجل التعامل مع مهام التوزيع. 4. دليل حزم بايثون (Python Package Index (PyPIدليل حزم بايثون أو PyPI هو مستودع مركزي (على الإنترنت Online) للمشاريع (توزيعات بايثون)، حيث تستخدم أدوات إدارة الحِزم مثل pip هذا المستودع من أجل استضافة، إيجاد وتثبيت الحِزَم. البدءفلنقم في البداية بإنشاء تطبيق بايثون بسيط وعام باستخدام إطار العمل المصغّر flask (إنشاء البنية) والذي يُمكننا لاحقًا تحزيمه. التطبيق عبارة عن تطبيق ويب بسيط جدا، ﻷن الهدف من الدرس هو كيفية التحزيم وليس التطبيق في حد ذاته. إنشاء بنية التطبيقنهدف إلى إنشاء مثال يشابه معظم مشاريع العالم الحقيقي، ولهذا من الأفضل أن نتخيّل حالة تحتوي على وحدات. بُنية المثال: /MyApplication |-- run.py |-- config.py |__ /app |-- __init__.py |-- /module_one |-- __init__.py |-- controllers.py |-- models.py |__ /templates |-- module_one |-- hello.html |__ /static |__ .. |__ .1. إنشاء المجلدات:/MyApplication |-- run.py |-- config.py |__ /app |-- __init__.py |-- /module_one |-- __init__.py |-- controllers.py |-- models.py |__ /templates |-- module_one |-- hello.html |__ /static |__ .. |__ .2. تعديل الملف run.py باستخدام برنامج nano:nano ~/MyApplication/run.pyنضع المحتويات التّالية بداخله: # Run a test server. from app import app app.run(debug=True)نقوم الآن بحفظه والخروج منه باستخدام CTRL+X ومن ثم تأكيد ذلك باستخدام Y. 3. تعديل الملف config.py باستخدام برنامج nano:nano ~/MyApplication/config.pyنضع المحتويات التّالية بداخله: DEBUG = True THREADS_PER_PAGE = 4 CSRF_ENABLED = True CSRF_SESSION_KEY = "secret"نقوم الآن بحفظه والخروج منه باستخدام CTRL+X ومن ثم تأكيد ذلك باستخدام Y. 4. تعديل الملف app/init.py باستخدام برنامج nano:nano ~/MyApplication/app/__init__.pyنضع المحتويات التّالية بداخله: from flask import Flask, render_template app = Flask(__name__) app.config.from_object("config") from app.module_one.controllers import module_one app.register_blueprint(module_one) نقوم الآن بحفظه والخروج منه باستخدام CTRL+X ومن ثم تأكيد ذلك باستخدام Y. 5. تعديل الملف app/module_one/controllers.py باستخدام برنامج nano:nano app/module_one/controllers.pyنضع المحتويات التّالية بداخله: from flask import Blueprint, request, render_template module_one = Blueprint("auth", __name__, url_prefix="/auth") @module_one.route("/hello") def hello(): return render_template("module_one/hello.html")نقوم الآن بحفظه والخروج منه باستخدام CTRL+X ومن ثم تأكيد ذلك باستخدام Y. 6. تعديل الملف app/templates/module_one/hello.html باستخدام برنامج nano:nano app/templates/module_one/hello.htmlنضع المحتويات التّالية بداخله: <DOCTYPE html> <html lang="en"> <head> <title>{% block title %}My Site{% endblock %}</title> {% block css %} {% endblock %} <meta name="viewport" content="width=device-width, initial-scale=1.0"> </head> <body> Hello, world! </body> </html>نقوم الآن بحفظه والخروج منه باستخدام CTRL+X ومن ثم تأكيد ذلك باستخدام Y. البدء بتوزيع وحزم التطبيقبعد إنشاء بنية التطبيق المثالية لموقع ويب يستخدم flask، نستطيع المتابعة بالقيام بالخطوة الأولى في إعداد التوزيعة. 1. تبديل بنية المجلدمن أجل حَزْم تطبيقنا بشكل جيّد نحتاج للقيام ببعض الإضافات لبُنية مجلّدنا. /MyApplication |-- run.py |__ /app |-- __init__.py |-- /module_one |-- __init__.py |-- controllers.py |-- models.py |__ /templates |-- module_one |-- hello.html |__ /static |__ .. |__ . |-- setup.py # Distribution setup file |-- README.txt # Read-me file |-- MANIFEST.in # Distribution manifest file |-- CHANGES.txt # Changes logفلنقم بتبديل بنية المجلد لإنشاء الملفات الضروريّة: touch ~/MyApplication/setup.py touch ~/MyApplication/README.py touch ~/MyApplication/MANIFEST.py touch ~/MyApplication/CHANGES.py mv ~/MyApplication/run.py ~/MyApplication/bin/run2. إنشاء الملف setup.pynano ~/MyApplication/setup.pyنضع المحتويات التّالية بداخله: from distutils.core import setup setup( # Application name: name="MyApplication", # Version number (initial): version="0.1.0", # Application author details: author="name surname", author_email="name@addr.ess", # Packages packages=["app"], # Include additional files into the package include_package_data=True, # Details url="http://pypi.python.org/pypi/MyApplication_v010/", # # license="LICENSE.txt", description="Useful towel-related stuff.", # long_description=open("README.txt").read(), # Dependent packages (distributions) install_requires=[ "flask", ], )نقوم الآن بحفظه والخروج منه باستخدام CTRL+X ومن ثم تأكيد ذلك باستخدام Y. 3. إنشاء الملف MANIFEST.inإن كنا نحتاج إلى شحن دلائل إضافية (ثابتة static أو قوالب templates) يجب علينا التصريح عنها في manifest لكي يتمّ حَزْمها، سنقوم بفعل هذا في MANIFEST.in. nano ~/MyApplication/MANIFEST.inنضع المحتويات التّالية بداخله: recursive-include app/templates * recursive-include app/static *نقوم الآن بحفظه والخروج منه باستخدام CTRL+X ومن ثم تأكيد ذلك باستخدام Y. هذا هو كل ما نحتاجه ، الآن حِزمة توزيعة بايثون جاهزة ليتمّ تثبيتها وشحنها. 4. ملفات إضافيةيجب دومًا أن نتذكّر أنّه من أجل الحصول على توزيعة كاملة يجب أن يكون الملف/الدليل محتويًا على الملفّات التالية ومربوطًا بها: README.txtMANIFEST.inLICENSE.txtالتعامل مع التطبيق الجاهز للتوزيعبعد أن انتهينا من إنشاء تطبيقنا ومن ثم أجرينا التبديلات الضرورية لبنية الملف لتحضيره لبناء توزيعة لا تحتوي على أيّة أخطاء، نستطيع الآن البدء بالمرور على عمليّات الحَزْم. 1. كيف نقوم بإنشاء ملف التوزيعمن أجل توليد نسخة ملف التوزيع، نقوم بتنفيذ الأمر التالي: cd ~/MyApplication python setup.py sdistسيذهب هذا الأمر إلى إعداداتنا، يطبع العمليات التي يتمّ تنفيذها ويُوَلِّد ملف أرشيف tar داخل الدليل الجديد diet، مشابهًا لما يلي: # root@hostname:~/MyApplication# ls dist # MyApplication-0.1.0.tar.gzملاحظة: بما أنّنا لم نقم بتأهيل جميع المجلدات الفرعية (مثل static) وتعاملنا مع ملفات إضافية (مثل README.txt)، فقد نحصل على بعض التحذيرات أثناء عمليّة الإنشاء. 2. كيفية تثبيت التطبيقيستطيع الآخرون من الآن فصاعدًا تثبيت واستخدام التّطبيق باستخدام ملف setup.py الذي أنشأناه. من أجل تثبيت التطبيق نقوم بتنفيذ الأوامر التالية: python setup.py installإن كان هذا التثبيت من أجل التطوير وأردنا تثبيت المُتطلّبات سنقوم بتنفيذ ما يلي: python setup.py develop3. كيفية مشاركة التطبيقإن أردنا مشاركة الشيفرة على دليل حِزَم بايثون، نستطيع فعل ذلك عن طريق بدء الإجراء register كما يلي: python setup.py registerنستطيع إكمال هذا الإجراء عبر اتّباع التّعليمات التي تظهر على الشّاشة. وإن كنّا نملك تسجيل دخول مسجل registered login من أجل الرفع Upload فقط نستطيع استخدام الأمر التالي: python setup.py sdist upload4. كيفية إنشاء حزم من الإصدارات الجديدة للتطبيقنقوم بتحرير الملف setup.py عن طريق مُحرّر نصوص (مثل nano) وتعيين رقم الإصدار الجديد "version="0.1.1.نقوم بتحرير الملف CHANGES.txt لنعكس التغييرات.نقوم بإجراء التّعديلات الضّروريّة على الملفين LICENSE.txt و README.txt.رفع الشّيفرة بعد الخطوة السّابقة.ترجمة -وبتصرّف- لـلمقال How To Package And Distribute Python Applications لصاحبه O.S. Tezer. حقوق الصورة البارزة: Designed by Freepik.