یکی از مشکلاتی که کاربران زبان برنامه نویسی پایتون با آن مواجه هستند این است که وقتی کدنویسی به پایان می رسد باید بتوانند محصول نهایی را به صورت فایلی اجرایی در بیاورند که کاربران بدون نیاز به نصب پایتون از آن استفاده کنند. یکی از راههای متداول استفاده از 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 قرار بگیرد از . به جای نام فولدر استفاده می کنیم.