zipapp --- مدیریت بایگانیهای zip قابلاجرای پایتون¶
اضافه شده در نسخهی 3.5.
کد منبع: Lib/zipapp.py
این ماژول ابزارهایی را برای مدیریت ایجاد پروندههای zip حاوی کد پایتون فراهم میکند، که میتوانند بهطور مستقیم توسط مفسر پایتون اجرا شوند. این ماژول هم یک رابط خط فرمان و هم یک API پایتون را فراهم میکند.
مثال ساده¶
مثال زیر نشان میدهد که چگونه میتوان از رابط خط فرمان برای ایجاد یک بایگانی قابل اجرا از یک پوشه حاوی کد پایتون استفاده کرد. هنگام اجرا، بایگانی تابع main را از ماژول myapp درون بایگانی اجرا میکند.
$ python -m zipapp myapp -m "myapp:main"
$ python myapp.pyz
<output from myapp>
رابط خط فرمان¶
هنگام فراخوانی بهعنوان یک برنامه از خط فرمان، از قالب زیر استفاده میشود:
$ python -m zipapp source [options]
اگر source یک پوشه باشد، این کار یک بایگانی از محتویات source ایجاد میکند. اگر source یک پرونده باشد، باید یک بایگانی باشد، و به بایگانی مقصد کپی میشود (یا محتویات خط shebang آن در صورتی که گزینه --info مشخص شده باشد نمایش داده میشود).
گزینههای زیر قابلدرک هستند:
- -o <output>, --output=<output>¶
خروجی را در پروندهای به نام output بنویسید. اگر این گزینه مشخص نشده باشد، نام پرونده خروجی همان نام ورودی source خواهد بود و پسوند
.pyzبه آن افزوده میشود. اگر نام پرونده صریحی داده شود، همانطور که هست استفاده میشود (بنابراین در صورت نیاز، باید پسوند.pyzلحاظ شود).اگر source یک بایگانی باشد، باید نام پرونده خروجی مشخص شود (و در این حالت، output نباید با source یکسان باشد).
- -p <interpreter>, --python=<interpreter>¶
یک خط
#!به بایگانی اضافه کنید که interpreter را بهعنوان دستور برای اجرا مشخص میکند. همچنین، در POSIX، بایگانی را قابلاجرا کنید. پیشفرض این است که هیچ خط#!نوشته نشود و پرونده قابلاجرا نشود.
- -m <mainfn>, --main=<mainfn>¶
یک پرونده
__main__.pyدر بایگانی بنویسید که mainfn را اجرا میکند. آرگومان mainfn باید به قالب "pkg.mod:fn" باشد، که در آن "pkg.mod" یک بسته/ماژول در بایگانی است، و "fn" یک شیء فراخوانیپذیر در ماژول دادهشده است. پرونده__main__.pyآن شیء فراخوانیپذیر را اجرا خواهد کرد.هنگام کپی کردن یک بایگانی نمیتوان
--mainرا مشخص کرد.
- -c, --compress¶
فشردهسازی پروندهها با متد deflate، که اندازهی پرونده خروجی را کاهش میدهد. بهطور پیشفرض، پروندهها بهصورت فشردهنشده در آرشیو ذخیره میشوند.
--compressهنگام کپی کردن یک بایگانی هیچ تأثیری ندارد.اضافه شده در نسخهی 3.7.
- --info¶
مفسر تعبیهشده در بایگانی را برای اهداف تشخیصی نمایش میدهد. در این حالت، تمام گزینههای دیگر نادیده گرفته میشوند و SOURCE باید یک بایگانی باشد، نه یک پوشه.
- -h, --help¶
یک پیام کوتاه کاربرد را چاپ میکند و خارج میشود.
API پایتون¶
این ماژول دو تابع سهولتبخش تعریف میکند:
- zipapp.create_archive(source, target=None, interpreter=None, main=None, filter=None, compressed=False)¶
یک بایگانی برنامه از source ایجاد کنید. منبع میتواند هر یک از موارد زیر باشد:
نام یک پوشه، یا یک path-like object که به یک پوشه اشاره میکند؛ در این صورت یک آرشیو برنامهی جدید از محتوای آن پوشه ایجاد خواهد شد.
نام یک پرونده آرشیو برنامه موجود، یا یک path-like object که به چنین پروندهای اشاره دارد؛ در این صورت پرونده به مقصد کپی میشود (و بهگونهای تغییر داده میشود که مقدار دادهشده برای آرگومان interpreter را بازتاب دهد). نام پرونده باید در صورت لزوم شامل پسوند
.pyzباشد.یک شیء پرونده که برای خواندن در حالت بایت باز شده است. محتوای پرونده باید یک بایگانی برنامه باشد، و فرض میشود شیء پرونده در ابتدای بایگانی قرار دارد.
آرگومان target تعیین میکند که بایگانی حاصل کجا نوشته خواهد شد:
اگر نام یک پرونده یا یک path-like object باشد، بایگانی در آن پرونده نوشته خواهد شد.
اگر یک شیء پرونده باز باشد، بایگانی در آن شیء پرونده نوشته خواهد شد؛ این شیء باید برای نوشتن در حالت بایت باز باشد.
اگر مقصد حذف شود (یا
Noneباشد)، منبع باید یک پوشه باشد و مقصد پروندهای با همان نام منبع خواهد بود که پسوند.pyzبه آن افزوده میشود.
آرگومان interpreter نام مفسر پایتون را مشخص میکند که بایگانی با آن اجرا خواهد شد. این مقدار بهصورت یک خط «shebang» در ابتدای بایگانی نوشته میشود. در POSIX، این خط توسط سیستمعامل تفسیر خواهد شد و در ویندوز توسط راهانداز پایتون مدیریت خواهد شد. حذف interpreter منجر به نوشته نشدن هیچ خط «shebang» میشود. اگر مفسری مشخص شده باشد و مقصد یک نام پرونده باشد، بیت اجرایی (executable bit) پرونده مقصد تنظیم خواهد شد.
آرگومان main نام یک شیء فراخوانیپذیر را مشخص میکند که بهعنوان برنامه اصلی بایگانی استفاده خواهد شد. این آرگومان فقط زمانی میتواند مشخص شود که منبع یک پوشه باشد و منبع از قبل حاوی پرونده
__main__.pyنباشد. آرگومان main باید بهشکل "pkg.module:callable" باشد و بایگانی با ایمپورت کردن "pkg.module" و اجرای شیء فراخوانیپذیر دادهشده بدون آرگومان اجرا خواهد شد. اگر منبع یک پوشه باشد و حاوی پرونده__main__.pyنباشد، مشخص نکردن main خطا است، زیرا در غیر این صورت بایگانی حاصل قابل اجرا نخواهد بود.آرگومان اختیاری filter یک تابع کالبک را مشخص میکند که یک شیء Path به آن داده میشود؛ این شیء مسیر پرونده در حال اضافه شدن (نسبت به پوشه منبع) را نشان میدهد. این تابع باید در صورتی که پرونده قرار است اضافه شود،
Trueرا برگرداند.آرگومان اختیاری compressed مشخص میکند که پروندهها فشرده شوند یا خیر. اگر روی
Trueتنظیم شود، پروندههای درون بایگانی با روش deflate فشرده میشوند؛ در غیر این صورت، پروندهها بهصورت غیرفشرده ذخیره میشوند. این آرگومان هنگام کپی کردن یک بایگانی موجود تأثیری ندارد.اگر برای source یا target یک شیء پرونده مشخصشده باشد، مسئولیت بستن آن پس از فراخوانی create_archive با فراخواننده است.
هنگام کپی کردن یک بایگانی موجود، اشیای پرونده ارائهشده فقط به متدهای
readوreadlineیاwriteنیاز دارند. هنگام ایجاد یک بایگانی از یک پوشه، اگر مقصد یک شیء پرونده باشد، به کلاسzipfile.ZipFileداده میشود و باید متدهای مورد نیاز آن کلاس را فراهم کند.تغییر یافته در نسخهی 3.7: پارامترهای filter و compressed افزوده شدند.
مثالها¶
یک پوشه را در قالب یک بایگانی بستهبندی کنید و آن را اجرا کنید.
$ python -m zipapp myapp
$ python myapp.pyz
<output from myapp>
همین کار را میتوان با استفاده از تابع create_archive() انجام داد:
>>> import zipapp
>>> zipapp.create_archive('myapp', 'myapp.pyz')
برای قابلاجرا کردن مستقیم برنامه روی POSIX، یک مفسر برای استفاده مشخص کنید.
$ python -m zipapp myapp -p "/usr/bin/env python"
$ ./myapp.pyz
<output from myapp>
برای جایگزینی خط shebang در یک بایگانی موجود، یک بایگانی اصلاحشده را با استفاده از تابع create_archive() ایجاد کنید:
>>> import zipapp
>>> zipapp.create_archive('old_archive.pyz', 'new_archive.pyz', '/usr/bin/python3')
برای بهروزرسانی پرونده بهصورت درجا، جایگزینی را در حافظه با استفاده از یک شیء BytesIO انجام دهید و سپس منبع را بازنویسی کنید. توجه داشته باشید که هنگام بازنویسی یک پرونده بهصورت درجا، این خطر وجود دارد که یک خطا باعث از دست رفتن پرونده اصلی شود. این کد در برابر چنین خطاهایی محافظت نمیکند، اما کد تولیدی باید این کار را انجام دهد. همچنین، این روش تنها در صورتی کار میکند که آرشیو در حافظه جا شود:
>>> import zipapp
>>> import io
>>> temp = io.BytesIO()
>>> zipapp.create_archive('myapp.pyz', temp, '/usr/bin/python2')
>>> with open('myapp.pyz', 'wb') as f:
>>> f.write(temp.getvalue())
تعیین مفسر¶
توجه داشته باشید که اگر مفسری را مشخص کنید و سپس آرشیو برنامهی خود را توزیع کنید، باید اطمینان حاصل کنید که مفسر استفادهشده قابل حمل است. راهانداز پایتون برای ویندوز از رایجترین شکلهای خط #! POSIX پشتیبانی میکند، اما مسائل دیگری نیز وجود دارند که باید آنها را در نظر بگیرید:
اگر از "/usr/bin/env python" (یا سایر شکلهای دستور "python"، مانند "/usr/bin/python") استفاده میکنید، باید در نظر داشته باشید که کاربران شما ممکن است پایتون 2 یا پایتون 3 را بهعنوان پیشفرض خود داشته باشند و کد خود را بهگونهای بنویسید که تحت هر دو نسخه کار کند.
اگر از یک نسخه مشخص استفاده کنید، برای مثال "/usr/bin/env python3"، برنامه شما برای کاربرانی که آن نسخه را ندارند کار نخواهد کرد. (اگر کد خود را با Python 2 سازگار نکردهاید، ممکن است همین چیزی باشد که میخواهید).
راهی برای بیان "python X.Y or later" وجود ندارد، بنابراین در استفاده از یک نسخهی دقیق مانند "/usr/bin/env python3.4" احتیاط کنید، زیرا برای مثال برای کاربران Python 3.5 ناچار خواهید بود خط shebang خود را تغییر دهید.
معمولاً باید از "/usr/bin/env python2" یا "/usr/bin/env python3" استفاده کنید، بسته به اینکه کد شما برای پایتون 2 نوشته شده باشد یا 3.
ایجاد برنامههای مستقل با zipapp¶
با استفاده از ماژول zipapp، میتوان برنامههای پایتون خودکفا ایجاد کرد که قابل توزیع بین کاربران نهایی هستند؛ این کاربران تنها نیاز دارند نسخه مناسبی از پایتون روی سیستم خود نصب باشد. کلید این کار قرار دادن همه وابستگیهای برنامه به همراه کد برنامه در بایگانی است.
مراحل ساخت یک بایگانی مستقل به شرح زیر است:
برنامه خود را مانند حالت عادی در یک پوشه ایجاد کنید، بهگونهای که یک پوشه
myappداشته باشید که شامل یک پرونده__main__.pyو هر کد پشتیبان برنامه باشد.تمام وابستگیهای برنامه شما را با استفاده از pip در پوشه
myappنصب کنید:$ python -m pip install -r requirements.txt --target myapp
(این فرض بر این است که نیازمندیهای پروژه شما در یک پرونده
requirements.txtقرار دارد؛ در غیر این صورت، میتوانید صرفاً وابستگیها را بهصورت دستی در خط فرمان pip فهرست کنید).بستهبندی برنامه با استفاده از:
$ python -m zipapp -p "interpreter" myapp
این کار یک پرونده اجرایی مستقل تولید میکند که میتوان آن را روی هر ماشینی که مفسر مناسب در دسترس باشد اجرا کرد. برای جزئیات، تعیین مفسر را ببینید. میتوان آن را بهصورت یک پرونده واحد به کاربران تحویل داد.
در یونیکس، پرونده myapp.pyz بههمین شکل قابل اجرا است. اگر نام فرمان «ساده» را ترجیح میدهید، میتوانید نام پرونده را تغییر دهید تا پسوند .pyz حذف شود. در ویندوز، پرونده myapp.pyz[w] به این دلیل قابل اجرا است که مفسر پایتون هنگام نصب، پسوندهای پرونده .pyz و .pyzw را ثبت میکند.
نکات مهم¶
اگر برنامه شما به بستهای وابسته است که شامل یک افزونه C است، آن بسته نمیتواند از یک پرونده zip اجرا شود (این یک محدودیت سیستمعامل است، زیرا کد اجرایی باید در سامانه فایلبندی موجود باشد تا بارگذار سیستمعامل بتواند آن را بارگذاری کند). در این صورت، میتوانید آن وابستگی را از پرونده zip خارج کنید و یا از کاربران خود بخواهید آن را نصب کرده باشند، یا آن را همراه پرونده zip خود توزیع کنید و کدی به __main__.py خود اضافه کنید تا پوشهی حاوی ماژول از حالت فشرده خارجشده را در sys.path قرار دهد. در این صورت، باید اطمینان حاصل کنید که دودوییهای مناسب (binaries) برای معماری(های) هدف خود را توزیع میکنید (و در صورت لزوم، نسخه صحیح را برای افزودن به sys.path در زمان رانتایم، بر اساس ماشین کاربر انتخاب کنید).
قالب بایگانی برنامهی Zip پایتون¶
پایتون از نسخه 2.6 قادر به اجرای پروندههای zip حاوی یک پرونده __main__.py بوده است. برای اجرا شدن توسط پایتون، یک بایگانی برنامه صرفاً باید یک پرونده zip استاندارد حاوی یک پرونده __main__.py باشد که بهعنوان نقطه ورود برنامه اجرا خواهد شد. همانطور که برای هر اسکریپت پایتون معمول است، والد اسکریپت (در این مورد پرونده zip) در sys.path قرار میگیرد و بنابراین میتوان ماژولهای بیشتری را از پرونده zip ایمپورت کرد.
قالب پرونده zip اجازه میدهد دادههای دلخواه به ابتدای یک پرونده zip اضافه شوند. قالب برنامه zip از این قابلیت برای افزودن یک خط «shebang» استاندارد POSIX به ابتدای پرونده استفاده میکند (#!/path/to/interpreter).
بنابراین، قالب برنامهی zip پایتون بهطور رسمی عبارت است از:
یک خط shebang اختیاری، شامل نویسههای
b'#!'است که پس از آنها نام مفسر و سپس یک نویسهی خط جدید (b'\n') میآید. نام مفسر میتواند هر چیزی باشد که برای پردازش «shebang» سیستمعامل یا راهانداز پایتون در ویندوز قابلقبول باشد. نام مفسر باید در ویندوز با UTF-8 و در POSIX باsys.getfilesystemencoding()کدگذاری شود.دادههای استاندارد zipfile، همانطور که توسط ماژول
zipfileتولید میشوند. محتوای zipfile باید شامل پروندهای به نام__main__.pyباشد (که باید در «ریشه» zipfile باشد - یعنی نمیتواند در یک زیرپوشه باشد). دادههای zipfile میتوانند فشرده یا غیرفشرده باشند.
اگر یک آرشیو برنامه دارای خط shebang باشد، ممکن است بیت اجرایی آن در سیستمهای POSIX تنظیم شده باشد تا بتوان آن را مستقیماً اجرا کرد.
هیچ الزامی وجود ندارد که ابزارهای این ماژول برای ایجاد بایگانیهای برنامه استفاده شوند - این ماژول برای سهولت است، اما بایگانیهای برنامه در قالب بالا که به هر وسیلهای ایجاد شده باشند، برای پایتون قابلقبول هستند.