تحويل ملف بايثون إلى ملف تنفيذي exe و حل مشكل كبر حجم الملف :

 

الكاتب : محمد الهادي بالطيب .
السلام عليكم ورحمة الله وبركاته وصلَّى الله على نبينا الأكرم وسلّم عليه تسليماً.
قبل البدء أتوجه بكل شكري و تقديري لأستاذي صلاح اعطير الذي شرّفني بمراجعة و تصحيح هذا المقال .
في مشاركتِنا اليوم سنتطرق لعملية تحويل ملف بايثون إلى ملف تنفيذي بأكبر قدر من التفصيل. 
وسنقسّم هذه المشاركة إلى ثلاثةِ أقسام، يمكنكم الانتقال بينهم بحرف h أو رقم 2.
تحويل ملف بسيط و تحويل مشروع متكامل و حل مشكل كبر حجم الملف التنفيذي .

القسم الأول: تحويل ملف بسيط.

المكتبة التي سأستخدمها في هذا الشرح هي مكتبة pyinstaller. أول ما علينا فعله هو تثبيت هذه المكتبة هكذا: pip install pyinstaller ملف البايثون الذي سيرافقنا في كل مراحل هذه المشاركة اسمه test.py. في البداية سيكون ملفنا بسيطا وسنحوّله هكذا: في cmd نختار مسار ملفنا ثم نكتب الأمر التالي: pyinstaller -w --onefile test.py -w تعني، بعد أن تتم عملية التحويل ونشغّله لن تظهر معنا شاشة cmd أما إن كنا نحتاج لهذه الشاشة ( مثلا لو ملفنا سيطبع لنا شيئا ما ) فإننا لا نكتب -w. --onefile تعني أننا نطلب من pyinstaller أن يضع الملف التنفيذي في ملف وحيد وإن لم نكتب هذا الرمز سيكون الملف التنفيذي الناتج في مجلدات وملفات متعددة. بعد انتهاء عملية التحويل بنجاح ندخل لمسار ملفنا وسنلاحظ وجود مجلدات جديدة وكذلك ملف اسمه test.spec وهذا الملف سنعود له في مرحلة متقدمة من هذه المشاركة، ما يعنينا حاليا أن الملف التنفيذي لملفنا البايثوني سنجده في المجلد الذي إسمهdist.

القسم الثاني: تحويل مشروع متكامل إلى ملف تنفيذي.

بعد شرح عملية تحويل ملف بسيط في القسم السابق سنتحدث الآن عن عملية تحويل أكثر تعقيدا. لنفترض أن ملفنا البايثون البسيط الذي حوّلناه في ما سبق، لنفترض أننا طورناه وأصبح مشروع برنامج متعدد المهام والملفات ومن ضمنها ملفات بيانات، في هذه الحالة لن تتم عملية التحويل بنفس الطريقة السابقة. عند عملية التحويل السابقة وجدنا في مسار ملفنا ملفا جديدا إسمه test.spec فماذا يحتوي هذا الملف وكيف نتعامل معه ؟ هذا الملف يحتوي اعدادت وخصائص مشروعنا ويمكن فتحه بواسطة المفكرة وسنجد محتواه شبيها بما يلي: # -*- mode: python ; coding: utf-8 -*- block_cipher = None a = Analysis( ['test.py'], pathex=[], binaries=[], datas=[], hiddenimports=[], hookspath=[], hooksconfig={}, runtime_hooks=[], excludes=[], win_no_prefer_redirects=False, win_private_assemblies=False, cipher=block_cipher, noarchive=False, ) pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher) exe = EXE( pyz, a.scripts, a.binaries, a.zipfiles, a.datas, [], name='test', debug=False, bootloader_ignore_signals=False, strip=False, upx=True, upx_exclude=[], runtime_tmpdir=None, console=False, disable_windowed_traceback=False, argv_emulation=False, target_arch=None, codesign_identity=None, entitlements_file=None, ) بإمكاننا إدخال بعض التعديلات على هذا الملف وسنقوم بتعديل شيء وحيد وأنصح بعدم تعديل أي شيء إلا إذا كنت واثقا وفاهما بالدقة المطلوبة ماذا تعدل وماذا تريد من تعديلاتك تلك. في عملية التحويل البسيطة السابقة قام pyinstaller بشكل تلقائي بإنشاء ملف test.spec ولكن في عملية التحويل " المتقدّمة" التي سنقوم بها الآن سنقسمها إلى مرحلتين منفصلتين: * أولا سنقوم بإنشاء ملف test.spec الخاص بمشروعنا *ثم نقوم بتحويل ملف test.spec إلى ملف تنفيذي وبين المرحلتين سنقوم بإدخال التعديلات التي نريدها على ملف test.spec. سنقوم بالتعديلات بعد إنشاء ملف test.spec وقبل تحويله إلى ملف تنفيذي. 1- ننشىء ملف test.spec الخاص بمشروعنا كما يلي: طبعا في cmd لابد أن نختار دوما مسار مشروعنا. pyi-makespec -w --onefile test.py -w و--onefile هي التي شرحناها في عملية التحويل السابقة في القسم الأول. Microsoft Windows [version 10.0.19044.1706] (c) Microsoft Corporation. Tous droits réservés. C:\Users\hedid\Desktop\test>pyi-makespec -w --onefile test.py Wrote C:\Users\hedid\Desktop\test\test.spec. Now run pyinstaller.py to build the executable. C:\Users\hedid\Desktop\test> ثم نفتح ملفtest.spec الذي سنجده في مسار مشروعنا وسندخل عليه تعديلا وحيدا. مشروعنا الذي تطوّر أصبح يضم ملفات بيانات وسأفترض أن ملفات البيانات هي التالية: 01.text 01.json و3 ملفات صوتيتة بصيغة wav ولكي نجد هذه الملفات مدمجة مع الملف التنفيذي الناتج نبحث داخل ملف test.spec عن العنصر datas وسنجده هكذا: datas = [] فنعدله على هذا النحو: datas = [('01.txt', '.'),('01.json','.'),('*.wav', '.')] "." تعني أن ملفات البيانات توجد في مجلد المشروع أما إن كانت هذه الملفات أو بعضها توجد في مجلدات فرعية، حينها نعوض "." بإسم المجلد الفرعي. وهكذا نكون قد أضفنا كل ملفات البيانات الخاصة بالمشروع إلى test.spec الذي سنحوله الى ملف تنفيذي. بعد إتمام عملية التعديل نحفظ تلك التعديلات ونغلق ملفtest.spec ونتوجه الى موجه الأوامر ونكتب ما يلي pyinstaller test.spec وبعد إتمام عملية التحويل بنجاح سنجد ملفنا التنفيذي داخل مجلد dist في مسار مشروعنا وستكون كل ملفات بياناتنا مدمجة في ذلك الملف وسيشتغل برنامجنا بكل سلاسة بإذن الله. الآن من حقنا أن نفرح بإنجازنا لكننا سنكتشف أمر سينغص علينا فرحتنا وهو حجم الملف التنفيذي الذي سيكون كبيرا بشكل مزعج. في هذه الحالة ماذ علينا أن نفعل ؟ والجواب عن هذا السؤال سيكون محور القسم الثالث بإذن الله.

القسم الثالث:pyinstaller، مشكل كبر حجم الملف التنفيذي، الأسباب والحل.

في القسم السابق قمنا بتحويل مشروعنا إلى ملف تنفيذي وكان حجمه كبيرا بشكل مزعج. وقبل الحديث عن حل مشكل كبر حجم الملف التنفيذي لبرنامجنا سنتحدث عن عملية التحويل كيف تتم. سأتحدث هنا عن لغة البايثون، لكي يشتغل برنامجنا الذي صمّمناه بالبايثون على أي حاسوب لا يحتوي على بايثون يقوم pyinstaller بنسخ بيئة عمل البايثون بما في ذلك المكتبات التي استخدمناها في مشروعنا ويدرج كل هذه البيئة داخل الملف التنفيذي إضافة لملفات مشروعنا وهكذا يصبح بوسع أي حاسوب أن يشغّل ذلك البرنامج بما أنه يحتوي على كل بيئة العمل التي تم بواسطتها تصميم برنامجنا. الأمر يبدو عاديا ومنطقيا فأين المشكل وما دخل هذا في كبر حجم الملف التنفيذي الذي نبحث عن حل له؟ المشكل أن pyinstaller عندما يقوم بنقل بيئة عمل البايثون ويضعها في الملف التنفيذي لا يضع المكتبات التي يحتاجها المشروع والتي كنا نحن إستوردناها في كود برنامجنا فقط بل يضم عدد آخر من المكتبات الزائدة عن الحاجة، وللدقة والأمانة العلمية أنا لا أعرف على أي أساس يختار pyinstaller المكتبات غير الضرورية ليضعها ضمن الملف التنفيذي، إذاً مشكل كبر حجم الملف التنفيذي سببه هو هذه المكتبات التي لا يحتاجها برنامجنا ويضمها pyinstaller للملف التنفيذي. حل مشكل كبر حجم الملف التنفيذي يجب أن يعالج هذه النقطة بالتحديد. ولكن كيف نجبر pyinstaller على ضم المكتبات الضرورية دون سواها للملف التنفيذي؟ الطريقة التي سنعالج بها مشكل كبر حجم الملف التنفيذي ستعتمد هذا المنهج أي إجبار pyinstaller على إدراج المكتبات الضرورية لعمل المشروع فقط دون سواها وهذه المكتبات هي التي استوردناها في مشروعنا واشتغل بها كملف بايثون. الحل هو في ما يسمّى " بيئة العمل الافتراضية virtual environement " ويمكننا إنشاء بيئة عمل افتراضية خاصة بكل مشروع. مثال: ملفنا التنفيذي الذي حصلنا عليه في القسم السابق والذي أزعجنا كبر حجمه سنحذفه فنحن لا نريده لأنه غير عملي. وسنعود لمشروعنا الأصلي بصيغة بايثون وللتذكير كان اسمه test.py ننشىء مجلدا جديدا باسم envs وهذا المجلد envs سنضع داخله البيئة الافتراضية لمشروعنا الحالي وكل مشاريعنا المستقبلية. وبعد إنشاء مجلد البيئات الإفتراضية envs سًَنُنْشِئُ داخله أول مجلد سيكون باسم مشروعنا هذا أي test. سنفترض أن مسار المجلدات الجديدة هو: مجلد envs: D:\programmation\envs ومجلد test: D:\programmation\envs\test يمكننا الآن إنشاء بيئة عمل افتراضية هكذا: في موجه الأوامر نكتب: Microsoft Windows [version 10.0.19044.1645] (c) Microsoft Corporation. Tous droits réservés. C:\Windows\System32>python -m venv D:\programmation\envs\test ونضغط أنتر وننتظر حتى تنتهي عملية إنشاء البيئة الإفتراضية الخاصة بمشروع test وعندما تنتهي هذه العملية سيعود موجه الأوامر لوضعه العادي هكذا: C:\Windows\System32> الآن تم إنشاء بيئة العمل الافتراضية لمشروعنا. نذهب الى مجلد test ونجد أنه أصبح يحتوي عناصر جديدة. بيئة عملنا الافتراضية أصبحت موجودة ولكنها غير مفعلة ولتفعيلها نكتب في موجه الأوامر ما يلي: C:\Windows\System32>D:\programmation\envs\test\Scripts\activate.bat ونضغط أنتر فيصبح شكل موجه الأوامر هكذا: (test) C:\Windows\System32> نلاحظ أن اسم بيئة عملنا الافتراضية مكتوب في أول السطر وموضوع بين قوسين وهذا يعني أننا الآن في بيئة عملنا وهي مفعلة. لنتثبت من المكتبات الموجودة في بيؤة العمل الافتراضية الخاصة بمشروع test نكتب " (test) C:\Windows\System32>pip list وبعد الضغط على أنتر نجد أمامنا قائمة المكتبات واصداراتها المثبتة ببيئة عملنا هكذا: Package Version ---------- ------- pip 18.1 setuptools 40.6.2 You are using pip version 18.1, however version 22.1 is available. You should consider upgrading via the 'python -m pip install --upgrade pip' command. (test) C:\Windows\System32> الآن أصبح الميدان جاهزا لنبدأ عملنا الفعلي وأول ما يجب علينا القيام به هو تثبيت المكتبات التي يحتاجها مشروعنا ومن ضمنها pyinstaller، مثال هكذا: (test) C:\Windows\System32>pip install pyinstaller نلاحظ أننا نتعامل مع بيئة العمل الافتراضية هذه تماما كما نتعامل مع بيئة العمل العادية لبايثون. وبعد تثبيت كل المكتبات التي يحتاجها مشروعنا test.py ونجربه ويشتغل نقوم بتحويله إلى ملف تنفيذي طبقا لما تم شرحه في القسم الثاني. وسيكون حجم الملف التنفيذي صغيرا ومختلفا عن حجمه عندما قمنا بتحويله بالطريقة التقليدية. وللتذكير والتأكيد، كل العمل يكون داخل هذه البيئة يعني يكون موجه الأوامر على هذا الشكل. (test) C:\Windows\System32> بعد الإنتهاء من عملنا نغلق هذه البيئة الافتراضية وذلك بتعطيلها بهذا الأمر (test) C:\Windows\System32>deactivate وهنا نلاحظ أننا عدنا للوضع العادي لموجه الأوامر هكذا: C:\Windows\System32> أتمنى أن تنجح هذه الطريقة في تقليص حجم الملفات التنفيذية لديكم والسلام عليكم ورحمة الله وبركاته. تونس في 04/06/2022 .

تعليقات