مشاكل واسئلة التطوير من python2 الى python3

mfaraj57

مسؤول فريق الدريم بوكس
طاقم الإدارة
إنضم
24 أوت 2007
المشاركات
9.927
مستوى التفاعل
47.711
السلام عليكم
بدأ الحديث عن تطوير صور الانيجما من python2 الى python3 وبدأت بعض الفرق بالفعل اطلاق الاصدارات الحديثه مزوده ب python3
مثل openatv 6.5.
الانتقال ليس سهلا على المطوريين لان البرامج والسكينات التي كانت تعمل في بيئة python2 تحتاج الى تعديل لتعمل على python3.
وكل ما زادت الاضافه او البرنامج او السكين تعقيدا زاد العمل المطلوب لتحويله.
قد يخطر على البال السؤال ولماذا التطوير الى python3 مع كل هذه المشاكل مع توقف عدد كبير من البلاغنات والسكينات عن العمل
في الواقع الامر ليس اختياري للفرق ويتوجب عليها التطوير اذا ارادت ان تبقى في الساحه لسببان ان python.org وهي مصدر لغة Python ألغت دعم اصدارات python2 والسبب الثاني ان الباكجات الحديثه التي تعمل على python والانيجما كلها تدعم فقط python3.
لست بصدد ذكر ميزات python3 على Python2 فزملائنا المبرمجين هم اقدر على ذكر ذلك اذا كان لهم معرفه بها.
بالتعاون بيني وبين الاخ حسين قمنا بتطوير بعض البلاغنات لكن لا اعتقد ان هنا احد عنده الخبره الكافيه لذلك سنتعاون لحل اي مشكله في تطوير اي بلغن او سكين والمفروض التوجه اولا الى مبرمج البلغن او السكين لتحويله لان عملية التطوير تتطلب فهم الكود وعمله وهي ليست مباشره
نرحب بارائكم ومعلوماتكم عن الموضوع .
هذا الموضوع ليس لاستقبال طلبات تحويل البلاغنات فهذه عمليه شاقة وتأخذ وقتا وانما للمساعده في مشكله معينه اثناء التحويل
 
التعديل الأخير:

mfaraj57

مسؤول فريق الدريم بوكس
طاقم الإدارة
إنضم
24 أوت 2007
المشاركات
9.927
مستوى التفاعل
47.711
للمطورين فقط
اكثر الاخطاء شيوعا في عملية التحويل من Py2 ألى py3 هو عدم التمييز بين bytes , str
كود:
TypeError: a bytes-like object is required, not 'str'
لمعرفة التعامل مع هذا الخطأ يجب اخذ فكره عن هذان النوعان data types
لست خبيرا في هذا الموضوع ولكن هذا ما تعلمته اثناء عملية تحويل بعض البلاغنات من py2 الى py3

bytes , str هما نوعان يمثلان لما يسمى string
وكانا يستعمبلان في py2 ولكن لم يكون حدود فاصله ظاهره ولكن مع Python3 أصبح النوعان منفصلان تماما واستعمال واحد بدل الاخر يؤدي الى خطأ كالمذكور اعلاه
مفهموم bytes وهو نوع متغير type variable اقرب الى تمثيل النص الى لغة الجهاز Machine language
ويكتب مباشرة الى memory او الدسك
str هو نص مقروء human readable ويجب تحويله الى bytes قبل تخزينه
ما يهمنا هو عملية التحويل بين النوعان في حال مصادفة خطأ كالمذكور اعلاه
للتحويل من str الى bytes هناك عدة طرق ولكن ساذكر اثنتان لتفادي التشويش
اذا كان النص ثابت مثل نضيف حرف b امام النص
كود:
str url='https://www.tunisia-sat.com/forums/threads/4142603/'

bytes url=b'https://www.tunisia-sat.com/forums/threads/4142603/

الحاله الثانيه اذا كان متغير
مثل
كود:
url is str
page_url=b"http://"+ url.encode("utf-8")
نستخدم encode مع تمرير utf-8 encoding مع انه ليس ضروري لان utf-8 هو الافتراضي وممكن استخدام
encoding اخر حسب لغة النص
للتحويل من bytes الى str نستخدم decode
كود:
url is bytes
page_url=url.decode("utf-8")
مثال على ذلك ما يحدث اثناء استعمال مكتبة twisted web المستعمله كثيرا في الانيجما لتنزيل عدة ملفات او صور بدون ايقاف الكود
كود:
    def checkupdates(self):
           try:
                   from twisted.web.client import getPage, error
                   url = 'http://xxxx.info/plugins//installer.sh'
                
                   getPage(url, headers={'Content-Type': 'application/x-www-form-urlencoded'}, timeout=10).addCallback(self.parseData).addErrback(self.errBack)
           except Exception as error:
                   trace_error()
    def errBack(self,error=None):
           logdata("[error %s]" % str(error))

    def addErrback(self, result):
           logdata("data-failed",result)
           if result:
               logdata("Error:",str(result))

في عملية تطبيق الكود اعلاه نحصل على الخطأ التالي
كود:
builtins.TypeError: sequence item 0: expected a bytes-like object, str found

واضح من المثال ان getPage رفضت الرابط لكونه متغير نصي str بينما هي لا تقبل الا متغير من نوع bytes
لمعالجة الخطا فقط نحول الرابط من str الى bytes قبل تمريره الى getPage هكذا
كود:
try:
                   from twisted.web.client import getPage, error
                   url = b'http://xxxx.info/plugins//installer.sh'##add character b
او باستخدام encode
كود:
try:
                   from twisted.web.client import getPage, error
                   url = 'http://xxxx.info/plugins//installer.sh'
                   url=url.encode()
 
التعديل الأخير بواسطة المشرف:

fairman

كبير مراقبي فريق الدريم بوكس
طاقم الإدارة
إنضم
8 جانفي 2012
المشاركات
25.299
مستوى التفاعل
92.658
كذلك في python3 دائماً نحتاج الى إضافة هذا الكود ببداية الملف لان utf-8 أصبح إفتراضي في Py3 فعدم وجودة يسبب خطأ في الملف إذا كان يحتيو على أكواد تعتمد على encoding
كود:
#!/usr/bin/python
# -*- coding: utf-8 -*-

واما بخصوص طباعة المعلومات print في Python3 يجب أن نضع المعطيات ما بين قوسين وإلا سوف يحدث لنا خطأ

اولاً يجب وضع هذا الكود في أعلى الملف وليس في اسفل اوامر import هكذا
كود:
#!/usr/bin/python
# -*- coding: utf-8 -*-

# python3
from __future__ import print_function

ثم مثال على print هكذا يجب أن يكون

python 2
كود:
print "This is python2"

python 2+3
كود:
print("This is python2")
 

fairman

كبير مراقبي فريق الدريم بوكس
طاقم الإدارة
إنضم
8 جانفي 2012
المشاركات
25.299
مستوى التفاعل
92.658
إستيراد المعلومات من ملفات بايثون اخرى ...

حينما نريد إستيراد بعض الاكواد او def من ملف اخر موجود بنفس مجلد البلجن مثلاً

لدينا بلجن يحتوي على مجلد plugin.py و skin.py

في python 2 يكون هكذا لا مشكلة
كود:
from skin import *

أما في python 3 يجب وضع علامة . قبل إسم الملف وإلا سوف يحدث كراش هكذا
كود:
from .skin import *

او مثال اخر لدينا بلجن إسمه Test ويحتوي بداخله على مجلد إسمه screens وبداخل المجلد يحتوي على skin.py
حتى نستورد معلومات skin.py الذي في مجلد screens يجب الكتابه المسار هكذا ولا ننسى . ببداية السطر
كود:
from .screens.skin import *

***************

أما إذا كان الملف في مسار خارج مجلد البلجن يجب وضع المسار كاملاً مثلاً نجلب screen

في python 2 كان هكذا لا يسبب مشكلة
كود:
from Screen import Screen

أما python 3 يجب أن نحدد المسار بشكل صحيح كامل هكذا
كود:
from Screens.Screen import Screen
او نستور معلومات config
كود:
from Components.config import config, getConfigListEntry
 

fairman

كبير مراقبي فريق الدريم بوكس
طاقم الإدارة
إنضم
8 جانفي 2012
المشاركات
25.299
مستوى التفاعل
92.658
التعديل الأخير:

mfaraj57

مسؤول فريق الدريم بوكس
طاقم الإدارة
إنضم
24 أوت 2007
المشاركات
9.927
مستوى التفاعل
47.711
برنامج صغير يساعد في اجراء التحويلات الاساسيه في تحويل ملف Python2 ألى ملف Python3
يجب تنصيب python 3.8 او 3.9 على الحاسوب
تعيين مسار python3 من الاعدادات settings
windows7,8,9,10

يوجد خياران
التحويل يجري على الملف الاصلي وياخذ باكب عنه قبل التحويل
او اعادة تسمية الملف المحول الى امتداد py3

main.png

screenshot_65.pngscreenshot_66.png
 

المرفقات

  • p2p3converter.zip
    100 KB · المشاهدات: 7

mfaraj57

مسؤول فريق الدريم بوكس
طاقم الإدارة
إنضم
24 أوت 2007
المشاركات
9.927
مستوى التفاعل
47.711
برنامج اخر لتحويل ملفات python2 الى python3
يعمل على ويندوز و لينكس
مبرمج على tkinter python

 

المرفقات

  • Py2-to-Py3-Converter-GUI-tkinter-master.zip
    58,2 KB · المشاهدات: 11

fairman

كبير مراقبي فريق الدريم بوكس
طاقم الإدارة
إنضم
8 جانفي 2012
المشاركات
25.299
مستوى التفاعل
92.658
كذلك مستخدمي linux وبشكل خاص ubuntu يطبقوا ما يلي ...
يثبتوا بكيج 2to3
كود:
sudo apt update
sudo apt install 2to3
ثم بعدها لتحويل نعطي امر بسيط وهو 2to3 ونضع بجنبه إسم الملف
كود:
2to3 plugin.py
سوف يظهر لنا باتش المتغيرات التي - هو الكود المحذوف و + هو الكود الجديد المحول الى بايثون 3
كود:
[email protected]:~/Desktop$ 2to3 plugin.py
--- plugin.py    (original)
+++ plugin.py    (refactored)
@@ -67,11 +67,11 @@
                 if self.frontend:
                     return True
                 else:
-                    print "getFrontend failed"
+                    print("getFrontend failed")
             else:
-                print "getRawChannel failed"
+                print("getRawChannel failed")
         else:
-            print "getResourceManager instance failed"
+            print("getResourceManager instance failed")
         return False

     def __init__(self, session, feid=0):
@@ -123,7 +123,7 @@

     def newConfig(self):
         cur = self["config"].getCurrent()
-        print "cur is", cur
+        print("cur is", cur)
         if cur is None:
             pass
         elif cur == self.typeOfScanEntry or \
@@ -395,7 +395,7 @@
         self.tuning_type = ConfigSelection(choices = [("predefined_transponder", _("Predefined transponder")), ("manual_transponder", _("Manual transponder"))])
         self.tuning_sat = getConfigSatlist(192, nimmanager.getSatListForNim(self.feid))
                 self.orbital_position = 192
-        if self.frontendData and self.frontendData.has_key('orbital_position'):
+        if self.frontendData and 'orbital_position' in self.frontendData:
             self.orbital_position = self.frontendData['orbital_position']
         ScanSetup.createConfig(self, self.frontendData)
         self.updateSats()
RefactoringTool: Files that need to be modified:
RefactoringTool: plugin.py

ولمعرفة المزد من الاوامر تعطي امر help
كود:
2to3 --help

للمزيد من هنا
 
التعديل الأخير:
أعلى