در مطلب ایجاد برنامه های خط فرمان با ماژول sys توضیح دادیم که چگونه توسط لیست sys.argv یک برنامه خط فرمان ساده ایجاد کنیم. در واقع هدف این بود که توضیح دهیم چگونه می توانیم آرگومان های ورودی به نام اسکریپت را کنترل کنیم. توجه کنید که نام اسکریپت در لیست sys.argv اولین المان با اندیس صفر است. اما فهرست sys.argv برای کاربردهای جدی و نوشتن برنامه های کاربردی به هیچ عنوان عملی و کاربردی ساده نخواهد داشت، بنابراین در این مطلب می خواهیم از ماژولی به نام click برای ایجاد برنامه های خط فرمان استفاده کنیم.

نصب click

click مخفف Command Line Interface Creation Kit و ماژولی است که از آن برای ایجاد برنامه های خط فرمان استفاده می شود.  برای نصب آن می توانیم از دستور pip در محیط مجازی virtualenv استفاده کنیم. در پایتون ماژول استاندارد دیگری به نام argparse وجود دارد که از آن نیز می توانیم برای ایجاد برنامه های خط فرمان استفاده کنیم. در مطلب  می توانید آموزش ماژول argparse را مطالعه کنید.

همچنین اگر می خواهید در محیط Anaconda برنامه نویسی کنید باید توسط دستور زیر ماژول click را نصب کنید. توجه کنید که اگر از سیستم عامل ویندوز استفاده می کنید دیگر نیازی به نوشتن دستور sudo پیش از دستور conda ندارید و دستور sudo را تنها در سیستم عامل های لینوکس، مکینتاش و دیگر یونیکس ها استفاده کنید.

نوشتن اولین دستور

پیش از هر چیز باید با مفهوم decorator در پایتون آشنا باشید، زیرا ماژول click دستورها را از طریق decorator ها ایجاد می کند. در مفاهیم click یک تابع زمانی که از طریق decorator تعریف شود، به عنوان یک عملکرد خواهد بود. به طور کلی هر تابع یکی از قابلیت ها و عملکردهای دستور را تعریف می کند. همچنین منظور از دستور نام اسکریپت پایتونی است که کدها در آن تعریف شده اند. در ماژول (کلاس click) متدی (method) به نام ()echo وجود دارد که پیغام را در خروجی نمایش می دهد. دلیل استفاده و پیاده سازی این متد در ماژول click به جای استفاده از تابع ()print این است که از نسخه های مختلف پایتون ۲ و ۳ پشتیبانی شود.

چاپ خروجی در پایتون

کدهای زیر برنامه بسیار ساده را از کاربرد click نشان می دهند. ()hello نام تابعی است که تنها یک پیغام ساده را نشان می دهد. توجه کنید که در ابتدا ()click.command@ نوشته شده است و سپس به دنبال آن تابع ()hello تعریف شده است.

شکل زیر دو اجرای متفاوت از دستور را نشان می دهد. همانطور که مشخص نام فایل اسکریپت یعنی cmd.py همان نام دستور است. در اجرای اول هیچ آرگومانی به تابع ارسال نشده است و به صورت پیشفرض پیغام تابع ()hello نشان داده می شود. دلیل نمایش پیغام تابع ()hello برای این است که این تابع در خط ۹ و پس از شرط if فراخوانی شده است. در اجرای دوم سويیچ help– به دستور ارسال شده است و پیغام راهنمای استفاده از دستور را نشان می دهد.

در سیستم عامل های یونیکسی (و حتمالا ویندوز) دو نوع سوئیچ وجود دارد که یک دسته با تک علامت منها (یا علامت dash ) آغاز می شوند و دسته دیگر با دو علامت منها شروع می شوند. اصطلاحا سوئیچ هایی که با دو علامت منها آغاز می شوند را human readble می گویند زیر قابل خوانده شدن و درک شدن راحتری برای ما هستند. به طور مثال ممکن است دو سوئیچ به نام های h- و help- – وجود داشته باشد که هر دو راهنمای دستور را نشان می دهند ولی help- – را راحتر و ساده تر متوجه می شویم. توجه کنید که در مفاهیم یونیکس از واژه option برای تعیین یک سوئیچ استفاده می شود.

تعریف Option های بولی

برای تعریف سوئیچ یا همان option ها در دستورهای یونیکسی باید هر option را توسط یک decotator به نام ()click.option@ تعریف کنیم. کد زیر بازنویسی شده کد بالا است که در خط ۴ یک option بولی (boolean option) به نام verbose- – تعریف شده است. سپس در خط ۵ نام option تعیین شده، یعنی verbose را به عنوان پارامتر به تابع ارسال می کنیم. سپس در خط ۶ بررسی می کنیم که آیا verbose- – در خط فرمان تعیین شده است یا نه. اگر این verbose- – تعیین شده باشد، پس مقدار متغیر (پارامتر) verbose برابر با True است.

شکل زیر دو اجرا از دستور را نشان می دهد که در یکی verbose- – تعیین شده و در دیگری تعیین نشده است. همانطور که می بینید زمانی که verbose- – تعیین شده است هر دو پیغام متد ()echo نمایش داده می شود ولی اگر تعیین نشده باشد تنها پیغام دومی نشان داده می شود.

در خط ۴ و درون ()click.option@ آرگومان help پیغامی را تعیین می کند که این پیغام در متن راهنمای دستور و در جلوی نام option (یا همان سوئیچ) نشان داده می شود. در شکل زیر می ینید که متن آرگومان help در جلوی نام option نوشته شده است.

همانطور که گفتیم خود ماژول click یک option پیشفرض به نام help- – را آماده کرده است که راهنمای دستور را آماده و نمایش می دهد. اگر بخواهیم option به نام h- را نیز برای نمایش راهنمای دستور آماده و تعریف کنیم باید از ()click.help_option و به صورت خط ۴ در کد زیر استفاده کنیم. اگر خط ۴ را تعیین نکرده باشید و از h- برای نمایش راهنما استفاده کنید، خطای Error: no such option: -h نشان داده می شود.

تعریف Option ها با مقدار

option های بولی که برای تعریف آنها باید از پارامتر is_flag=True استفاده کنیم، هیچ مقداری را دریافت نمی کنند بلکه حالت فعال (True) یا غیر فعال (False) را پیاده سازی می کنند. در مقابل می توانیم option هایی را تعریف کنیم که باید یک مقدار را در یافت کنند و سپس بر روی آن یک عملیات انجام دهند و در نهایت خروجی را نمایش دهند. کد زیر یک option به نام n را تعریف می کند که عددی را دریافت و سپس علامت * را به اندازه n بار و n مرتبه و هر n ثاینه یک بار تکرار می کند.

مطابق شکل زیر برای اجرای دستور با option هایی که به یک مقدار نیاز دارند باید از علامت مساوی برای انتساب مقدار به option استفاده کنیم. در شکل زیر می بینید که مقدار عدد ۳ به option و قاعدتا به تابع ()print ارسال شده است. توجه کنید که در خط ۷ مقدار ورودی n را توسط تابع ()int به نوع عدد صحیح تبدیل کرده ایم زیرا ورودی ها به صورت پیشفرض نوع رشته هستند. اگر این تبدیل نوع انجام نمی شد، خط بعدی یعنی حلقه for و تابع ()range دچار خطا می شد، زیر تابع ()range عدد صحیح را از ورودی دریافت می کند.

تعریف Option های مقداری

درون ()click.option@ از پارامتر nargs برای تعیین تعداد مقادیر ارسالی به option استفاده می شود. همچنین اگر بخواهیم نوع مقدار (رشته، عدد صحیح، اعشاری، یونیکد) را تعیین کنیم، باید از پارامتر type استفاده کنیم. در قطعه کد زیر option نیاز به دو مقدار دارد که در زمان ارسال به option با فاصله از هم جدا می شوند. همچنین نیازی به نوشتن علامت سوال نیست. نوع دو مقدار ارسالی نیز از نوع str یا رشته است.

همانطور که از شکل بالا مشخص است، دو مقدار عنوان ورودی option با یک فاصله از هم به option ارسال شده اند و سپس توسط خط ۶ یک علامت منها (علامت dash) بین آنها گذاشته شده و سپس در خروجی نشان داده می شود. حال برای آزمایش برنامه هیچ ورودی یا تنها یک ورودی را وارد کنید تا ببینید که آیا خطایی نشان داده می شود. همچنین برای مستندسازی عملکرد option می توانید همانند خط زیر پارامتر help در ()click.option@ را با رشته مناسب، مقدار دهی کنید تا این رشته به عنوان خط راهنما در جلوی نام option در راهنمای دستور نمایش داده شود. همانطور که توضیح دادیم راهنمای دستور به صورت پیشفرض توسط help– نمایش داده می شود.

ارسال تاپلی از مقادیر برای تعریف option های چند مقدار ی

مطابق قطعه کد زیر می توانیم option هایی را تعریف کنیم که نیاز به چندین مقدار و البته با انواع مختلف دارند. برای این منظور باید به پارامتر type یک تاپل که نوع مقادیر را تعیین می کند ارسال شود. در کد زیر نیاز به دو مقدار ورودی رشته و سپس یک مقدار عدد صحیح داریم، پس در خط ۴ تاپل از نوع ها را به صورت (type=(str,str,int ارسال کرده ایم. همچنین دیگر نیازی به نعیین پارامتر nargs نیست و می توانید از آن صرف نظر کنید ولی اگر می خواهید آنرا بنویسید، مقدار آن باید برابر با تعداد عناصر تاپل ارسالی به پارامتر type باشد.