جدید آموزش ساخت فایل اجرایی exe در پایتون با استفاده از PyInstaller
یکی از مشکلاتی که کاربران زبان برنامه نویسی پایتون با آن مواجه هستند این است که وقتی کدنویسی به پایان می رسد باید بتوانند محصول نهایی را به صورت فایلی اجرایی در بیاورند که کاربران بدون نیاز به نصب پایتون از آن استفاده کنند. یکی از راههای متداول استفاده از PyInstaller است. در این مطلب خلاصه ای از ترجمه راهنمای این ماژول ارایه شده است.
نصب PyInstaller
برای نصب PyInstaller به این صورت از pip استفاده می کنیم:
pip install pyinstaller
برای به روز رسانی یا آپگرید آن از دستور زیر استفاده می نماییم:
pip install --upgrade pyinstaller
برای اطمینان یافتن از اینکه PyInstaller درست نصب شده است فرمان زیر را اجرا کنید:
pyinstaller --version
PyInstaller به دو ماژول پایتون در سیستم ویندوز نیاز دارد. برای ویندوز به افزونه PyWin32 یا pypiwin32 Python نیاز دارد. اگر PyInstaller را با استفاده از pip نصب می کنید و PyWin32 قبلاً نصب نشده است، pypiwin32 به طور خودکار نصب می شود. PyInstaller همچنین به بسته pefile نیاز دارد.
بسته pip-Win توصیه می شود، اما الزامی نیست.
پکیج PyInstaller چکار می کند و چگونه این کار را انجام می دهد؟
PyInstaller یک اسکریپت پایتون نوشته شده توسط شما را می خواند. کد شما را برای کشف هر ماژول و کتابخانه دیگری که اسکریپت شما برای اجرا نیاز دارد، تجزیه و تحلیل می کند. سپس کپی هایی از تمام آن فایل ها را جمع آوری می کند و آنها را با اسکریپت خود در یک پوشه یا به صورت اختیاری در یک فایل اجرایی قرار می دهد.
برای اکثر برنامه ها، این کار را می توان با یک دستور کوتاه انجام داد:
pyinstaller myscript.py
یا با چند گزینه اضافی، به عنوان مثال یک برنامه پنجره ای به عنوان یک فایل اجرایی تک فایل:
pyinstaller -noconsole –onefile –windowed myscript.py
شما بسته نرم افزاری تولید شده را به عنوان یک پوشه یا فایل بین افراد دیگر توزیع می کنید و آنها می توانند برنامه شما را اجرا کنند. برای کاربران شما، برنامه مستقل است. آنها نیازی به نصب پایتون یا هیچ ماژولی ندارند.
یافتن فایل های مورد نیاز برنامه شما
معمولا اسکریپت شما برای اجرا به ماژول ها و کتابخانه های دیگری نیاز دارد که به آنها Dependencies می گویند.
برای پیدا کردن این فایلها، PyInstaller تمام عبارات import را در اسکریپت شما پیدا می کند. ماژولهای فراخوانی شده را پیدا میکند و در آنها برای عبارات import جستجو میکند، تا زمانی که فهرست کاملی از ماژولهایی را که اسکریپت شما ممکن است استفاده کند، داشته باشد.
برخی از اسکریپتهای پایتون ماژولها را به روشهایی وارد میکنند که PyInstaller نمیتواند شناسایی کند: برای مثال، با استفاده از تابع __import__ با دادههای متغیر، یا دستکاری مقدار sys.path در زمان اجرا. اگر اسکریپت شما به فایل هایی نیاز دارد که PyInstaller از آنها اطلاعی ندارد، باید به آن کمک کنید:
• می توانید فایل های اضافی را در خط فرمان pyinstaller ارایه کنید.
• می توانید مسیرهای import های اضافی را در خط فرمان اعلام کنید.
• می توانید فایل myscript.spec را ویرایش کنید که PyInstaller اولین باری که آن را برای اسکریپت خود اجرا می کنید می نویسد. در فایل spec، میتوانید به PyInstaller درباره ماژولهای کدی که مختص اسکریپت شما هستند، بگویید.
• می توانید فایل های “hook” بنویسید که PyInstaller را از import های پنهان مطلع می کند. اگر یک “hook” برای بسته ای ایجاد می کنید که سایر کاربران نیز ممکن است از آن استفاده کنند، می توانید فایل hook خود را به PyInstaller اضافه کنید.
اگر برنامه شما به دسترسی به فایل های داده خاصی بستگی دارد، می توانید به PyInstaller بگویید که آنها را نیز در بسته قرار دهد. شما این کار را با تغییر فایل spec انجام می دهید.
برای یافتن فایلهای موجود در زمان اجرا، برنامه شما باید بتواند مسیر خود را در زمان اجرا به گونهای بیاموزد که بدون در نظر گرفتن اینکه آیا از یک بسته اجرا میشود یا نه.
بستهبندی داخل یک فولدر
وقتی PyInstaller را روی myscript.py اعمال میکنید، نتیجه پیشفرض یک پوشه به نام myscript است. این پوشه حاوی تمام Dependency های اسکریپت شما و یک فایل اجرایی با نام myscript.exe است.
شما پوشه را با نام myscript.zip فشرده کرده و به کاربران خود ارسال می کنید. آنها برنامه را به سادگی با خارج کردن آن از حالت فشرده نصب می کنند. یک کاربر برنامه شما را با باز کردن پوشه و راه اندازی فایل اجرایی myscript در داخل آن اجرا می کند.
دیباگ کردن مشکلاتی که در هنگام ساختن برنامه هنگام استفاده از حالت تک پوشه ای ( one-folder ) رخ می دهد، آسان است. دقیقاً می توانید ببینید PyInstaller چه فایل هایی را در پوشه جمع آوری کرده است.
یکی دیگر از مزایای یک بسته one-folder این است که وقتی کد خود را تغییر می دهید، تا زمانی که دقیقاً همان مجموعه Dependency ها را import می کنید، می توانید فقط فایل اجرایی myscript به روز شده را به کاربران ارسال کنید. که معمولاً بسیار کوچکتر از کل پوشه است. اگر اسکریپت را طوری تغییر دهید که Dependency های بیشتری یا متفاوت import کند، یا اگر Dependency ها ارتقا یافته باشند، باید کل بسته را دوباره توزیع کنید.
یک عیب کوچک حالت one-folder این است که یک پوشه حاوی تعداد زیادی فایل است. کاربر شما باید فایل اجرایی myscript را در یک لیست طولانی از نام ها یا در میان آرایه بزرگی از نمادها پیدا کند. همچنین کاربر شما می تواند با کشیدن تصادفی فایل ها به خارج از پوشه مشکل ایجاد کند.
برنامه تک پوشه ای ( one-folder ) چگونه کار می کند
یک برنامه بسته بندی شده همیشه را در بوت لودر PyInstaller شروع به اجرا می کند. این قلب فایل اجرایی myscript.exe داخل پوشه است.
بوت لودر PyInstaller یک برنامه اجرایی باینری برای پلتفرم فعال (ویندوز، لینوکس، Mac OS X و غیره) است.
هنگامی که کاربر برنامه شما را راه اندازی می کند، این بوت لودر است که اجرا می شود. بوت لودر یک محیط پایتون موقت ایجاد می کند به طوری که مفسر پایتون تمام ماژول ها و کتابخانه های وارد شده را در پوشه myscript پیدا می کند. بوت لودر یک کپی از مفسر پایتون را برای اجرای اسکریپت شما شروع می کند. همه چیز به طور معمول از آنجا دنبال می شود، مشروط بر اینکه تمام فایل های پشتیبانی لازم گنجانده شده باشد.
بسته بندی درون یک فایل
PyInstaller می تواند اسکریپت شما و تمام Dependency های آن را در یک فایل اجرایی به نام myscript.exe بسته بندی کند.
مزیت حالت تک فایلی one-file این است که کاربران شما چیزی را دریافت می کنند که برایشان قابل درک است، یک فایل اجرایی برای راه اندازی. یک نقطه ضعف این روش این است که هر فایل مرتبط مانند README باید به طور جداگانه توزیع شود. همچنین، اجرای one-file نسبت به بسته نرم افزاری one-folder کمی کندتر انجام می شود.
قبل از اینکه بخواهید برنامه تان را در یک فایل بسته بندی کنید، مطمئن شوید که برنامه شما در حالت تک پوشه به درستی کار می کند. تشخیص مشکلات در حالت تک پوشه بسیار ساده تر است.
برنامه تک فایل ( one-file ) چگونه کار می کند
بوت لودر قلب بسته تک فایل نیز هست. هنگامی که شروع می شود، یک پوشه موقت در محل temp-folder سیستم عامل ایجاد می کند. نام پوشه _MEIxxxxxx است که xxxxxx یک عدد تصادفی است.
یک فایل اجرایی شامل یک آرشیو جاسازی شده از همه ماژول های پایتون مورد استفاده توسط اسکریپت شما است و همچنین کپی های فشرده شده از هر فایلی که پایتون پشتیبانی نمی کند. بوت لودر فایل های پشتیبانی را از حالت فشرده خارج می کند و کپی ها را در پوشه موقت می نویسد. این کار ممکن است کمی طول بکشد. به همین دلیل است که شروع یک برنامه تک فایل کمی کندتر از یک برنامه تک پوشه است.
پس از ایجاد پوشه موقت، بوت لودر دقیقاً مانند بسته تک پوشه، در زمینه پوشه موقت پیش می رود. هنگامی که اجرای کد بسته بندی شده پایان می یابد، بوت لودر پوشه موقت را حذف می کند.
از آنجایی که برنامه یک پوشه موقت با یک نام منحصر به فرد ایجاد می کند، می توانید چندین نسخه از برنامه را اجرا کنید. آنها با یکدیگر تداخل نخواهند کرد با این حال، اجرای چند نسخه در فضای دیسک پرهزینه است زیرا هیچ چیز به اشتراک گذاشته نمی شود.
در صورت خراب شدن یا از بین رفتن برنامه، پوشه _MEIxxxxxx حذف نمیشود. بنابراین اگر برنامه شما مکرراً خراب شود، کاربران فضای دیسک اختصاص داده شده به پوشه های موقت _MEIxxxxxx را از دست خواهند داد.
مخفی کردن Source Code
برنامه بسته بندی شده هیچ کد منبعی را شامل نمی شود. با این حال، بستههای PyInstaller اسکریپتهای پایتون (فایلهای pyc.) را کامپایل کردند. اینها در اصل می توانند برای آشکار کردن منطق کد شما دیکامپایل شوند.
اگر می خواهید کد منبع خود را به طور کامل مخفی کنید، یکی از گزینه های ممکن این است که برخی از ماژول های خود را با Cython کامپایل کنید. با استفاده از Cython می توانید ماژول های پایتون را به C تبدیل کنید و C را به زبان ماشین کامپایل کنید. PyInstaller می تواند عبارات وارداتی را که به ماژول های شی Cython C اشاره می کنند دنبال کند و آنها را بسته بندی کند.
علاوه بر این، بایت کد پایتون را می توان با تعیین یک کلید رمزگذاری در خط فرمان PyInstaller با AES256 مبهم کرد. لطفاً توجه داشته باشید که استخراج کلید و بازگرداندن بایت کد اصلی هنوز بسیار آسان است، اما باید از اکثر حالت های دستکاری «اتفاقی» جلوگیری کند.
استفاده از PyInstaller
سینتکس دستور pyinstaller به صورت زیر است:
pyinstaller [options] script [script ...] | specfile
در ساده ترین حالت، دایرکتوری فعلی را در محل برنامه myscript.py تنظیم کرده و این دستور را اجرا کنید:
pyinstaller myscript.py
PyInstaller برنامه myscript.py را تجزیه و تحلیل می کند و:
• myscript.spec را در همان پوشه اسکریپت می نویسد.
• در صورتی که پوشه build وجود نداشته باشد، این پوشه را در همان پوشه اسکریپت ایجاد می کند.
• تعدادی فایل گزارش و فایل های کاری را در پوشه build می نویسد.
• در صورت عدم وجود پوشه dist آن را در همان پوشه اسکریپت ایجاد می کند.
• پوشه اجرایی myscript را در پوشه dist می نویسد.
در پوشه dist، برنامه بسته بندی شده ای را که بین کاربران خود توزیع می کنید، خواهید یافت.
معمولاً فقط یک اسکریپت را در خط فرمان نام می برید. اگر بیشتر نام ببرید، همه آنالیز شده و در خروجی گنجانده شده است.
در این صورت اولین اسکریپت نامگذاری شده، نام فایل مشخصات و پوشه یا فایل اجرایی را مشخص میکند. این کد اولین کدی است که در run-time اجرا می شود.
برای استفاده های خاص می توانید محتویات myscript.spec را ویرایش کنید. پس از انجام این کار، به جای اسکریپت، نام فایل spec را به PyInstaller میدهید:
pyinstaller myscript.spec
یا می توانید به فایل اسکریپت یا مشخصات یک مسیر بدهید:
pyinstaller "C:\Documents and Settings\project\myscript.spec"
گزینه ها
گزینه های کلی
-h, --help
راهنما را نشان می دهد و خارج می شود.
-v, --version
اطلاعات نسخه برنامه را نمایش می دهد و خارج می شود.
--distpath DIR
محل قرار دادن برنامه بسته بندی شده (پیشفرض:./dist )
--workpath WORKPATH
محل قرار دادن همه فایلهای کاری موقت، .log، .pyz و غیره (پیشفرض: ./build)
-y, --noconfirm
دایرکتوری خروجی را بدون درخواست تأیید جایگزین می کند . (پیشفرض: SPECPATH/dist/SPECNAME)
--upx-dir UPX_DIR
مسیر ابزار UPX (پیشفرض: جستجوی مسیر اجرا)
-a, --ascii
پشتیبانی از رمزگذاری یونیکد را شامل نشود (پیشفرض: در صورت موجود بودن گنجانده شده است)
--clean
کش PyInstaller را پاک و فایل های موقت را قبل از ساختن حذف می کند.
--log-level LEVEL
مقدار جزئیات در پیام های کنسول زمان ساخت. LEVEL ممکن است یکی از این موارد باشد: TRACE، DEBUG، INFO، WARN، ERROR، CRITICAL (پیشفرض: INFO).
چه چیزی تولید شود
-D, --onedir
ایجاد یک بسته تک پوشه ( one-folder ) حاوی یک فایل اجرایی (پیشفرض)
-F, --onefile
یک فایل اجرایی بسته بندی شده تک فایل ( one-file ) ایجاد شود.
--specpath DIR
پوشه ای برای ذخیره فایل مشخصات تولید شده (پیش فرض: دایرکتوری فعلی)
-n NAME, --name NAME
اختصاص دادن نام به برنامه بسته بندی شده و فایل spec (پیشفرض: نام اولین اسکریپت)
چه چیزی را بسته بندی کند، کجا را جستجو کند
--add-data <SRC;DEST or SRC:DEST>
فایل ها یا پوشه های غیر باینری اضافی که باید به فایل اجرایی اضافه شوند. این گزینه را می توان چندین بار استفاده کرد.
--add-binary <SRC;DEST or SRC:DEST>
فایل های باینری اضافی که به فایل اجرایی اضافه می شوند. برای جزئیات بیشتر به گزینه –add-data مراجعه کنید. این گزینه را می توان چندین بار استفاده کرد.
-p DIR, --paths DIR
مسیر جستجوی import ها (مانند استفاده از PYTHONPATH). مشخص کردن چند مسیر هم مجاز هست، با “:” از هم جدا کنید، یا چندین بار از این گزینه استفاده کنید.
--hidden-import MODULENAME, --hiddenimport MODULENAME
مشخص کردن نام Import هایی که در کد اسکریپت(ها) قابل مشاهده نیست. این گزینه را نیز می توان چندین بار استفاده کرد.
--additional-hooks-dir HOOKSPATH
یک مسیر اضافی برای جستجوی هوک. این گزینه را می توان چندین بار استفاده کرد.
--runtime-hook RUNTIME_HOOKS
مسیر یک فایل هوک سفارشی run-time. هوک run-time کدی است که با فایل اجرایی همراه است و قبل از هر کد یا ماژول دیگری اجرا می شود تا ویژگی های ویژه محیط اجرا را تنظیم کند. این گزینه را می توان چندین بار استفاده کرد.
--exclude-module EXCLUDES
ماژول یا بسته اختیاری (نام پایتون، نه نام مسیر) که می خواهیم نادیده گرفته شود (گویا پیدا نشده است). این گزینه را می توان چندین بار استفاده کرد.
--key KEY
کلیدی که برای رمزگذاری بایت کد پایتون استفاده می شود.
نحوه تولید
-d, --debug
به بوت لودر می گوید که هنگام راهاندازی اولیه و شروع برنامه بسته بندی شده، پیامهای پیشرفت را صادر کند. برای تشخیص مشکلات مربوط به import های گم شده استفاده می شود.
--noupx
از UPX حتی اگر در دسترس است استفاده نمی کند.
گزینه های خاص Windows
-c, --console, --nowindowed
یک پنجره کنسول برای i/o استاندارد باز می کند. (پیشفرض)
-w, --windowed, --noconsole
سیستم عامل پنجره کنسولی برای i/o استاندارد ارائه نمی کند.
-i <FILE.ico or FILE.exe,ID or FILE.icns>, --icon <FILE.ico or FILE.exe,ID or FILE.icns>
FILE.ico: این آیکون را روی یک فایل اجرایی ویندوز اعمال می کند. FILE.exe، ID، آیکون را با ID از یک exe استخراج می کند.
مثال
ابتدا مسیر را به محل جاری اسکریپت تغییر می دهیم:
cd "D:\Python tutorial\exe"
تک فولدر
pyinstaller exetest1.py
یا
pyinstaller --onedir exetest1.py
تک فایل
pyinstaller --onefile exetest1.py
تعیین محل ایجاد فایل مشخصات:
pyinstaller --workpath "D:\Python tutorial\exe\test" exetest1.py
تعیین نام فایل اجرایی
pyinstaller --name KARAKIT exetest1.py
پاک کردن کش و فایلهای موقت قبل از بسته بندی مجدد برنامه
pyinstaller --clean exetest1.py
تعیین آیکون برای برنامه اجرایی
pyinstaller --icon "D:\Python tutorial\exe\myicon.ico" -F exetest1.py
ساخت فایل اجرایی پنجره ای بدون باز شدن صفحه کنسول
pyinstaller -w exetest2.py
ایجاد فایل اجرایی با تعیین آیکون برنامه و آیکون پنجره
pyinstaller -w --add-data "D:\Python tutorial\exe\logo2.png;." --icon "D:\Python tutorial\exe\logo2.ico" --clean exetest1.py
در دستور add-data لازم است بعد از مشخص کردن مسیر فایل یک علامت ; قرار دهیم و بعد نام فولدری که قرار است این فایل در آنجا قرار بگیرد را تعیین کنیم. اما اگر بخواهیم در همان فولدر dist قرار بگیرد از . به جای نام فولدر استفاده می کنیم.