ساخت پروژه متن باز پایتون — راهنمای کاربردی
هر فرد توسعهدهنده نرمافزار و دانشمند داده باید تمرین ایجاد یک بسته نرمافزاری را تجربه کند، چون در این مسیر موارد زیادی را خواهد آموخت. ایجاد یک پروژه اوپن سورس پایتون ممکن است کار دشواری به نظر برسد؛ اما لازم نیست یک قهرمان باشید. همچنین حتی لازم نیست که ایده یک محصول عالی را در ذهن خود بپرورانید. شما صرفاً باید صبور باشید و زمان خود را صرف کنید. البته با مطالعه این راهنما این دو ضرورت نیز رفع میشوند.
در این مقاله به صورت گام به گام یک بسته ابتدایی پایتون میسازیم. در مقالات بعدی در این زمینه نیز اقدام به راهاندازی تستهای خودکار و ساخت doc-های خودکار میکنیم. همچنین اپلیکیشنهای مفید دیگری را برای بهبود توسعه بستهها مورد استفاده قرار میدهیم. در این زمان میتوانید آن چه را که آموختهاید برای رفع نیازهایتان مورد بهرهبرداری قرار دهید.
این راهنما برای سیستم macOS و پایتون نسخه 3.7 نوشته شده است. همه مواردی که در این مقاله نوشته شدهاند در زمان نگارش آن کار میکردهاند؛ اما همه چیز به سرعت در حال تغییر است و هیچ تضمینی نیست که اگر چند سال دیگر این راهنما را بخوانید و یا حتی مواردی مانند my_package یا my_file را با نامهای خودتان عوض کنید، همچنان کار کنند. بنابراین در این مورد هوشیار باشید.
گام اول: طرح یک نقشه
تصور کنید ما قصد داریم یک کتابخانه ساده برای استفاده در برنامههای پایتون بسازیم. این بسته به کاربر امکان میدهد که به سادگی یک ژوپیتر نتبوک را به یک فایل HTML یا اسکریپت پایتون تبدیل کند.
نخستین متد بسته ما به کاربر امکان میدهد که تابعی را فراخوانی کند و یک گزاره را نمایش دهد. اینک که میدانیم چه چیزی را میخواهیم بسازیم، باید تصمیم بگیریم که بسته خود را چه بنامیم.
گام دوم: نامگذاری بسته
نامگذاری به طور کلی کار پیچیدهای است. نامها باید منحصربهفرد و کوتاه بوده و قابلیت به خاطر سپردن داشته باشند. همچنین باید کلاً با حروف کوچک نوشته شوند و هرگز از خط تیره یا دیگر علائم سجاوندی در آنها استفاده نشده باشد. استفاده از زیرخط نیز توصیه نمیشود. پیش از نامگذاری بسته خود مطمئن شوید که این نام روی گوگل، گیتهاب و PyPI موجود است یا نه.
اگر امید زیادی دارید که بسته شما روزی به 10،000 ستاره گیتهاب برسد، در این صورت باید نام مورد نظر خود را در شبکههای اجتماعی نیز بررسی کنید. در این مثال ما بسته خود را notebookc مینامیم زیرا هم موجود است، و هم کوتاه و تقریباً گویا است!
گام سوم: پیکربندی محیط
اطمینان حاصل کنید که پایتون نسخه 3.7، گیتهاب و Homebrew روی سیستمتان نصب و پیکربندی شدهاند. اگر به هر کدام از این موارد نیاز دارید جزییات آنها چنین است:
پایتون
پایتون نسخه 3.7 را از این لینک (+) دانلود و نصب کنید.
گیتهاب
اگر حساب کاربری گیتهاب ندارید، به این لینک (+) بروید و یک حساب کاربری رایگان بسازید. روش نصب و پیکربندی گیت را نیز میتوانید در این صفحه (+) مشاهده کنید. شما به ابزار خط فرمان هم نیاز دارید و میتوانید با لینکهای مربوطه، آن را دانلود و نصب کنید. نام کاربری خود را تعیین کنید و آدرس ایمیل کامیتتان را نیز وارد نمایید.
Homebrew
Homebrew یک ابزار مدیریت بسته خاص Mac است و روش نصب آن را میتوانید در این لینک (+) ملاحظه کنید.
venv
از نسخه 3.6 پایتون به بعد توصیه شده است که برای ایجاد محیطهای مجازی برای توسعه بسته از venv (+) استفاده کنید. روشهای زیادی برای مدیریت محیطهای مجازی در پایتون وجود دارند و پیشنهادها در این خصوص به طور مدام در حال تکامل هستند.
venv از نسخه 3.3 پایتون به بعد همراه با آن روی سیستم نصب میشود. دقت کنید که venv از نسخه 3.4 به بعد اقدام به نصب pip و setuptools در محیط مجازی میکند.
یک محیط مجازی پایتون 3.7 را با اجرای دستور زیر بسازید:
python3.7 -m venv my_env
نام my_env را با هر نامی که دوست دارید عوض کنید. در ادامه محیط مجازی خود را با دستور زیر فعال کنید:
source my_env/bin/activate
اینک میتوانید محیط my_env یا هر نام دیگری که برای آن انتخاب کردید را در سمت چپ اعلان ترمینال مشاهده کنید. زمانی که کار توسعهتان به پایان رسید، میتوانید این محیط مجازی را با دستور deactivate غیرفعال کنید. در ادامه به بررسی روش راهاندازی موارد مختلف روی گیتهاب میپردازیم.
گام چهارم: ایجاد سازمان روی گیتهاب
گیتهاب یکی از پلتفرمهای پیشرو در زمینه سیستمهای کنترل نسخه محسوب میشود. GitLab و Bitbucket نیز جزو گزینههای محبوب به حساب میآیند. ما در این راهنما از گیتهاب استفاده خواهیم کرد.
در این نوشته به طور مکرر با گیت و گیتهاب سروکار داریم، بنابراین اگر با آنها آشنا نیستید، توصیه میکنیم با استفاده از مطالب زیر بر غنای دانش خود در این زمینه بیفزایید:
- آموزش گیت (Git) برای مدیریت نسخه توزیعشده
- 1۰ ویژگی کاربردی گیتهاب (GitHub) که باید آنها را بدانید — راهنمای کاربردی
یک «سازمان» (organization) جدید روی گیتهاب ایجاد کنید. ما با طی مراحل مختلف نام سازمان خود را notebooktoall گذاشتیم. شما باید ریپازیتوری مورد نظر را زیر حساب کاربری خودتان ایجاد کنید؛ اما بخشی از هدف ما آشنایی با روش راهاندازی یک پروژه اوپنسورس برای جامعه بزرگتر است.
گام پنجم: راهاندازی ریپازیتوری گیتهاب
یک ریپازیتوری جدید بسازید. ما نام ریپازیتوری خود را notebookc گذاشتیم.
یک فایل gitignore. به انتهای لیست اضافه کنید. از ریپازیتوری خودتان گزینه Python را انتخاب کنید. محتوای فایل gitignore. با برخی انواع فایلها و پوشهها مطابقت مییابد تا آنها را از ریپازیتوری گیت حذف کند. شما میتوانید در ادامه محتوای gitignore. را تغییر دهید تا فایلهای حساس یا غیر ضروری وارد ریپوی شما نشوند.
پیشنهاد میکنیم از منوی بازشدنی Add a license یک مجوز نیز برای پروژه خود انتخاب کنید. این مجوز تعیین میکند که کاربران میتوانند چه کارهایی با ریپازیتوری شما انجام دهند. برخی مجوزها آزادی عمل بیشتری به کاربران میدهند. در صورتی که هیچ مجوزی انتخاب نکنید؛ قوانین پیشفرض کپیرایت اعمال خواهد شد. در مورد این مجوز در این صفحه (+) بیشتر بخوانید.
برای این پروژه ما از مجوز GNU General Public نسخه 3.0 استفاده میکنیم، چون گزینه رایجی است و تضمین میکند که کاربران میتوانند آزادانه، نرمافزار را اجرا و مطالعه کنند و همچنین به اشتراک گذارده و تغییر دهند.
گام ششم: کلون کردن و افزودن دایرکتوری
انتخاب کنید که میخواهید ریپازیتوری خود را به کجا به صورت محلی کلون کنید و دستور زیر را اجرا نمایید:
git clone https://github.com/notebooktoall/notebookc.git
بدیهی است که شما باید نام سازمان و ریپازیتوری خود را در دستور فوق جایگزین کنید.
با استفاده از GUI دسکتاپ یا ویرایشگر کد به پوشه پروژه خود بروید. همچنین میتوانید از خط فرمان با دستور cd my-project استفاده کنید و سپس فایلها را با دستور ls –A مشاهده کنید. پوشهها و فایلهای اولیه شما باید چیزی مانند زیر باشند:
.git .gitignore LICENSE README.rst
یک پوشه فرعی درون فایلهای اصلی پروژه خود ایجاد کنید. پیشنهاد میکنیم نام این پوشه فرعی را همان نام بسته خود قرار دهید. اطمینان حاصل کنید که در این نام از فاصله استفاده نشده است.
یک فایل با نام init__.py__ در پوشه فرعی اصلی خود بسازید. این فایل فعلاً خالی باقی خواهد ماند. وجود این فایل برای این که بتوان فایلهای این پوشه را ایمپورت کرد ضروری است.
فایل دیگری با همان نام پوشه فرعی اصلی و پسوند py. بسازید. برای نمونه فایل ما notebookc.py نام دارد. شما میتواند نام این فایل پایتون را هر چه که دوست دارید بگذارید.
اینک دایرکتوری notebook ما به صورت زیر در آمده است:
.git .gitignore LICENSE README.rst notebookc/__init__.py notebookc/notebookc.py
گام هفتم: ایجاد و نصب فایل requirements_dev.txt
در سطح بالای دایرکتوری پروژه خودتان یک فایل به نام requirements_dev.txt ایجاد کنید. این فایل در اغلب موارد به صورت requirements.txt نامگذاری میشود؛ اما ما به این خاطر آن را requirements_dev.txt نامگذاری میکنیم که مشخص شود این بسته تنها از سوی توسعهدهندگان پروژه نصب میشود.
در فایل requirements_dev.txt تعیین میکنیم که pip و wheel (+) باید نصب شوند:
pip==19.0.3 wheel==0.33.1
دقت کنید که نسخههای دقیق این بستهها را با دو علامت تساوی و همچنین عدد نسخه کامل به صورت major.minor.micro تعیین کردهایم.
بدین ترتیب یک همکار شما که ریپازیتوری پروژه را فورک کرده و بستههای پین شده requirements_dev.txt را با استفاده از pip نصب میکند، دقیقاً همان نسخههایی که شما داشتید را روی سیستم خود خواهد داشت. بدین ترتیب مطمئن میشویم که این بستهها برای وی کارآمد است. ضمناً بخش Read The Docs از این موارد برای نصب بستهها در زمان ساخت مستندات استفاده میکند.
در محیط مجازی فعال شده خودتان بستههای موجود در فایل requirements_dev.txt را با اجرای دستور زیر نصب کنید:
pip install -r requirements_dev.txt
بهتر است بستهها را با انتشار نسخههای جدید بهروزرسانی کنید. فعلاً میتوانید هر نسخهای که جدیدتر است را با جستجوی PyPI نصب کنید.
ما قصد داریم در بخش بعدی این سری مقالات یک ابزار نصب کنیم که به اجرای بهتر این فرایند کمک میکند. بنابراین بخش بعدی این سری مقالات را از دست ندهید!
گام هشتم: کدنویسی و کامیت کردن
در این مرحله قصد داریم به منظور نمایش اهداف خود تابعی مقدماتی بنویسیم. شما میتوانید تابع زیبای خودتان را بعدتر نیز بنویسید. کد زیر را در فایل اصلی قرار دهید. این فایل برای ما در مسیر notebookc/notebookc/notebookc.py قرار دارد:
1def convert(my_name):
2 """
3 Print a line about converting a notebook.
4 Args:
5 my_name (str): person's name
6 Returns:
7 None
8 """
9
10 print(f"I'll convert a notebook for you some day, {my_name}.")
این همه تابع با شکوه ما محسوب میشود.
«رشتههای مستندات» (docstrings) با گیومههای جفتی آغاز یافته و پایان مییابند. از این موارد در مقاله بعدی برای ایجاد خودکار مستندات استفاده شده است. در این مرحله، تغییراتی را که ایجاد کردیم، کامیت میکنیم. اگر میخواهید اطلاعات گیت خود را یادآوری کنید میتوانید سری به این مقاله بزنید:
گام نهم: ایجاد فایل setup.py
فایل setup.py اسکریپت سازنده بسته ما محسوب میشود. تابع setup از Setuptools اقدام به ساخت بسته ما برای آپلود به PyPI میکند. Setuptools شامل اطلاعاتی در مورد بسته، نسخه آن، بستههای دیگر مورد نیاز و نظایر آن است. فایل setup.py مثال ما چنین است:
1from setuptools import setup, find_packages
2
3with open("README.md", "r") as readme_file:
4 readme = readme_file.read()
5
6requirements = ["ipython>=6", "nbformat>=4", "nbconvert>=5", "requests>=2"]
7
8setup(
9 name="notebookc",
10 version="0.0.1",
11 author="Jeff Hale",
12 author_email="jeffmshale@gmail.com",
13 description="A package to convert your Jupyter Notebook",
14 long_description=readme,
15 long_description_content_type="text/markdown",
16 url="https://github.com/your_package/homepage/",
17 packages=find_packages(),
18 install_requires=requirements,
19 classifiers=[
20 "Programming Language :: Python :: 3.7",
21 "License :: OSI Approved :: GNU General Public License v3 (GPLv3)",
22 ],
23)
دقت کنید که long_description برابر با محتوای فایل README.md تعیین شده است.
لیست Requirements تعیین شده در setuptools.setup.install_requires شامل همه بستههای وابستگی مورد نیاز برای کارکرد بسته شما است.
برخلاف لیست بستههای مورد نیاز برای توسعه در requirements_dev.txt، این لیست از بستهها باید در حد امکان، آزادی عمل را در اختیار کاربران قرار دهد.
لیست install_requires را محدود به بستههایی بکنید که قطعاً مورد نیاز هستند، چون شما نمیخواهید کاربرانتان بستههای غیر ضروری را پاک کنند. دقت کنید که شما باید صرفاً بستههایی را در لیست قرار دهید که بخشی از کتابخانه استاندارد پایتون نیستند. کاربر شما اگر دوست داشته باشد از بسته شما استفاده کند، قطعاً پایتون را روی سیستم خود نصب دارد!
بسته ما نیازمند هیچ وابستگی خارجی نیست و از این رو میتوانید آن را از چهار بسته لیست شده فوق حذف کنید. یکی از همکارانتان که ریپوی بسته شما را فورک میکند و بستههای پین شده را با pip نصب میکند، همان شماره بستههایی را که شما در اختیار دارید، مشاهده خواهد کرد. بدین ترتیب از کارکرد بسته مطمئن خواهیم شد.
اطلاعات دیگر setuptools را طوری تغییر دهید که با اطلاعات بسته شما هماهنگ باشد. آرگومانهای کلیدواژهای اختیاری و کلاسیفرهای زیاد دیگری نیز وجود دارند. فهرستی از آنها را میتوانید از این لینک (+) ملاحظه کنید.
برای مشاهده راهنمای دقیقتری در خصوص فایل setup.py به لینکهای (+) و (+) مراجعه کنید.
گام دهم: ساخت اولین نسخه
Twine مجموعهای از ابزارها برای انتشار امن بستههای پایتون روی PyPI است. بسته Twine (+) را در خط خالی آخر فایل requirements_dev.txt به صورت زیر اضافه کنید:
twine==1.13.0
سپس با نصب مجدد بستههای requirements_dev.txt اقدام به نصب Twine در محیط مجازی بکنید:
pip install -r requirements_dev.txt
در ادامه دستور زیر را برای ایجاد فایلهای بسته خود وارد کنید:
python setup.py sdist bdist_wheel
چندین پوشه مخفی باید ایجاد شوند: dist ،build و در مورد مثال ما notebookc.egg-info. در ادامه نگاهی به فایلهای موجود در پوشه dist میاندازیم. فایل whl. یک فایل wheel است که توزیع ساخته شده است. فایل tar.gz. یک آرشیو منبع است.
روی سیستم کاربر، pip در صورت امکان اقدام به نصب بستهها به صورت wheel میکند. wheel-ها نصب سریعتری دارند. زمانی که pip نتواند یک wheel را نصب کند، به آرشیو منبع بازمیگردد. اینک برای آپلود wheel و آرشیو منبع آماده میشویم.
گام یازدهم: ایجاد حساب TestPyPI
PyPI (+) اختصاری برای عبارت «اندیس بسته پایتون» (Python Package Index) است که ابزار مدیریت بسته رسمی پایتون محسوب میشود. pip فایلها را هنگامی که به صورت محلی نصب نباشند از PyPI دریافت میکند.
TestPyPI یک نسخه تست کارآمد از PyPI محسوب میشود. یک حساب TestPyPI را در این صفحه (+) ایجاد کنید و آدرس ایمیل خود را تأیید نمایید. دقت کنید که باید رمزهای عبور جداگانهای برای آپلود کردن سایت تست و سایت رسمی داشته باشید.
گام دوازدهم: انتشار TestPyPI
از Twine برای انتشار امن بسته روی TestPyPI استفاده میکنیم. دستور زیر را وارد کنید. دقت کنید که نیاز به ایجاد هیچ تغییری نیست:
twine upload --repository-url https://test.pypi.org/legacy/ dist/*
در ادامه از شما نام کاربری و رمز عبور سؤال میشود. به خاطر داشته باشید که رمزهای عبور TestPyPI و PyPI متفاوت از هم هستند!
در صورت نیاز خطاها را اصلاح کنید و شماره نسخه جدیدی در setup.py ایجاد کنید. همچنین باید هر آن چه از build قدیمی بر جای مانده را حذف کنید که شامل پوشههای build ،dist و egg میشود. با دستور زیر:
python setup.py sdist bdist_wheel
بسته را مجدداً بسازید و در ادامه با Twine آن را بازسازی کنید. داشتن شماره نسخه روی TestPyPI که هیچ چیزی را نشان نمیدهد کار سختی محسوب نمیشود، چون شما تنها کسی هستید که از این نسخههای بسته استفاده میکنید.
زمانی که با موفقیت بسته را آپلود کردید، باید مطمئن شوید که میتوان آن را نصب کرده و مورد استفاده قرار داد.
گام سیزدهم: تأیید نصب و استفاده
برگه جدیدی در پوسته ترمینال باز کنید و محیط مجازی دیگری بسازید.
python3.7 -m venv my_env
آن را فعال کنید:
source my_env/bin/activate
اگر بسته خود را روی سایت سمی PyPI آپلود کردهاید در این صورت میتوانید از دستور زیر استفاده کنید:
pip install your-package
شما میتوانید با استفاده از دستور تغییر یافته فوق بسته را از TestPyPI دریافت کرده و نصب کنید.
دستورالعمل رسمی نصب بسته از TestPyPI به صورت زیر است:
شما میتوانید به pip اعلام کنید که بستهها را به جای PyPI از TestPyPI دریافت کند، به این منظور باید فلگ index-url را تعیین کنید:
pip install --index-url https://test.pypi.org/simple/ my_packageاگر میخواهید به pip اجازه بدهید که همه بستهها را از PyPI دریافت کند، میتوانید extra-index-url را طوری تعیین کنید که به PyPI اشاره کند. این حالت هنگامی مفید است که بسته شما وابستگیهای تست دارد:
pip install --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple my_package
اگر بسته شما دارای وابستگی است، میتوانید از دستور دوم استفاده کنید و نام بستهتان را جایگزین نمایید.
شما میتوانید آخرین نسخه از بسته را که در محیط مجازی نصب شده است ببینید. برای تأیید نصب میتوانید از بسته خود استفاده کنید و از یک نشست IPython در ترمینال با استفاده از دستور زیر بهره بگیرید:
Python
تابع خود را ایمپورت کنید و با استفاده از آرگومان رشتهای آن را فراخوانی نمایید. کد ما به صورت زیر است:
from notebookc.notebookc import convert convert(“Jeff”)
در این صورت خروجی زیر را مشاهده میکنید:
I’ll convert a notebook for you some day, Jeff.
بدین ترتیب نوبت آن رسیده است که کارهای خود را روی گیتهاب آپلود کنیم:
گام چهاردهم: ارسال به گیتهاب
ابتدا اطمینان حاصل کنید که کد خود را کامیت کردهاید. پوشه پروژه notebook ما اینک به صورت زیر است:
.git .gitignore LICENSE README.md requirements_dev.txt setup.py notebookc/__init__.py notebookc/notebookc.py
هر گونه محیط مجازی که نمیخواهید آپلود شود را حذف کنید. فایل gitignore. پایتون که در زمان ساخت ریپو انتخاب کردهایم، میتواند جلوی اندیس شدن فایلهای اضافی build را بگیرد. همچنین میتوانید پوشههای محیط مجازی را پاک کنید.
در ادامه شاخه محلی گیتهاب را با دستور زیر push کنید:
git push origin my_branch
گام پانزدهم: ایجاد و ادغام PR
در مرورگر خود به وبسایت گیتهاب بروید. اینک میتوانید گزینهای برای درخواست pull مشاهده کنید. با فشردن دکمههای سبزرنگ برای ایجاد و ادغام PR، شاخه ویژگی ریموت را حذف کنید.
اینک به ترمینال بازگردید و شاخه ویژگی محلی را با دستور زیر حذف کنید:
git branch -d my_feature_branch
ما فایلها و پوشههای زیاد دیگری را در مقالات بعدی اضافه خواهیم کرد. فعلاً گامهایی که در این مقاله پیمودیم را جمعبندی میکنیم.
جمعبندی
امیدواریم این راهنمای ایجاد و انتشار نخستین بسته پایتون برای شما مفید بوده باشد. در بخش بعدی این سری مقالات آموزشی پایتون اقدام به تست، یکپارچهسازی مداوم، پوشش کد و موارد دیگر برای کار با بستهها خواهیم نمود. برای مطالعه آن روی لینک زیر کلیک کنید:
اگر این مطلب برای شما مفید بوده است، آموزشهای زیر نیز به شما پیشنهاد میشوند:
- مجموعه آموزشهای برنامهنویسی پایتون Python
- مجموعه آموزشهای برنامهنویسی
- آموزش برنامه نویسی پایتون – مقدماتی
- آموزش تکمیلی برنامه نویسی پایتون
- آموزش یادگیری ماشین (Machine Learning) با پایتون (Python)
- آموزش پایتون (Python) — مجموعه مقالات جامع وبلاگ فرادرس
==