دليل تعلم بايثون كيفية ترحيل شيفرة بايثون 2 إلى بايثون 3


محمد الميداوي

طُوِّرَت بايثون في أواخر الثمانينات، وأُطلقَت لأول مرة عام 1991. استُوحي اسمها من المجموعة الكوميدية البريطانية Monty Python، تُعدُّ بايثون خليفة للغة البرمجة ABC متعددة الأغراض. تضمنت بايثون في إصداراتها الأولى معالجة الاستثناءات، والدوال، والأصناف والوراثة.

سيرشدك هذا الدرس إلى أفضل آليات وممارسات ترحيل الشيفرات من بايثون 2 إلى بايثون 3، وما إن كان عليك جعل الشيفرة متوافقة مع كلا الإصدارين.

كيـفـيــة-تـرحـيـــل-شيفرة-بايثون-2-إلـى-بـايـثــــــون-3.jpg

خلفية عامة

صدر الإصدار 2 من بايثون عام 2000، ليُدشِّن حقبةً جديدةً من التطوير تقوم على الشفافية والشمولية، إذ شمل هذا الإصدار العديد من الميزات البرمجية، واستمر في إضافة المزيد طوال مدة تطويره.

يُعد إصدار بايثون 3 مستقبل بايثون، وهو إصدار اللغة قيد التطوير حاليًا، فجاء في أواخر عام 2008، ليعالج العديد من عيوب التصميم الداخلية ويُعدِّلها. بيْد أنَّ اعتماد بايثون 3 كان بطيئًا بسبب عدم توافقه مع بايثون 2.

في خضم ذلك، جاء الإصدار بايثون 2.7 في عام 2010 ليكون آخر إصدارات بايثون ‎2.x وليُسِّهل على مستخدمي بايثون ‎2.x الانتقال إلى بايثون 3 من خلال توفير قدر من التوافق بين الاثنتين، فهذا هو الهدف الأساسي من إطلاقه.

يمكنك معرفة المزيد حول إصدارات بايثون والاختيار من بينها من المقالة: اعتبارات عملية للاختيار ما بين بايثون 2 و بايثون 3.

ابدأ ببايثون 2.7

للانتقال إلى بايثون 3، أو لدعم بايثون 2 وبايثون 3 معًا، يجب عليك التأكد من أنّ شيفرة بايثون 2 متوافقة تمامًا مع بايثون 2.7.

يعمل العديد من المطورين حصريًا بشيفرات بايثون 2.7، أمَّا المبرمجون الذي يعملون بشيفرات أقدم، فعليهم أن يتأكدوا من أنّ الشيفرة تعمل جيدًا مع بايثون 2.7، وتتوافق معه.

التأكُّد من توافق الشيفرة مع بايثون 2.7 أمرٌ بالغ الأهمية لأنه الإصدار الوحيد من بايثون 2 الذي ما يزال قيد الصيانة، وتُصحَّحُ ثغراته. فإذا كنت تعمل بإصدار سابق من بايثون 2، فستجد نفسك تتعامل مع مشكلات في شيفرة لم تعد مدعومة، ولم تعد ثغراتها تُصحَّح.

هناك أيضًا بعض الأدوات التي تسِّهل ترحيل الشيفرة، مثل الحزمة Pylint التي تبحث عن الأخطاء البرمجية، لكن لا تدعمها إصدارات بايثون السابقة للإصدار 2.7.

من المهم أن تضع في حسبانك أنَّه رغم أنَّ بايثون 2.7 ما زالت قيد الدعم والصيانة في الوقت الحالي، إلا أنَّها ستموت في النهاية. ستجد في PEP 373 تفاصيل الجدول الزمني لإصدار بايثون 2.7، وفي وقت كتابة هذا المقال، فإنّ أجل بايثون 2.7 حُدِّد في عام 2020 (يحتمل أن تكون قد ماتت وأنت تقرأ هذه السطور :-| ).

الاختبار

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

يمكنك إضافة حالات بايثون التفاعلية (interactive Python cases) إلى السلاسل النصية التوثيقية (docstrings) الخاصة بكافة الدوال والتوابع والأصناف والوحدات، ثم استخدام الوحدة doctest المضمنة للتحقق من أنها تعمل كما هو موضح، إذ يعدُّ ذلك جزءًا من عملية الاختبار.

إلى جانب doctest، يمكنك استخدام الحزمة package.py لتتبع وحدة الاختبار. ستراقب هذه الأداة برنامجك وتحدد الأجزاء التي تُنفِّذها من الشيفرة، والأجزاء التي يمكن تنفيذها ولكن لم تُنفَّذ. يمكن أن تطبع Cover.py تقارير في سطر الأوامر، أو تنتج مستند HTML. تُستخدم عادةً لقياس فعالية الاختبارات، إذ توضح الأجزاء من الشيفرة التي اختُبِرت، والأجزاء التي لم تُختبَر.

تَذكَّر أنه ليس عليك اختبار كل شيء، لكن تأكَّد من تغطية أيّ شيفرة غامضة أو غير عادية. للحصول على أفضل النتائج، يُنصح أن تشمل التغطية 80٪ من الشيفرة.

تعرف على الاختلافات بين بايثون 2 و بايثون 3

سيمكّنك التعرّف على الاختلافات بين بايثون 2 و بايثون 3 من استخدام الميزات الجديدة المتاحة، أو التي ستكون متاحة في بايثون 3.

تتطرق مقالتنا حول "اعتبارات عملية للاختيار ما بين بايثون 2 و بايثون 3" إلى بعض الاختلافات الرئيسية بين الإصدارين. يمكنك أيضًا مراجعة توثيق بايثون الرسمي لمزيد من التفاصيل.

عند البدء في ترحيل الشيفرة، فهناك بعض التغييرات في الصياغة عليك تنفيذها فوريًا.

  • print حلت الدالة print()‎‎ في بايثون 3 مكان التعليمة print في بايثون 2:
بايثون 2 بايثون 3
"مرحبا بالعالم!" print ("مرحبا بالعالم!")print

 

  • exec تغيَّرت التعليمة exec في بايثون 2 وأصبحت دالةً تسمح بمتغيرات محلية (locals) وعامة (globals) صريحة في بايثون 3:
بايثون 2 بايثون 3
exec code exec(code)‎
exec code in globals exec(code, globals)‎
exec code in (globals, locals)‎ exec(code, globals, locals)‎

 

  • / و // تُجرِي بايثون 2 القسمة التقريبية (floor division) بالعامل / ، بينما تخصص بايثون 3 العامل // لإجراء القسمة التقريبية:
بايثون 2 بايثون 3
‎5 / 2 = 2‎ ‎5 / 2 = 2.5‎
  ‎5 // 2 = 2‎

لاستخدام هذين المعاملين في بايثون 2، استورد division من الوحدة __future__:

from __future__ import division

اقرأ المزيد عن قسمة الأعداد الصحيحة من المقالة: اعتبارات عملية للاختيار ما بين بايثون 2 و بايثون 3.

  • raise في بايثون 3، يتطلب إطلاق الاستثناءات ذات الوسائط استخدام الأقواس، كما لا يمكن استخدام السلاسل النصية كاستثناءات:
بايثون 2 بايثون 3
raise Exception, args raise Exception
  raise Exception(args)‎
raise Exception, args, traceback raise Exception(args).with_traceback(traceback)‎
raise "Error"‎ raise Exception("Error")‎

 

  • except في بايثون 2، كان من الصعب إدراج الاستثناءات المُتعدِّدة، لكن ذلك تغيَّر في بايثون 3.

لاحظ أنَّ as تُستخدَم صراحةً مع except في بايثون 3:

بايثون 2 بايثون 3
except Exception, variable:‎ except AnException as variable:‎
  except (OneException, TwoException) as variable:‎

 

  • def في بايثون 2، يمكن للدوال أن تقبل سلاسل مثل الصفوف أو القوائم. أمَّا في بايثون 3، فقد أزيل هذا الأمر.
بايثون 2 بايثون 3
def function(arg1, (x, y)):‎ def function(arg1, x_y): x, y = x_y

 

  • expr لم تعد صياغة علامة الاقتباس المائلة `` في بايثون 2 صالحة، واستخدم بدلًا عنها repr()أوstr.format()‎` في بايثون 3.
بايثون 2 بايثون 3
`x = `355/113`` `x = repr(355/113):`

 

  • تنسيق السلاسل النصية (String Formatting) لقد تغيرت صياغة تنسيق السلاسل النصية من بايثون 2 إلى بايثون 3.
بايثون 2 بايثون 3
`"%d %s" % (i, s)` `"{} {}".format(i, s)`
`"%d/%d=%f" % (355, 113, 355/113)` `"{:d}/{:d}={:f}".format(355, 113, 355/113)`

تعلم كيفية استخدام تنسيقات السلاسل النصية في بايثون 3 من مقالة كيفية استخدام آلية تنسيق السلاسل النصية في بايثون 3.

  • class ليست هناك حاجة لتمرير object في بايثون 3.

    • بايثون 2
class MyClass(object):
    pass
    •  بايثون 3
class MyClass:
    pass

 

  • في بايثون 3، تُضبَط الأصناف العليا (metaclasses) بالكلمة مفتاحية metaclass.
    • بايثون 2:
class MyClass:
    __metaclass__ = MyMeta

 

class MyClass(MyBase):
    __metaclass__ = MyMeta
    •  بايثون 3:
 
class MyClass(metaclass=type):
    pass
class MyClass(MyBase, metaclass=MyMeta): 
    pass

تحديث الشيفرة

هناك أدَاتان رئيّسيتان لتَحديث الشيفرة تلقائيًا إلى بايثون 3 مع الحفاظ على توافقيّتها مع بايثون 2 وهما: future و modernize. تختلف آليَتا عمل هاتين الأداتين، إذ تحاول future نقل أفضل ممارسات بايثون 3 إلى بايثون 2، في حين أنّ modernize تسعى إلى إنشاء شيفرات موحدة لبايثون تتوافق مع 2 و 3 وتستخدم الوحدة six لتحسين التوافقية.

يمكن أن تساعدك هاتان الأداتان في إعادة كتابة الشيفرة وتحديد ورصد المشاكل المحتملة وتصحيحها.

يمكنك تشغيل الأداة عبر مجموعة unittest لفحص الشيفرة والتحقق منها بصريًا، والتأكد من أنّ المراجعات التلقائية التي أُجريَت دقيقة. وبمجرد انتهاء الاختبارات، يمكنك تحويل الشيفرة.

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

إن أردت استخدام future، فعليك إضافة عبارة الاستيراد التالية في جميع وحدات بايثون 2.7:

from __future__ import print_function, division, absolute_imports, unicode_literals

رغم أن هذا لن يعفيك من إعادة كتابة الشيفرة، إلا أنه سيضمن لك أن تتماشى شيفرة بايثون 2 مع صياغة بايثون 3.

أخيرًا، يمكنك استخدام الحزمة pylint لتحديد ورصد أي مشكلات محتملة أخرى في الشيفرة. تحتوي هذه الحزمة على مئات القواعد التي تغطي مجموعة واسعة من المشكلات التي قد تطرأ، بما فيها قواعد الدليل PEP 8، بالإضافة إلى أخطاء الاستخدام.

قد تجد أنّ بعض أجزاء شيفرتك تربك pylint وأدوات الترحيل التلقائي الأخرى. حاول تبسيطها، أو استخدم unittest.

التكامل المستمر (Continuous Integration)

إذا أردت أن تجعل شفرتك متوافقة مع عدة إصدارات من بايثون، فستحتاج إلى تشغيل الإطار unittest باستمرار وفق مبدأ التكامل المستمر (وليس يدويًا)، أي أن تفعل ذلك أكبر عدد ممكن من المرات أثناء عملية التطوير.

إذا كنت تستخدم الحزمة six لصيانة التوافقية بين بايثون 2 و 3، فستحتاج إلى استخدام عدة بيئات عمل لأجل الاختبار.

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

خلاصة

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

هذه المقالة جزء من سلسة مقالات حول تعلم البرمجة في بايثون 3.

ترجمة -وبتصرّف- للمقال How To Port Python 2 Code to Python 3 لصاحبته Lisa Tagliaferri

اقرأ أيضًا





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


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



يجب أن تكون عضوًا لدينا لتتمكّن من التعليق

انشاء حساب جديد

يستغرق التسجيل بضع ثوان فقط


سجّل حسابًا جديدًا

تسجيل الدخول

تملك حسابا مسجّلا بالفعل؟


سجّل دخولك الآن