optparse --- پارسر گزینههای خط فرمان¶
کد منبع: Lib/optparse.py
انتخاب یک کتابخانه تجزیه آرگومان¶
کتابخانه استاندارد شامل ۳ کتابخانه تجزیه آرگومان است:
getopt: ماژولی که API رویهایgetoptدر زبان C را بهدقت بازتاب میدهد. از پیش از نخستین انتشار Python 1.0 در کتابخانه استاندارد گنجانده شده است.optparse: جایگزینی اعلانی برایgetoptکه قابلیت معادلی را بدون نیاز به اینکه هر برنامه منطق تجزیه گزینههای خود را بهصورت رویهای پیادهسازی کند، فراهم میکند. از نسخه Python 2.3 در کتابخانه استاندارد گنجانده شده است.argparse: جایگزینی سختگیرانهتر برایoptparseکه بهطور پیشفرض قابلیتهای بیشتری فراهم میکند، اما به بهای کاهش انعطافپذیری برنامه در کنترل دقیق چگونگی پردازش آرگومانها. از زمان انتشار Python 2.7 و Python 3.2 در کتابخانه استاندارد گنجانده شده است.
در نبود محدودیتهای طراحی خاصتر برای تجزیه آرگومان، argparse گزینه توصیهشده برای پیادهسازی برنامههای خط فرمان است، زیرا بالاترین سطح از قابلیتهای پایه را با کمترین کد در سطح برنامه ارائه میدهد.
getopt تقریباً بهطور کامل به دلایل سازگاری با نسخههای پیشین حفظ شده است. با این حال، این ماژول همچنین کاربرد خاصی بهعنوان ابزاری برای نمونهسازی و آزمون مدیریت آرگومانهای خط فرمان در برنامههای کاربردی C مبتنی بر getopt دارد.
در موارد زیر، optparse باید بهعنوان جایگزینی برای argparse در نظر گرفته شود:
یک برنامه کاربردی از قبل از
optparseاستفاده میکند و نمیخواهد خطر تغییرات رفتاری ظریفی را که ممکن است هنگام مهاجرت بهargparseپیش بیایند، بپذیردبرنامه به کنترل بیشتری بر نحوهی در هم آمیخته شدن گزینهها و پارامترهای جایگاهی در خط فرمان نیاز دارد (از جمله توانایی غیرفعال کردن کامل قابلیت در هم آمیختن)
برنامه کاربردی به کنترل بیشتری بر تجزیه تدریجی عناصر خط فرمان نیاز دارد (اگرچه
argparseاز این قابلیت پشتیبانی میکند، اما شیوه دقیق عملکرد آن در عمل برای برخی موارد استفاده نامطلوب است)برنامه به کنترل بیشتری بر پردازش گزینههایی نیاز دارد که مقادیر پارامترهایی را میپذیرند که ممکن است با
-شروع شوند (مانند گزینههای واگذاریشده برای ارسال به زیرفرآیندهای فراخوانیشده)برنامه کاربردی به رفتار دیگری برای پردازش پارامترهای خط فرمان نیاز دارد که
argparseاز آن پشتیبانی نمیکند، اما میتوان آن را بر اساس رابط سطح پایینتر ارائهشده توسطoptparseپیادهسازی کرد
این ملاحظات همچنین به این معناست که optparse احتمالاً پایه بهتری برای نویسندگان کتابخانهها که کتابخانههای پردازش آرگومانهای خط فرمان شخص ثالث را مینویسند، فراهم میکند.
بهعنوان مثالی ملموس، دو پیکربندی تجزیهی آرگومانهای خط فرمان زیر را در نظر بگیرید، که اولی از optparse و دومی از argparse استفاده میکند:
import optparse
if __name__ == '__main__':
parser = optparse.OptionParser()
parser.add_option('-o', '--output')
parser.add_option('-v', dest='verbose', action='store_true')
opts, args = parser.parse_args()
process(args, output=opts.output, verbose=opts.verbose)
import argparse
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('-o', '--output')
parser.add_argument('-v', dest='verbose', action='store_true')
parser.add_argument('rest', nargs='*')
args = parser.parse_args()
process(args.rest, output=args.output, verbose=args.verbose)
واضحترین تفاوت این است که در نسخهی optparse، آرگومانهای غیرگزینهای پس از تکمیل پردازش گزینهها، بهطور جداگانه توسط برنامه پردازش میشوند. در نسخهی argparse، آرگومانهای جایگاهی به همان شیوهی گزینههای نامدار تعریف و پردازش میشوند.
با این حال، نسخهی argparse برخی ترکیبهای پارامتر را نیز متفاوت از شیوهای که نسخهی optparse آنها را مدیریت میکرد، مدیریت خواهد کرد. برای مثال (از جمله تفاوتهای دیگر):
ارائهی
-o -vهنگام استفاده ازoptparse،output="-v"وverbose=Falseرا بهدست میدهد، اما درargparseیک خطای کاربرد ایجاد میکند (با این اعتراض که هیچ مقداری برای-o/--outputارائه نشده است، زیرا-vبهعنوان پرچم سطح جزئیات تفسیر میشود)بهطور مشابه، ارائه
-o --هنگام استفاده ازoptparse،output="--"وargs=()را میدهد، اما درargparseیک خطای کاربرد ایجاد میکند (همچنین اعلام میکند که هیچ مقداری برای-o/--outputارائه نشده است، زیرا--بهعنوان پایان پردازش گزینهها تفسیر میشود و تمام مقادیر باقیمانده بهعنوان آرگومانهای جایگاهی در نظر گرفته میشوند)وارد کردن
-o=fooهنگام استفاده ازoptparseمقدارoutput="=foo"را میدهد، اما باargparseمقدارoutput="foo"را میدهد (زیرا=بهعنوان یک جداکننده جایگزین برای مقدارهای پارامتر گزینه، یک حالت خاص محسوب میشود).
اینکه این رفتارهای متفاوت در نسخهی argparse مطلوب یا مشکل تلقی شوند، به مورد استفاده خاص برنامه خط فرمان بستگی دارد.
همچنین ملاحظه نمائید
click یک کتابخانه شخص ثالث برای پردازش آرگومان است (در ابتدا مبتنی بر optparse)، که امکان توسعه برنامههای خط فرمان را بهصورت مجموعهای از توابع دکوراتورشده پیادهسازی دستور فراهم میکند.
سایر کتابخانههای شخص ثالث، مانند typer یا msgspec-click، به شما امکان میدهند رابطهای خط فرمان را به شیوههایی مشخص کنید که بهطور مؤثرتری با بررسی ایستای حاشیهنویسیهای نوع پایتون یکپارچه میشوند.
مقدمه¶
optparse کتابخانهای آسانتر، انعطافپذیرتر و قدرتمندتر برای تجزیهی گزینههای خط فرمان نسبت به ماژول کمینهگرای getopt است. optparse از سبک اعلامیتری برای تجزیهی خط فرمان استفاده میکند: شما یک نمونه از OptionParser ایجاد میکنید، آن را با گزینهها پر میکنید و خط فرمان را تجزیه میکنید. optparse به کاربران اجازه میدهد گزینهها را با سینتکس مرسوم GNU/POSIX مشخص کنند و علاوه بر این، پیامهای کاربرد و راهنمایی را برای شما تولید میکند.
در اینجا مثالی از استفاده از optparse در یک اسکریپت ساده آمده است:
from optparse import OptionParser
...
parser = OptionParser()
parser.add_option("-f", "--file", dest="filename",
help="write report to FILE", metavar="FILE")
parser.add_option("-q", "--quiet",
action="store_false", dest="verbose", default=True,
help="don't print status messages to stdout")
(options, args) = parser.parse_args()
با این چند خط کد، کاربران اسکریپت شما اکنون میتوانند «کار معمول» را در خط فرمان انجام دهند، برای مثال:
<yourscript> --file=outfile -q
هنگامی که optparse خط فرمان را تجزیه میکند، ویژگیهای شیء options برگرداندهشده توسط parse_args() را بر اساس مقادیر خط فرمان ارائهشده توسط کاربر تنظیم میکند. هنگام بازگشت parse_args() از تجزیه این خط فرمان، options.filename برابر "outfile" و options.verbose برابر False خواهد بود. optparse هم از گزینههای بلند و هم از گزینههای کوتاه پشتیبانی میکند، اجازه میدهد گزینههای کوتاه با یکدیگر ادغام شوند، و اجازه میدهد گزینهها به روشهای گوناگونی با آرگومانهای خود مرتبط شوند. بنابراین، سطرهای فرمان زیر همگی معادل مثال بالا هستند:
<yourscript> -f outfile --quiet
<yourscript> --quiet --file outfile
<yourscript> -q -foutfile
<yourscript> -qfoutfile
علاوه بر این، کاربران میتوانند یکی از موارد زیر را اجرا کنند
<yourscript> -h
<yourscript> --help
و optparse خلاصهای کوتاه از گزینههای اسکریپت شما را نمایش خواهد داد:
کاربرد: <yourscript> [options]
گزینهها:
-h, --help این پیام راهنما را نمایش میدهد و خارج میشود
-f FILE, --file=FILE گزارش را در FILE مینویسد
-q, --quiet پیامهای وضعیت را در stdout چاپ نمیکند
که مقدار yourscript در رانتایم تعیین میشود (معمولاً از sys.argv[0]).
پیشزمینه¶
optparse بهصراحت طراحی شده است تا ایجاد برنامههایی با رابطهای خط فرمان ساده را تشویق کند که از قراردادهای تعیینشده توسط خانوادهی توابع getopt() در دسترس توسعهدهندگان C پیروی میکنند. برای همین منظور، این ماژول فقط از رایجترین سینتکس و معناشناسی خط فرمان پشتیبانی میکند که بهطور قراردادی در یونیکس استفاده میشود. اگر با این قراردادها آشنا نیستید، خواندن این بخش به شما امکان میدهد با آنها آشنا شوید.
اصطلاحات¶
- آرگومان
رشتهای که در خط فرمان وارد میشود و از سوی پوسته به
execl()یاexecv()پاس داده میشود. در پایتون، آرگومانها عناصرsys.argv[1:]هستند (sys.argv[0]نام برنامهای است که اجرا میشود). پوستههای یونیکس همچنین از اصطلاح «word» استفاده میکنند.گاهی جایگزینکردن فهرستی از آرگومانها غیر از
sys.argv[1:]مطلوب است، بنابراین باید «آرگومان» را بهعنوان «عنصری ازsys.argv[1:]، یا از فهرست دیگری که بهعنوان جایگزینی برایsys.argv[1:]فراهم شده است» بخوانید.- گزینه
آرگومانی که برای ارائه اطلاعات اضافی بهمنظور هدایت یا سفارشیسازی اجرای یک برنامه استفاده میشود. سینتکسهای مختلفی برای گزینهها وجود دارد؛ سینتکس سنتی یونیکس یک خط تیره («-») است که پس از آن یک نویسه میآید، برای مثال
-xیا-F. همچنین، سینتکس سنتی یونیکس اجازه میدهد چند گزینه در یک آرگومان واحد ادغام شوند، برای مثال-x -Fمعادل-xFاست. پروژهی گنو--را معرفی کرد که پس از آن دنبالهای از کلمههای جداشده با خط تیره میآید، برای مثال--fileیا--dry-run. اینها تنها دو سینتکس گزینه هستند که توسطoptparseارائه میشوند.برخی دیگر از سینتکسهای گزینهها که دنیا به خود دیده است عبارتاند از:
یک خط تیره و پس از آن چند حرف، برای مثال
-pf(این با چند گزینه که در یک آرگومان واحد ادغام شدهاند، یکسان نیست)یک خط تیره که پس از آن یک کلمه کامل بیاید، مثلاً
-file(این از نظر فنی معادل سینتکس قبلی است، اما این دو معمولاً در یک برنامه دیده نمیشوند)یک علامت مثبت بههمراه یک حرف، یا چند حرف، یا یک کلمه، مثلاً
+f،+rgbیک اسلش که پس از آن یک حرف، یا چند حرف، یا یک کلمه بیاید، برای مثال
/f،/file
این سینتکسهای گزینه توسط
optparseپشتیبانی نمیشوند و هرگز پشتیبانی نخواهند شد. این موضوع عمدی است: سه مورد نخست در هیچ محیطی استاندارد نیستند و آخرین مورد تنها زمانی منطقی است که منحصراً ویندوز یا برخی سکوهای قدیمی (مانند VMS، MS-DOS) را هدف قرار داده باشید.- آرگومان گزینه
آرگومانی که بهدنبال یک گزینه میآید، ارتباط نزدیکی با آن گزینه دارد و هنگامی که آن گزینه مصرف میشود، از فهرست آرگومانها برداشته میشود. با
optparse، آرگومانهای گزینه ممکن است در آرگومانی جداگانه از گزینهی خود باشند:-f foo --file foo
یا در همان آرگومان گنجانده شود:
-ffoo --file=foo
معمولاً یک گزینه مشخص یا آرگومان میگیرد یا نمیگیرد. بسیاری از افراد قابلیت «آرگومانهای اختیاری گزینهها» را میخواهند، به این معنا که برخی گزینهها اگر آرگومانی ببینند آن را میگیرند و اگر نبینند نمیگیرند. این موضوع تا حدی بحثبرانگیز است، زیرا باعث مبهم شدن تجزیه میشود: اگر
-aآرگومان اختیاری بگیرد و-bگزینهای کاملاً متفاوت باشد،-abرا چگونه تفسیر میکنیم؟ به دلیل همین ابهام،optparseاین قابلیت را پشتیبانی نمیکند.- آرگومان جایگاهی
چیزی باقیمانده در فهرست آرگومانها پس از تجزیه گزینهها، یعنی پس از تجزیه گزینهها و آرگومانهایشان و حذف آنها از فهرست آرگومانها.
- گزینهی ضروری
گزینهای که باید در خط فرمان ارائه شود؛ توجه داشته باشید که عبارت «required option» در زبان انگلیسی متناقض است.
optparseشما را از پیادهسازی گزینههای الزامی بازنمیدارد، اما کمک زیادی هم در این زمینه به شما نمیکند.
برای مثال، این خط فرمان فرضی را در نظر بگیرید:
prog -v --report report.txt foo bar
-v و --report هر دو گزینه هستند. با فرض اینکه --report یک آرگومان میگیرد، report.txt آرگومانِ گزینه است. foo و bar آرگومانهای جایگاهی هستند.
گزینهها برای چه منظوری هستند؟¶
گزینهها برای ارائهی اطلاعات اضافی جهت تنظیم یا سفارشیسازی اجرای یک برنامه استفاده میشوند. در صورتی که واضح نبود، گزینهها معمولاً اختیاری هستند. یک برنامه باید بتواند بدون حتی یک گزینه نیز بهخوبی اجرا شود. (برنامهای تصادفی از مجموعهابزارهای Unix یا GNU انتخاب کنید. آیا میتواند بدون هیچ گزینهای اجرا شود و همچنان معنادار باشد؟ استثناهای اصلی find، tar و dd---که همهی آنها عجیبوغریبهای جهشیافتهای هستند که بهحق بهدلیل سینتکس غیراستاندارد و رابطهای گیجکنندهشان مورد انتقاد قرار گرفتهاند.)
بسیاری از افراد میخواهند برنامههایشان «گزینههای اجباری» داشته باشند. به این موضوع فکر کنید. اگر چیزی اجباری است، پس اختیاری نیست! اگر اطلاعاتی وجود دارد که برنامهی شما برای اجرای موفق بهطور قطع به آن نیاز دارد، آرگومانهای جایگاهی برای همین منظور هستند.
بهعنوان نمونهای از طراحی خوب رابط خط فرمان، ابزار ساده cp را برای کپی کردن پروندهها در نظر بگیرید. تلاش برای کپی کردن پروندهها بدون مشخص کردن مقصد و حداقل یک منبع چندان منطقی نیست. بنابراین، اگر cp را بدون هیچ آرگومانی اجرا کنید، با شکست مواجه میشود. با این حال، این ابزار دارای سینتکس انعطافپذیر و مفیدی است که اصلاً به هیچ گزینهای نیاز ندارد:
cp SOURCE DEST
cp SOURCE ... DEST-DIR
فقط با همان میتوانید تا حد زیادی پیش بروید. بیشتر پیادهسازیهای cp گزینههای زیادی را برای تنظیم دقیق نحوهی کپیشدن پروندهها فراهم میکنند: میتوانید حالت و زمان تغییر را حفظ کنید، از دنبال کردن پیوندهای نمادین خودداری کنید، پیش از بازنویسی پروندههای موجود تأیید بخواهید و غیره. اما هیچکدام از این موارد توجه را از مأموریت اصلی cp منحرف نمیکند؛ یعنی کپی کردن یک پرونده به پروندهای دیگر، یا چند پرونده به پوشهای دیگر.
آرگومانهای جایگاهی برای چه کاربردی دارند؟¶
آرگومانهای جایگاهی برای آن دسته از اطلاعاتی هستند که برنامه شما قطعاً و یقیناً برای اجرا به آنها نیاز دارد.
یک رابط کاربری خوب باید تا حد ممکن نیازمندیهای مطلق کمی داشته باشد. اگر برنامه شما برای اجرای موفقیتآمیز به ۱۷ مورد اطلاعات مجزا نیاز داشته باشد، چگونگی دریافت آن اطلاعات از کاربر چندان اهمیتی ندارد---بیشتر افراد پیش از آنکه برنامه را با موفقیت اجرا کنند، تسلیم میشوند و آن را ترک میکنند. این موضوع چه رابط کاربری خط فرمان باشد، چه پرونده پیکربندی و چه GUI صدق میکند: اگر اینقدر از کاربران خود درخواست داشته باشید، بیشتر آنها بهسادگی تسلیم خواهند شد.
بهطور خلاصه، سعی کنید میزان اطلاعاتی را که کاربران قطعاً ملزم به ارائه آن هستند به حداقل برسانید—هر جا که ممکن است از پیشفرضهای مناسب استفاده کنید. البته، شما همچنین میخواهید برنامههای شما بهطور معقولی انعطافپذیر باشند. گزینهها برای همین منظور هستند. باز هم، فرقی نمیکند که آنها ورودیهایی در یک پرونده پیکربندی باشند، ابزارکهایی در پنجرهی «Preferences» یک GUI، یا گزینههای خط فرمان—هرچه گزینههای بیشتری را پیادهسازی کنید، برنامهی شما انعطافپذیرتر میشود و پیادهسازی آن پیچیدهتر میگردد. البته انعطافپذیری بیشازحد هم معایبی دارد؛ گزینههای بیشازحد میتوانند کاربران را سردرگم کنند و نگهداری کد شما را بسیار سختتر کنند.
آموزش¶
اگرچه optparse بسیار انعطافپذیر و قدرتمند است، اما استفاده از آن در بیشتر موارد ساده است. این بخش الگوهای کد رایج در هر برنامهی مبتنی بر optparse را پوشش میدهد.
ابتدا باید کلاس OptionParser را ایمپورت کنید؛ سپس در ابتدای برنامه اصلی، یک نمونه از OptionParser ایجاد کنید:
from optparse import OptionParser
...
parser = OptionParser()
سپس میتوانید تعریف گزینهها را آغاز کنید. سینتکس پایه به این صورت است:
parser.add_option(opt_str, ...,
attr=value, ...)
هر گزینه یک یا چند رشتهی گزینه، مانند -f یا --file، و چندین ویژگی گزینه دارد که به optparse میگویند چه چیزی را باید انتظار داشته باشد و وقتی با آن گزینه در خط فرمان مواجه میشود چه کاری باید انجام دهد.
معمولاً هر گزینه دارای یک رشتهی گزینهی کوتاه و یک رشتهی گزینهی بلند است، برای مثال:
parser.add_option("-f", "--file", ...)
شما آزادید هر تعداد رشتهی گزینه کوتاه و هر تعداد رشتهی گزینه بلند که بخواهید تعریف کنید (از جمله صفر)، به شرطی که در مجموع دستکم یک رشتهی گزینه وجود داشته باشد.
رشتههای گزینهای که به OptionParser.add_option() داده میشوند، در عمل برچسبهایی برای گزینهای هستند که با آن فراخوانی تعریف میشود. برای اختصار، ما اغلب به برخورد با یک گزینه در خط فرمان اشاره خواهیم کرد؛ در واقع، optparse با رشتههای گزینه برخورد میکند و گزینهها را از آنها جستوجو میکند.
پس از اینکه همهی گزینههای شما تعریف شدند، به optparse دستور دهید خط فرمان برنامهتان را تجزیه کند:
(options, args) = parser.parse_args()
(در صورت تمایل، میتوانید فهرستی سفارشی از آرگومانها را به parse_args() بدهید، اما این کار بهندرت ضروری است: بهطور پیشفرض از sys.argv[1:] استفاده میکند.)
parse_args() دو مقدار بازمیگرداند:
options، شیءای حاوی مقادیر همهی گزینههای شما—برای مثال اگر--fileیک آرگومان رشتهای میگیرد، آنگاهoptions.fileنام پروندهای خواهد بود که کاربر ارائه کرده است، یاNoneاگر کاربر آن گزینه را ارائه نکرده باشدargs، فهرست آرگومانهای جایگاهی باقیمانده پس از تجزیه گزینهها
این بخش از آموزش تنها چهار مورد از مهمترین ویژگیهای گزینه را پوشش میدهد: action، type، dest (مقصد)، و help. از میان اینها، action بنیادیترین است.
درک کنشهای گزینه¶
اکشنها به optparse میگویند که هنگامی که با گزینهای در خط فرمان مواجه میشود، چه کاری انجام دهد. مجموعهای ثابت از اکشنها در optparse بهصورت سختکد وجود دارد؛ افزودن اکشنهای جدید موضوعی پیشرفته است که در بخش گسترش optparse پوشش داده شده است. بیشتر اکشنها به optparse میگویند که مقداری را در متغیری ذخیره کند—برای مثال، رشتهای را از خط فرمان بگیرد و آن را در ویژگیای از options ذخیره کند.
اگر اکشن گزینهای را مشخص نکنید، optparse بهطور پیشفرض از store استفاده میکند.
کنش store¶
رایجترین اکشن گزینه store است، که به optparse میگوید آرگومان بعدی (یا باقیماندهی آرگومان فعلی) را بگیرد، اطمینان حاصل کند که از نوع صحیح است، و آن را در مقصد انتخابی شما ذخیره کند.
برای مثال:
parser.add_option("-f", "--file",
action="store", type="string", dest="filename")
حال بیایید یک خط فرمان جعلی بسازیم و از optparse بخواهیم آن را تجزیه کند:
args = ["-f", "foo.txt"]
(options, args) = parser.parse_args(args)
وقتی optparse رشتهی گزینهی -f را میبیند، آرگومان بعدی، foo.txt، را مصرف میکند و آن را در options.filename ذخیره میکند. بنابراین، پس از این فراخوانی parse_args()، options.filename برابر "foo.txt" است.
برخی دیگر از انواع گزینههای پشتیبانیشده توسط optparse، int و float هستند. در اینجا گزینهای آمده است که انتظار یک آرگومان عدد صحیح را دارد:
parser.add_option("-n", type="int", dest="num")
توجه داشته باشید که این گزینه رشتهی گزینهی بلندی ندارد، که کاملاً قابل قبول است. همچنین، هیچ اکشن صریحی وجود ندارد، زیرا پیشفرض store است.
بیایید یک خط فرمان جعلی دیگر را تجزیه کنیم. این بار، آرگومان گزینه را دقیقاً به خود گزینه میچسبانیم: از آنجا که -n42 (یک آرگومان) معادل -n 42 (دو آرگومان) است، کد
(options, args) = parser.parse_args(["-n42"])
print(options.num)
42 را چاپ خواهد کرد.
اگر نوعی را مشخص نکنید، optparse آن را string فرض میکند. با توجه به این واقعیت که اکشن پیشفرض برابر store است، این بدان معناست که اولین مثال ما میتواند بسیار کوتاهتر باشد:
parser.add_option("-f", "--file", dest="filename")
اگر مقصدی ارائه نکنید، optparse یک پیشفرض مناسب را از رشتههای گزینه تعیین میکند: اگر اولین رشته گزینه بلند --foo-bar باشد، آنگاه مقصد پیشفرض foo_bar است. اگر هیچ رشته گزینه بلندی وجود نداشته باشد، optparse اولین رشته گزینه کوتاه را بررسی میکند: مقصد پیشفرض برای -f برابر f است.
optparse همچنین شامل نوع توکار complex میشود. افزودن انواع در بخش گسترش optparse پوشش داده شده است.
مدیریت گزینههای بولی (پرچمی)¶
گزینههای پرچمی---که هنگام مشاهدهی یک گزینهی خاص، متغیری را روی درست یا نادرست تنظیم میکنند---بسیار رایج هستند. optparse از آنها با دو اکشن جداگانه، store_true و store_false پشتیبانی میکند. برای مثال، ممکن است یک پرچم verbose داشته باشید که با -v فعال و با -q غیرفعال میشود:
parser.add_option("-v", action="store_true", dest="verbose")
parser.add_option("-q", action="store_false", dest="verbose")
در اینجا دو گزینه متفاوت با یک مقصد یکسان داریم که کاملاً قابل قبول است. (این فقط به این معناست که هنگام تنظیم مقادیر پیشفرض باید کمی دقت کنید—در زیر ببینید.)
هنگامی که optparse با -v در خط فرمان مواجه میشود، options.verbose را روی True تنظیم میکند؛ هنگامی که با -q مواجه میشود، options.verbose روی False تنظیم میشود.
سایر اکشنها¶
برخی دیگر از کنشهای پشتیبانیشده توسط optparse عبارتند از:
"store_const"ذخیرهی یک مقدار ثابت، از پیش تنظیمشده از طریق
Option.const"append"افزودن آرگومان این گزینه به یک فهرست
"count"یک شمارنده را یک واحد افزایش دهید
"callback"فراخوانی یک تابع مشخص
این موارد در بخش راهنمای مرجع و بخش کالبکهای گزینه پوشش داده شدهاند.
مقادیر پیشفرض¶
همهی مثالهای بالا شامل تنظیم یک متغیر (همان «مقصد») هنگامی است که گزینههای خاصی در خط فرمان دیده شوند. اگر آن گزینهها هرگز دیده نشوند، چه اتفاقی میافتد؟ از آنجا که هیچ مقدار پیشفرضی ارائه نکردهایم، همهی آنها روی None تنظیم میشوند. این معمولاً مشکلی ندارد، اما گاهی کنترل بیشتری میخواهید. optparse به شما امکان میدهد برای هر مقصد یک مقدار پیشفرض ارائه دهید، که پیش از تجزیهی خط فرمان اختصاص مییابد.
نخست، مثال verbose/quiet را در نظر بگیرید. اگر بخواهیم optparse مقدار verbose را روی True تنظیم کند، مگر آنکه -q مشاهده شود، میتوانیم این کار را انجام دهیم:
parser.add_option("-v", action="store_true", dest="verbose", default=True)
parser.add_option("-q", action="store_false", dest="verbose")
از آنجا که مقادیر پیشفرض به مقصد اعمال میشوند، نه به یک گزینه خاص، و این دو گزینه اتفاقاً مقصد یکسانی دارند، این دقیقاً معادل است:
parser.add_option("-v", action="store_true", dest="verbose")
parser.add_option("-q", action="store_false", dest="verbose", default=True)
این را در نظر بگیرید:
parser.add_option("-v", action="store_true", dest="verbose", default=False)
parser.add_option("-q", action="store_false", dest="verbose", default=True)
باز هم، مقدار پیشفرض برای verbose برابر True خواهد بود: آخرین مقدار پیشفرض ارائهشده برای هر مقصد مشخص، همان مقداری است که معتبر است.
راه روشنتر برای تعیین مقادیر پیشفرض، متد set_defaults() از OptionParser است که میتوانید آن را در هر زمانی پیش از فراخوانی parse_args() فراخوانی کنید:
parser.set_defaults(verbose=True)
parser.add_option(...)
(options, args) = parser.parse_args()
مانند قبل، آخرین مقدار تعیینشده برای یک مقصد گزینهی مشخص، مقداری است که معتبر است. برای شفافیت، سعی کنید برای تنظیم مقادیر پیشفرض فقط از یکی از دو روش استفاده کنید، نه از هر دو.
تولید راهنما¶
توانایی optparse در تولید خودکار متن راهنما و طرز استفاده، برای ایجاد رابطهای خط فرمان کاربرپسند مفید است. کافی است یک مقدار help برای هر گزینه ارائه دهید و بهاختیار، یک پیام کوتاه طرز استفاده برای کل برنامهتان قرار دهید. در اینجا یک OptionParser حاوی گزینههای کاربرپسند (مستندسازیشده) آمده است:
usage = "usage: %prog [options] arg1 arg2"
parser = OptionParser(usage=usage)
parser.add_option("-v", "--verbose",
action="store_true", dest="verbose", default=True,
help="make lots of noise [default]")
parser.add_option("-q", "--quiet",
action="store_false", dest="verbose",
help="be vewwy quiet (I'm hunting wabbits)")
parser.add_option("-f", "--filename",
metavar="FILE", help="write output to FILE")
parser.add_option("-m", "--mode",
default="intermediate",
help="interaction mode: novice, intermediate, "
"or expert [default: %default]")
اگر optparse با -h یا --help در خط فرمان مواجه شود، یا اگر فقط parser.print_help() را فراخوانی کنید، موارد زیر را در خروجی استاندارد چاپ میکند:
طرز استفاده: <yourscript> [options] arg1 arg2
گزینهها:
-h, --help نمایش این پیام راهنما و خروج
-v, --verbose سروصدای زیاد [پیشفرض]
-q, --quiet سکوت بسیار (من در حال شکار خرگوشها هستم)
-f FILE, --filename=FILE
نوشتن خروجی در FILE
-m MODE, --mode=MODE حالت تعامل: novice، intermediate یا
expert [پیشفرض: intermediate]
(اگر خروجی راهنما توسط یک گزینهی راهنما فعال شود، optparse پس از چاپ متن راهنما خارج میشود.)
در اینجا موارد زیادی وجود دارد که به optparse کمک میکند تا بهترین پیام راهنمای ممکن را تولید کند:
اسکریپت پیام کاربرد خود را تعریف میکند:
usage = "usage: %prog [options] arg1 arg2"
optparseمقدار%progرا در رشتهی کاربرد به نام برنامهی جاری، یعنیos.path.basename(sys.argv[0])، بسط میدهد. سپس رشتهی بسطیافته پیش از راهنمای دقیق گزینهها چاپ میشود.اگر رشتهی کاربرد را ارائه نکنید،
optparseاز یک پیشفرض ساده اما معقول استفاده میکند:"Usage: %prog [options]"، که اگر اسکریپت شما هیچ آرگومان جایگاهی دریافت نمیکند، مناسب است.هر گزینه یک رشتهی راهنما تعریف میکند و نگران شکستن سطرها نیست---
optparseشکستن سطرها و زیبا کردن خروجی راهنما را بر عهده میگیرد.گزینههایی که یک مقدار میپذیرند، این موضوع را در پیام راهنمای تولیدشده بهصورت خودکار نشان میدهند، برای مثال برای گزینه "mode":
-m MODE, --mode=MODE
در اینجا، به «MODE» فرامتغیر گفته میشود: این نشاندهندهی آرگومانی است که انتظار میرود کاربر به
-m/--modeبدهد. بهطور پیشفرض،optparseنام متغیر مقصد را به حروف بزرگ تبدیل میکند و از آن برای فرامتغیر استفاده میکند. گاهی، این آن چیزی نیست که شما میخواهید—برای مثال، گزینهی--filenameبهصراحتmetavar="FILE"را تنظیم میکند و منجر به این توضیح گزینهی تولیدشده بهصورت خودکار میشود:-f FILE, --filename=FILE
البته این موضوع فقط برای صرفهجویی در فضا مهم نیست: متن راهنمای نوشتهشده بهصورت دستی از متغیر متا (meta-variable)
FILEاستفاده میکند تا کاربر را از وجود ارتباط میان سینتکس نیمهرسمی-f FILEو توصیف معنایی غیررسمی «خروجی را در FILE بنویسید» آگاه کند. این راهی ساده اما مؤثر است که متن راهنمای شما را برای کاربران نهایی بسیار واضحتر و مفیدتر میکند.گزینههایی که مقدار پیشفرض دارند میتوانند شامل
%defaultدر رشتهی راهنما باشند---optparseآن را باstr()مقدار پیشفرض گزینه جایگزین میکند. اگر گزینهای مقدار پیشفرض نداشته باشد (یا مقدار پیشفرض آنNoneباشد)،%defaultبهnoneگسترش مییابد.
گروهبندی گزینهها¶
هنگام کار با گزینههای زیاد، گروهبندی این گزینهها برای خروجی راهنمای بهتر مناسب است. یک OptionParser میتواند شامل چندین گروه گزینه باشد، که هر یک میتواند شامل چندین گزینه باشد.
یک گروه گزینه با استفاده از کلاس OptionGroup به دست میآید:
- class optparse.OptionGroup(parser, title, description=None)¶
که در آن
parser نمونهای از
OptionParserاست که گروه در آن درج خواهد شدtitle عنوان گروه است
description، اختیاری، شرح بلندی از گروه است
OptionGroup از OptionContainer ارث میبرد (مانند OptionParser) و بنابراین میتوان از متد add_option() برای افزودن یک گزینه به گروه استفاده کرد.
پس از تعریف همهی گزینهها، گروه با استفاده از متد add_option_group() از کلاس OptionParser به پارسری که پیشتر تعریف شده است اضافه میشود.
با ادامهی کار با پارسر تعریفشده در بخش پیشین، افزودن یک OptionGroup به پارسر آسان است:
group = OptionGroup(parser, "Dangerous Options",
"Caution: use these options at your own risk. "
"It is believed that some of them bite.")
group.add_option("-g", action="store_true", help="Group option.")
parser.add_option_group(group)
این منجر به خروجی help زیر میشود:
طرز استفاده: <yourscript> [options] arg1 arg2
گزینهها:
-h, --help نمایش این پیام راهنما و خروج
-v, --verbose ایجاد سروصدای زیاد [پیشفرض]
-q, --quiet بسیار ساکت باشید (من در حال شکار خرگوشها هستم)
-f FILE, --filename=FILE
نوشتن خروجی در FILE
-m MODE, --mode=MODE حالت تعامل: novice، intermediate یا
expert [پیشفرض: intermediate]
گزینههای خطرناک:
احتیاط: از این گزینهها با مسئولیت خودتان استفاده کنید. تصور میشود برخی
از آنها گاز بگیرند.
-g گزینه گروهی.
یک مثال کمی کاملتر ممکن است شامل استفاده از بیش از یک گروه باشد: همچنان مثال قبلی را گسترش میدهیم:
group = OptionGroup(parser, "Dangerous Options",
"Caution: use these options at your own risk. "
"It is believed that some of them bite.")
group.add_option("-g", action="store_true", help="Group option.")
parser.add_option_group(group)
group = OptionGroup(parser, "Debug Options")
group.add_option("-d", "--debug", action="store_true",
help="Print debug information")
group.add_option("-s", "--sql", action="store_true",
help="Print all SQL statements executed")
group.add_option("-e", action="store_true", help="Print every action done")
parser.add_option_group(group)
که منجر به خروجی زیر میشود:
کاربرد: <yourscript> [options] arg1 arg2
گزینهها:
-h, --help نمایش این پیام راهنما و خروج
-v, --verbose ایجاد سر و صدای زیاد [پیشفرض]
-q, --quiet بسیار ساکت بودن (من در حال شکار خرگوشها هستم)
-f FILE, --filename=FILE
نوشتن خروجی در FILE
-m MODE, --mode=MODE حالت تعامل: novice، intermediate یا expert
[پیشفرض: intermediate]
گزینههای خطرناک:
احتیاط: استفاده از این گزینهها با مسئولیت خودتان است. اعتقاد بر این است که برخی
از آنها گاز میگیرند.
-g گزینه گروهی.
گزینههای اشکالزدایی:
-d, --debug چاپ اطلاعات اشکالزدایی
-s, --sql چاپ تمام دستورات SQL اجراشده
-e چاپ هر عمل انجامشده
یکی دیگر از متدهای جالب، بهویژه هنگام کار بهصورت برنامهای با گروههای گزینه، عبارت است از:
- OptionParser.get_option_group(opt_str)¶
OptionGroupای را برگردانید که رشتهی گزینهی کوتاه یا بلند opt_str (مثلاً'-o'یا'--option') به آن تعلق دارد. اگر چنینOptionGroupای وجود نداشت،Noneرا برگردانید.
چاپ رشتهی نسخه¶
همانند رشته کاربرد کوتاه، optparse همچنین میتواند یک رشته نسخه برای برنامه شما چاپ کند. شما باید رشته را بهعنوان آرگومان version به OptionParser ارائه دهید:
parser = OptionParser(usage="%prog [-f] [-q]", version="%prog 1.0")
%prog درست مانند آنچه در usage انجام میشود، بسط داده میشود. جدای از آن، version میتواند شامل هر چیزی باشد که شما بخواهید. هنگامی که آن را فراهم کنید، optparse بهطور خودکار یک گزینه --version به پارسر شما اضافه میکند. اگر با این گزینه در خط فرمان مواجه شود، رشته version شما را (با جایگزین کردن %prog) بسط میدهد، آن را در stdout چاپ میکند و خارج میشود.
برای مثال، اگر اسکریپت شما /usr/bin/foo نام داشته باشد:
$ /usr/bin/foo --version
foo 1.0
میتوان از دو متد زیر برای چاپ و دریافت رشتهی version استفاده کرد:
- OptionParser.print_version(file=None)¶
پیام نسخه برنامه جاری (
self.version) را در file (پیشفرض: stdout) چاپ میکند. همانندprint_usage()، هر رخداد%progدرself.versionبا نام برنامه جاری جایگزین میشود. اگرself.versionخالی یا تعریفنشده باشد، هیچ کاری انجام نمیدهد.
- OptionParser.get_version()¶
مشابه
print_version()است، اما به جای چاپ کردن آن، رشته نسخه را برمیگرداند.
چگونگی مدیریت خطاها در optparse¶
دو دستهی کلی از خطاها وجود دارد که optparse باید به آنها رسیدگی کند: خطاهای برنامهنویس و خطاهای کاربر. خطاهای برنامهنویس معمولاً فراخوانیهای نادرست به OptionParser.add_option() هستند، مثلاً رشتههای گزینهی نامعتبر، ویژگیهای گزینهی ناشناخته، ویژگیهای گزینهی مفقود و غیره. با این موارد به شیوهی معمول برخورد میشود: استثنایی پرتاب میشود (یا optparse.OptionError یا TypeError) و اجازه داده میشود برنامه فروپاشد.
مدیریت خطاهای کاربر بسیار مهمتر است، زیرا صرفنظر از میزان پایداری کد شما، وقوع آنها حتمی است. optparse میتواند برخی خطاهای کاربر، مانند آرگومانهای نامعتبر گزینه (ارسال -n 4x در جایی که -n آرگومانی از نوع عدد صحیح میگیرد) یا آرگومانهای جاافتاده (-n در انتهای خط فرمان، جایی که -n آرگومانی از هر نوعی میگیرد) را بهطور خودکار تشخیص دهد. همچنین میتوانید OptionParser.error() را برای اعلام وضعیت خطای تعریفشده توسط برنامه فراخوانی کنید:
(options, args) = parser.parse_args()
...
if options.a and options.b:
parser.error("options -a and -b are mutually exclusive")
در هر صورت، optparse خطا را به یک شکل مدیریت میکند: پیام استفادهی برنامه و یک پیام خطا را در خطای استاندارد چاپ میکند و با وضعیت خطای ۲ خارج میشود.
اولین مثال بالا را در نظر بگیرید، که در آن کاربر 4x را به گزینهای که یک عدد صحیح میپذیرد، ارسال میکند:
$ /usr/bin/foo -n 4x
Usage: foo [options]
foo: error: option -n: invalid integer value: '4x'
یا، در حالتی که کاربر اصلاً مقداری ارسال نمیکند:
$ /usr/bin/foo -n
استفاده: foo [گزینهها]
foo: خطا: گزینهی -n به یک آرگومان نیاز دارد
پیامهای خطای تولیدشده توسط optparse همیشه گزینهی مرتبط با خطا را ذکر میکنند؛ هنگام فراخوانی OptionParser.error() از کد برنامهتان، حتماً همین کار را انجام دهید.
اگر رفتار پیشفرض مدیریت خطای optparse مناسب نیازهای شما نیست، باید یک زیرکلاس از OptionParser بسازید و متدهای exit() و/یا error() آن را بازنویسی کنید.
کنار هم قرار دادن همه موارد¶
اسکریپتهای مبتنی بر optparse معمولاً به این شکل هستند:
from optparse import OptionParser
...
def main():
usage = "usage: %prog [options] arg"
parser = OptionParser(usage)
parser.add_option("-f", "--file", dest="filename",
help="read data from FILENAME")
parser.add_option("-v", "--verbose",
action="store_true", dest="verbose")
parser.add_option("-q", "--quiet",
action="store_false", dest="verbose")
...
(options, args) = parser.parse_args()
if len(args) != 1:
parser.error("incorrect number of arguments")
if options.verbose:
print("reading %s..." % options.filename)
...
if __name__ == "__main__":
main()
راهنمای مرجع¶
ایجاد پارسر¶
نخستین گام در استفاده از optparse، ایجاد یک نمونه از OptionParser است.
- class optparse.OptionParser(...)¶
سازندهی OptionParser هیچ آرگومان الزامی ندارد، اما تعدادی آرگومان کلیدواژهای اختیاری دارد. شما باید همیشه آنها را بهصورت آرگومانهای کلیدواژهای ارسال کنید، یعنی به ترتیب اعلام آرگومانها اتکا نکنید.
usage(پیشفرض:"%prog [options]")خلاصهی کاربردی که هنگام اجرای نادرست برنامهی شما یا همراه با گزینهی راهنما چاپ میشود. وقتی
optparseرشتهی کاربرد را چاپ میکند،%progرا بهos.path.basename(sys.argv[0])بسط میدهد (یا اگر آن آرگومان کلیدواژهای را فرستاده باشید، بهprog). برای جلوگیری از نمایش پیام کاربرد، مقدار ویژهیoptparse.SUPPRESS_USAGEرا بفرستید.option_list(پیشفرض:[])فهرستی از اشیای Option که با آنها پارسر پر میشود. گزینههای موجود در
option_listپس از همهی گزینههای موجود درstandard_option_list(یک صفت کلاس که ممکن است توسط زیرکلاسهای OptionParser تنظیم شود)، اما پیش از هر گزینهی نسخه یا راهنما افزوده میشوند. منسوخ؛ در عوض پس از ایجاد پارسر ازadd_option()استفاده کنید.option_class(پیشفرض: optparse.Option)کلاس مورد استفاده هنگام افزودن گزینهها به پارسر در
add_option().version(پیشفرض:None)یک رشتهی نسخه برای چاپ هنگامی که کاربر یک گزینهی نسخه ارائه میدهد. اگر برای
versionیک مقدار درست ارائه دهید،optparseبهطور خودکار یک گزینهی نسخه با تنها رشتهی گزینهی--versionاضافه میکند. زیررشتهی%progهمانندusageبسط داده میشود.conflict_handler(پیشفرض:"error")مشخص میکند که وقتی گزینههایی با رشتههای گزینهی متعارض به پارسر افزوده میشوند، چه کاری باید انجام شود؛ بخش تعارض بین گزینهها را ببینید.
description(پیشفرض:None)پاراگرافی از متن که مروری کوتاه بر برنامهی شما ارائه میدهد.
optparseاین پاراگراف را متناسب با عرض پایانهی جاری قالببندی مجدد میکند و هنگامی که کاربر درخواست راهنمایی میکند، آن را چاپ میکند (بعد ازusage، اما قبل از فهرست گزینهها).formatter(پیشفرض: یکIndentedHelpFormatterجدید)نمونهای از optparse.HelpFormatter که برای چاپ متن راهنما استفاده خواهد شد.
optparseدو کلاس عینی برای این منظور فراهم میکند: IndentedHelpFormatter و TitledHelpFormatter.add_help_option(پیشفرض:True)اگر درست باشد،
optparseیک گزینه راهنما (با رشتههای گزینه-hو--help) را به پارسر میافزاید.progرشتهای که هنگام بسط
%progدرusageوversionبهجایos.path.basename(sys.argv[0])استفاده میشود.epilog(پیشفرض:None)بندی از متن راهنما برای نمایش پس از راهنمای گزینه.
پر کردن پارسر¶
چندین روش برای پر کردن پارسر با گزینهها وجود دارد. روش ترجیحی استفاده از OptionParser.add_option() است، همانطور که در بخش آموزش نشان داده شده است. add_option() میتواند به یکی از دو روش فراخوانی شود:
یک نمونه Option (مانند آنچه
make_option()برمیگرداند) به آن بدهیدهر ترکیبی از آرگومانهای جایگاهی و کلیدواژهای قابلقبول برای
make_option()(یعنی برای سازندهی Option) را به آن بدهید، تا نمونهی Option را برای شما ایجاد کند
جایگزین دیگر این است که فهرستی از نمونههای Option از پیش ساختهشده را به سازنده OptionParser ارسال کنید، همانطور که در ادامه میآید:
option_list = [
make_option("-f", "--filename",
action="store", type="string", dest="filename"),
make_option("-q", "--quiet",
action="store_false", dest="verbose"),
]
parser = OptionParser(option_list=option_list)
(make_option() یک تابع کارخانه برای ایجاد نمونههای Option است؛ در حال حاضر، این تابع نام مستعاری برای سازندهی Option است. نسخهای آینده از optparse ممکن است Option را به چند کلاس تقسیم کند و make_option() کلاس مناسب را برای نمونهسازی انتخاب خواهد کرد. Option را بهصورت مستقیم نمونهسازی نکنید.)
تعریف گزینهها¶
هر نمونه از Option نشاندهنده مجموعهای از رشتههای گزینه خط فرمان هممعنی است، مثلاً -f و --file. شما میتوانید هر تعداد رشته گزینه کوتاه یا بلند را مشخص کنید، اما باید دستکم یک رشته گزینه در مجموع مشخص کنید.
روش کانونیکال برای ایجاد یک نمونه از Option، استفاده از متد add_option() از OptionParser است.
- OptionParser.add_option(option)¶
- OptionParser.add_option(*opt_str, attr=value, ...)
برای تعریف گزینهای فقط با یک رشتهی گزینه کوتاه:
parser.add_option("-f", attr=value, ...)
و برای تعریف یک گزینه فقط با یک رشتهی گزینهی بلند:
parser.add_option("--foo", attr=value, ...)
آرگومانهای کلیدواژهای ویژگیهای شیء جدید Option را تعریف میکنند. مهمترین ویژگی Option
actionاست، و تا حد زیادی تعیین میکند که کدامیک از ویژگیهای دیگر مرتبط یا ضروری هستند. اگر ویژگیهای Option نامرتبط را ارسال کنید یا ویژگیهای ضروری را ارسال نکنید،optparseاستثنایOptionErrorرا پرتاب میکند که اشتباه شما را توضیح میدهد.کنش یک گزینه مشخص میکند که
optparseهنگام مواجهه با این گزینه در خط فرمان چه کاری انجام میدهد. کنشهای استاندارد گزینه که بهصورت سختکد درoptparseقرار دارند عبارتند از:"store"ذخیرهی آرگومان این گزینه (پیشفرض)
"store_const"ذخیرهی یک مقدار ثابت، از پیش تنظیمشده از طریق
Option.const"store_true"Trueرا ذخیره میکند"store_false"Falseرا ذخیره میکند"append"افزودن آرگومان این گزینه به یک فهرست
"append_const"افزودن یک مقدار ثابت به یک فهرست، پیشتنظیمشده از طریق
Option.const"count"یک شمارنده را یک واحد افزایش دهید
"callback"فراخوانی یک تابع مشخص
"help"یک پیام کاربرد شامل همهی گزینهها و مستندات آنها را چاپ میکند
(اگر یک اکشن ارائه ندهید، پیشفرض
"store"است. برای این کنش، همچنین میتوانید ویژگیهای گزینهtypeوdestرا نیز ارائه دهید؛ اکشنهای استاندارد گزینهها را ببینید.)
همانطور که میبینید، بیشتر اکشنهای شامل ذخیره یا بهروزرسانی یک مقدار در جایی هستند. optparse همیشه برای این منظور یک شیء خاص ایجاد میکند، که بهطور قراردادی options نامیده میشود و نمونهای از optparse.Values است.
- class optparse.Values¶
شیءای که نامهای آرگومانهای تجزیهشده و مقدارهای آنها را بهعنوان ویژگیها نگهداری میکند. معمولاً هنگام فراخوانی
OptionParser.parse_args()ایجاد میشود، و میتواند با یک زیرکلاس سفارشی که به آرگومان values درOptionParser.parse_args()ارسال میشود، بازنویسی شود (همانطور که در تجزیهی آرگومانها توضیح داده شده است).
آرگومانهای گزینه (و مقادیر مختلف دیگر) بهعنوان ویژگیهای این شیء ذخیره میشوند، بر اساس ویژگی گزینهی dest (مقصد).
برای مثال، هنگامی که فراخوانی میکنید
parser.parse_args()
یکی از اولین کارهایی که optparse انجام میدهد، ایجاد شیء options است:
options = Values()
اگر یکی از گزینههای این پارسر به این صورت تعریف شده باشد
parser.add_option("-f", "--file", action="store", type="string", dest="filename")
و خط فرمانی که تجزیه میشود شامل هر یک از موارد زیر است:
-ffoo
-f foo
--file=foo
--file foo
سپس optparse، با دیدن این گزینه، معادل دستور زیر را انجام میدهد
options.filename = "foo"
ویژگیهای گزینه type و dest تقریباً به اندازه action مهم هستند، اما action تنها موردی است که برای همه گزینهها معنا دارد.
ویژگیهای گزینه¶
- class optparse.Option¶
یک آرگومان خط فرمان واحد، با ویژگیهای گوناگون که بهعنوان آرگومانهای کلیدواژهای به سازنده ارسال میشوند. معمولاً بهجای ایجاد مستقیم، با
OptionParser.add_option()ایجاد میشود و میتوان آن را با یک کلاس سفارشی از طریق آرگومان option_class برایOptionParserجایگزین کرد.
میتوان ویژگیهای گزینهی زیر را بهعنوان آرگومانهای کلیدواژهای به OptionParser.add_option() ارسال کرد. اگر ویژگی گزینهای را ارسال کنید که به گزینه خاصی مرتبط نیست، یا ویژگی لازمِ گزینه را ارسال نکنید، optparse استثنای OptionError را پرتاب میکند.
- Option.action¶
(پیشفرض:
"store")رفتار
optparseرا هنگامی که این گزینه در خط فرمان مشاهده شود، تعیین میکند؛ گزینههای موجود در اینجا مستند شدهاند.
- Option.type¶
(پیشفرض:
"string")نوع آرگومان مورد انتظار این گزینه (مثلاً
"string"یا"int")؛ انواع گزینههای موجود در اینجا مستند شدهاند.
- Option.dest¶
(پیشفرض: مشتقشده از رشتههای گزینه)
اگر کنش گزینه مستلزم نوشتن یا تغییر مقداری در جایی باشد، این به
optparseمیگوید که آن را کجا بنویسد:destنام ویژگیای از شیءoptionsاست کهoptparseهنگام تجزیه خط فرمان آن را میسازد.
- Option.default¶
مقداری که اگر این گزینه در خط فرمان مشاهده نشود، برای مقصد این گزینه استفاده میشود. همچنین
OptionParser.set_defaults()را ببینید.
- Option.nargs¶
(پیشفرض: ۱)
هنگامی که این گزینه مشاهده میشود، چند آرگومان از نوع
typeباید مصرف شوند. اگر بیش از ۱ باشد،optparseیک تاپل از مقادیر را درdestذخیره میکند.
- Option.const¶
برای کنشهایی که یک مقدار ثابت را ذخیره میکنند، مقدار ثابتی که باید ذخیره شود.
- Option.choices¶
برای گزینههایی از نوع
"choice"، فهرست رشتههایی که کاربر میتواند از میان آنها انتخاب کند.
- Option.callback¶
برای گزینههایی با اکشن
"callback"، شیء فراخوانیپذیر که هنگام مشاهدهی این گزینه فراخوانی میشود. برای جزئیات آرگومانهای ارسالشده به این شیء فراخوانیپذیر، بخش کالبکهای گزینه را ببینید.
- Option.callback_args¶
- Option.callback_kwargs¶
آرگومانهای جایگاهی و کلیدواژهای اضافی برای ارسال به
callbackپس از چهار آرگومان استاندارد کالبک.
اکشنهای استاندارد گزینهها¶
کنشهای مختلف گزینه همگی الزامات و اثرات کمی متفاوتی دارند. بیشتر کنشها چندین ویژگی مرتبط با گزینه دارند که میتوانید آنها را برای هدایت رفتار optparse مشخص کنید؛ تعداد کمی دارای ویژگیهای الزامی هستند که باید آنها را برای هر گزینهای که از آن کنش استفاده میکند مشخص کنید.
"store"[مرتبط:type،dest،nargs،choices]پس از این گزینه باید یک آرگومان بیاید که بر اساس
typeبه یک مقدار تبدیل میشود و درdestذخیره میشود. اگرnargs> 1 باشد، چند آرگومان از خط فرمان مصرف میشوند؛ تمام آنها بر اساسtypeتبدیل میشوند و بهصورت یک تاپل درdestذخیره میشوند. بخش انواع گزینههای استاندارد را ببینید.اگر
choicesارائه شده باشد (یک فهرست یا تاپل از رشتهها)، نوع بهطور پیشفرض"choice"خواهد بود.اگر
typeارائه نشود، مقدار پیشفرض آن"string"خواهد بود.اگر
destارائه نشود،optparseمقصدی را از اولین رشتهی گزینهی بلند استخراج میکند (برای مثال،--foo-barبه معنایfoo_barاست). اگر هیچ رشتهی گزینهی بلندی وجود نداشته باشد،optparseمقصدی را از اولین رشتهی گزینهی کوتاه استخراج میکند (برای مثال،-fبه معنایfاست).مثال:
parser.add_option("-f") parser.add_option("-p", type="float", nargs=3, dest="point")
هنگام تجزیه خط فرمان
-f foo.txt -p 1 -3.5 4 -fbar.txt
optparseتنظیم خواهد کردoptions.f = "foo.txt" options.point = (1.0, -3.5, 4.0) options.f = "bar.txt"
"store_const"[الزامی:const؛ مرتبط:dest]مقدار
constدرdestذخیره میشود.مثال:
parser.add_option("-q", "--quiet", action="store_const", const=0, dest="verbose") parser.add_option("-v", "--verbose", action="store_const", const=1, dest="verbose") parser.add_option("--noisy", action="store_const", const=2, dest="verbose")
اگر
--noisyدیده شود،optparseتنظیم خواهد کردoptions.verbose = 2
"store_true"[مرتبط:dest]حالت خاصی از
"store_const"کهTrueرا درdestذخیره میکند."store_false"[مرتبط:dest]مانند
"store_true"، اماFalseرا ذخیره میکند.مثال:
parser.add_option("--clobber", action="store_true", dest="clobber") parser.add_option("--no-clobber", action="store_false", dest="clobber")
"append"[مرتبط:type،dest،nargs،choices]پس از این گزینه باید یک آرگومان بیاید، که به فهرست موجود در
destافزوده میشود. اگر مقدار پیشفرضی برایdestارائه نشده باشد، هنگامی کهoptparseبرای اولین بار این گزینه را در خط فرمان مشاهده کند، بهطور خودکار یک فهرست خالی ایجاد میشود. اگرnargs> ۱ باشد، چندین آرگومان مصرف میشود و تاپلی به طولnargsبهdestافزوده میشود.مقادیر پیشفرض برای
typeوdestهمان مقادیر پیشفرض برای کنش"store"هستند.مثال:
parser.add_option("-t", "--tracks", action="append", type="int")
اگر
-t3در خط فرمان دیده شود،optparseمعادل زیر را انجام میدهد:options.tracks = [] options.tracks.append(int("3"))
اگر کمی بعد
--tracks=4دیده شود، این کار را انجام میدهد:options.tracks.append(int("4"))
اکشن
append، متدappendرا روی مقدار فعلی گزینه فراخوانی میکند. این بدان معناست که هر مقدار پیشفرض مشخصشده باید یک متدappendداشته باشد. همچنین بدان معناست که اگر مقدار پیشفرض غیرخالی باشد، عناصر پیشفرض در مقدار تجزیهشده برای گزینه وجود خواهند داشت و هر مقداری از خط فرمان پس از آن مقادیر پیشفرض اضافه میشود:>>> parser.add_option("--files", action="append", default=['~/.mypkg/defaults']) >>> opts, args = parser.parse_args(['--files', 'overrides.mypkg']) >>> opts.files ['~/.mypkg/defaults', 'overrides.mypkg']
"append_const"[الزامی:const؛ مرتبط:dest]مانند
"store_const"، اما مقدارconstبهdestافزوده میشود؛ همانند"append"، مقدار پیشفرضdestبرابرNoneاست و در اولین مواجهه با گزینه، یک فهرست خالی بهطور خودکار ایجاد میشود."count"[مرتبط:dest]عدد صحیح ذخیرهشده در
destرا افزایش میدهد. اگر مقدار پیشفرضی ارائه نشود،destپیش از نخستین افزایش، روی صفر تنظیم میشود.مثال:
parser.add_option("-v", action="count", dest="verbosity")
نخستین باری که
-vدر خط فرمان دیده شود،optparseمعادل زیر را انجام میدهد:options.verbosity = 0 options.verbosity += 1
هر تکرار بعدی
-vمنجر میشود بهoptions.verbosity += 1
"callback"[الزامی:callback؛ مرتبط:type،nargs،callback_args،callback_kwargs]تابع مشخصشده توسط
callbackرا فراخوانی میکند، که بهصورت زیر فراخوانی میشودfunc(option, opt_str, value, parser, *args, **kwargs)
برای جزئیات بیشتر، بخش کالبکهای گزینه را ببینید.
"help"یک پیام راهنمای کامل برای همهی گزینهها در پارسر فعلی گزینهها (option parser) چاپ میکند. پیام راهنما از رشتهی
usageارسالشده به سازندهی OptionParser و رشتهیhelpارسالشده به هر گزینه ساخته میشود.اگر برای یک گزینه، رشتهی
helpارائه نشود، آن گزینه همچنان در پیام راهنما فهرست میشود. برای حذف کامل یک گزینه، از مقدار ویژهیoptparse.SUPPRESS_HELPاستفاده کنید.optparseبهطور خودکار گزینهیhelpرا به تمام OptionParserها اضافه میکند، بنابراین شما معمولاً نیازی به ایجاد آن ندارید.مثال:
from optparse import OptionParser, SUPPRESS_HELP # usually, a help option is added automatically, but that can # be suppressed using the add_help_option argument parser = OptionParser(add_help_option=False) parser.add_option("-h", "--help", action="help") parser.add_option("-v", action="store_true", dest="verbose", help="Be moderately verbose") parser.add_option("--file", dest="filename", help="Input file to read data from") parser.add_option("--secret", help=SUPPRESS_HELP)
اگر
optparseهر یک از-hیا--helpرا در خط فرمان ببیند، چیزی شبیه پیام راهنمای زیر را در stdout چاپ میکند (با فرض اینکهsys.argv[0]برابر"foo.py"باشد):طرز استفاده: foo.py [گزینهها] گزینهها: -h, --help نمایش این پیام راهنما و خروج -v تا حدی پرگو باشد --file=FILENAME پرونده ورودی برای خواندن دادهها از آن
پس از چاپ پیام راهنما،
optparseفرایند شما را باsys.exit(0)خاتمه میدهد."version"شماره نسخه ارائهشده به OptionParser را در stdout چاپ میکند و خارج میشود. شماره نسخه در واقع توسط متد
print_version()از OptionParser قالببندی و چاپ میشود. بهطور کلی فقط در صورتی مرتبط است که آرگومانversionبه سازنده OptionParser ارائه شده باشد. مانند گزینههایhelp، بهندرت گزینههایversionرا ایجاد خواهید کرد، زیراoptparseدر صورت نیاز آنها را بهطور خودکار اضافه میکند.
انواع گزینههای استاندارد¶
optparse دارای پنج نوع گزینهی توکار است: "string"، "int"، "choice"، "float" و "complex". اگر نیاز به افزودن انواع جدید گزینه دارید، بخش گسترش optparse را ببینید.
آرگومانهای مربوط به گزینههای رشتهای به هیچ وجه بررسی یا تبدیل نمیشوند: متن خط فرمان، همانطور که هست، در مقصد ذخیره میشود (یا به کالبک ارسال میشود).
آرگومانهای عدد صحیح (نوع "int") بهصورت زیر تجزیه میشوند:
اگر عدد با
0xشروع شود، بهعنوان عدد مبنای شانزده تجزیه میشوداگر عدد با
0شروع شود، بهعنوان عدد مبنای هشت تجزیه میشوداگر عدد با
0bشروع شود، بهعنوان یک عدد مبنای دو تجزیه میشوددر غیر این صورت، عدد بهعنوان یک عدد مبنای ده تجزیه میشود
این تبدیل با فراخوانی int() با مبنای مناسب (۲، ۸، ۱۰ یا ۱۶) انجام میشود. اگر این تبدیل ناموفق باشد، optparse نیز ناموفق خواهد بود، هرچند با پیام خطای مفیدتری.
آرگومانهای گزینه "float" و "complex" مستقیماً با float() و complex() تبدیل میشوند و مدیریت خطای مشابهی دارند.
گزینههای "choice" زیرنوعی از گزینههای "string" هستند. ویژگی گزینه choices (یک دنباله از رشتهها) مجموعهای از آرگومانهای مجاز گزینه را تعریف میکند. optparse.check_choice() آرگومانهای گزینه ارائهشده توسط کاربر را با این فهرست مرجع مقایسه میکند و اگر رشته نامعتبری داده شود، OptionValueError را پرتاب میکند.
تجزیهی آرگومانها¶
هدف اصلی از ایجاد و پر کردن یک OptionParser، فراخوانی متد parse_args() آن است.
- OptionParser.parse_args(args=None, values=None)¶
گزینههای خط فرمان موجود در args را تجزیه کنید.
پارامترهای ورودی عبارتند از
argsفهرست آرگومانها برای پردازش (پیشفرض:
sys.argv[1:])valuesیک شیء
Valuesبرای ذخیرهی آرگومانهای گزینه در آن (پیشفرض: یک نمونه جدید ازValues) -- اگر یک شیء موجود بدهید، پیشفرضهای گزینهها روی آن مقداردهی اولیه نمیشوند
و مقدار بازگشتی یک جفت
(options, args)است کهoptionsهمان شیءای که بهعنوان values ارسال شده است، یا نمونهی
optparse.Valuesکه توسطoptparseایجاد شده استargsآرگومانهای جایگاهی باقیمانده پس از پردازش همهی گزینهها
رایجترین کاربرد این است که هیچیک از آرگومانهای کلیدواژهای ارائه نشود. اگر values را ارائه دهید، با فراخوانیهای مکرر setattr() تغییر داده میشود (تقریباً یک فراخوانی برای هر آرگومان گزینهای که در یک مقصد گزینه ذخیره میشود) و توسط parse_args() برگردانده میشود.
اگر parse_args() با خطایی در فهرست آرگومانها مواجه شود، متد error() از OptionParser را با یک پیام خطای مناسب برای کاربر نهایی فراخوانی میکند. این موضوع در نهایت فرایند شما را با وضعیت خروجی ۲ (وضعیت خروجی مرسوم یونیکس برای خطاهای خط فرمان) خاتمه میدهد.
پرسوجو و دستکاری پارسر گزینههای شما (option parser)¶
رفتار پیشفرض پارسر گزینهها (option parser) را میتوان تا حدی سفارشی کرد، و شما همچنین میتوانید در پارسر گزینههای خود کاوش کنید و ببینید چه مواردی در آن وجود دارد. OptionParser چندین متد برای کمک به شما فراهم میکند:
- OptionParser.disable_interspersed_args()¶
تجزیه را طوری تنظیم کنید که در اولین آرگومانی که گزینه نیست متوقف شود. برای مثال، اگر
-aو-bهر دو گزینههای سادهای باشند که آرگومانی نمیگیرند،optparseمعمولاً این سینتکس را میپذیرد:prog -a arg1 -b arg2
و آن را معادل در نظر میگیرد
prog -a -b arg1 arg2
برای غیرفعال کردن این قابلیت،
disable_interspersed_args()را فراخوانی کنید. این کار سینتکس سنتی یونیکس را بازمیگرداند، که در آن تجزیه گزینهها با نخستین آرگومان غیرگزینهای متوقف میشود.اگر پردازندهی فرمانی دارید که فرمان دیگری با گزینههای خودش را اجرا میکند و میخواهید مطمئن شوید که این گزینهها اشتباه گرفته نمیشوند، از این استفاده کنید. برای مثال، ممکن است هر فرمان مجموعهای متفاوت از گزینهها داشته باشد.
- OptionParser.enable_interspersed_args()¶
تجزیه را طوری تنظیم کنید که در نخستین غیرگزینه متوقف نشود و امکان قرار دادن سوئیچها در میان آرگومانهای فرمان فراهم شود. این رفتار پیشفرض است.
- OptionParser.get_option(opt_str)¶
نمونهی Option با رشتهی گزینه opt_str را برمیگرداند، یا اگر هیچ گزینهای آن رشتهی گزینه را نداشته باشد،
Noneرا برمیگرداند.
- OptionParser.has_option(opt_str)¶
اگر OptionParser گزینهای با رشتهی گزینه opt_str (مثلاً
-qیا--verbose) داشته باشد،Trueرا برمیگرداند.
- OptionParser.remove_option(opt_str)¶
اگر
OptionParserگزینهای متناظر با opt_str داشته باشد، آن گزینه حذف میشود. اگر آن گزینه رشتههای گزینهی دیگری را فراهم کرده باشد، همهی آن رشتههای گزینه نامعتبر میشوند. اگر opt_str در هیچیک از گزینههای متعلق به اینOptionParserوجود نداشته باشد،ValueErrorپرتاب میشود.
تعارض بین گزینهها¶
اگر مراقب نباشید، بهراحتی میتوانید گزینههایی با رشتههای گزینه متعارض تعریف کنید:
parser.add_option("-n", "--dry-run", ...)
...
parser.add_option("-n", "--noisy", ...)
(این امر بهویژه زمانی صادق است که شما زیرکلاس OptionParser خودتان را با برخی گزینههای استاندارد تعریف کرده باشید.)
هر بار که گزینهای را اضافه میکنید، optparse تعارضهای آن با گزینههای موجود را بررسی میکند. اگر موردی پیدا کند، سازوکار فعلی مدیریت تعارض را فراخوانی میکند. میتوانید سازوکار مدیریت تعارض را یا در سازنده تنظیم کنید:
parser = OptionParser(..., conflict_handler=handler)
یا با یک فراخوانی جداگانه:
parser.set_conflict_handler(handler)
مدیرهای تعارض (conflict handlers) موجود عبارتند از:
"error"(پیشفرض)تداخل گزینهها را یک خطای برنامهنویسی فرض میکند و
OptionConflictErrorرا پرتاب میکند"resolve"حل تعارض گزینهها بهصورت هوشمندانه (در زیر ببینید)
بهعنوان مثال، بیایید یک OptionParser تعریف کنیم که تعارضها را بهصورت هوشمندانه حل کند و گزینههای متعارض را به آن اضافه کنیم:
parser = OptionParser(conflict_handler="resolve")
parser.add_option("-n", "--dry-run", ..., help="do no harm")
parser.add_option("-n", "--noisy", ..., help="be noisy")
در این نقطه، optparse تشخیص میدهد که گزینهای که پیشتر افزوده شده است، در حال حاضر از رشتهی گزینهی -n استفاده میکند. از آنجا که conflict_handler برابر "resolve" است، این موقعیت را با حذف -n از فهرست رشتههای گزینهی مربوط به گزینهی پیشین حل میکند. اکنون --dry-run تنها راه کاربر برای فعالسازی آن گزینه است. اگر کاربر راهنمایی بخواهد، پیام راهنمایی این موضوع را منعکس خواهد کرد:
Options:
--dry-run do no harm
...
-n, --noisy be noisy
میتوان رشتههای گزینهی یک گزینهی پیشتر افزودهشده را بهتدریج حذف کرد تا هیچ رشتهای باقی نماند و کاربر دیگر راهی برای فراخوانی آن گزینه از خط فرمان نداشته باشد. در این صورت، optparse آن گزینه را بهطور کامل حذف میکند، بنابراین در متن راهنما یا هیچ جای دیگری نمایش داده نمیشود. ادامهی کار با OptionParser موجود:
parser.add_option("--dry-run", ..., help="new dry-run option")
در این نقطه، گزینه اصلی -n/--dry-run دیگر در دسترس نیست، بنابراین optparse آن را حذف میکند و این متن راهنما را باقی میگذارد:
Options:
...
-n, --noisy be noisy
--dry-run new dry-run option
پاکسازی¶
نمونههای OptionParser چندین ارجاع حلقهای دارند. این موضوع نباید برای زبالهرو پایتون مشکلی ایجاد کند، اما ممکن است بخواهید پس از اتمام کار با OptionParser خود، با فراخوانی destroy() روی آن، ارجاعهای حلقهای را بهصراحت بشکنید. این کار بهویژه در برنامههای با اجرای طولانی مفید است که در آنها گرافهای بزرگ شیء از OptionParser شما قابلدسترسی هستند.
متدهای دیگر¶
OptionParser از چندین متد عمومی دیگر پشتیبانی میکند:
- OptionParser.set_usage(usage)¶
رشته کاربرد را مطابق قواعدی که در بالا برای آرگومان کلیدواژهای
usageدر سازنده توضیح داده شد، تنظیم کنید. با گذراندنNone، رشته کاربرد پیشفرض تنظیم میشود؛ برای جلوگیری از نمایش پیام کاربرد ازoptparse.SUPPRESS_USAGEاستفاده کنید.
- OptionParser.print_usage(file=None)¶
پیام طرز استفاده برای برنامه جاری (
self.usage) را در file (پیشفرض stdout) چاپ میکند. هر مورد از رشته%progدرself.usageبا نام برنامه جاری جایگزین میشود. اگرself.usageخالی یا تعریفنشده باشد، کاری انجام نمیدهد.
- OptionParser.get_usage()¶
مانند
print_usage()است اما به جای چاپ کردن، رشتهی کاربرد را برمیگرداند.
- OptionParser.set_defaults(dest=value, ...)¶
مقادیر پیشفرض چندین مقصد گزینه را یکجا تنظیم کنید. استفاده از
set_defaults()روش ترجیحدادهشده برای تنظیم مقادیر پیشفرض گزینهها است، زیرا چندین گزینه میتوانند یک مقصد مشترک داشته باشند. برای مثال، اگر چندین گزینهی «mode» همگی یک مقصد را تنظیم کنند، هر یک از آنها میتواند مقدار پیشفرض را تنظیم کند و آخرین گزینه برنده است:parser.add_option("--advanced", action="store_const", dest="mode", const="advanced", default="novice") # overridden below parser.add_option("--novice", action="store_const", dest="mode", const="novice", default="advanced") # overrides above setting
برای اجتناب از این سردرگمی، از
set_defaults()استفاده کنید:parser.set_defaults(mode="advanced") parser.add_option("--advanced", action="store_const", dest="mode", const="advanced") parser.add_option("--novice", action="store_const", dest="mode", const="novice")
کالبکهای گزینه¶
هنگامی که کنشها و انواع توکار optparse برای نیازهای شما کاملاً کافی نیستند، دو انتخاب دارید: گسترش optparse یا تعریف یک گزینهی کالبک. گسترش optparse عمومیتر است، اما برای بسیاری از موارد ساده زیادهروی است. اغلب یک کالبک ساده تمام چیزی است که نیاز دارید.
تعریف یک گزینهی کالبک دو مرحله دارد:
خود گزینه را با استفاده از کنش
"callback"تعریف کنیدکالبک را بنویسید؛ این یک تابع (یا متد) است که حداقل ۴ آرگومان دریافت میکند، همانطور که در زیر توضیح داده شده است
تعریف یک گزینهی کالبک¶
مانند همیشه، سادهترین راه برای تعریف یک گزینهی کالبک، استفاده از متد OptionParser.add_option() است. به جز action، تنها ویژگی گزینهای که باید مشخص کنید callback است، یعنی تابعی که باید فراخوانی شود:
parser.add_option("-c", action="callback", callback=my_callback)
callback یک تابع (یا شیء فراخوانیپذیر دیگر) است، بنابراین هنگام ایجاد این گزینهی کالبک، باید از قبل my_callback() را تعریف کرده باشید. در این حالت ساده، optparse حتی نمیداند که -c آرگومانی میگیرد یا خیر، که معمولاً به این معناست که این گزینه آرگومانی ندارد—صرف وجود -c در خط فرمان تنها چیزی است که باید بداند. هرچند در برخی شرایط، ممکن است بخواهید کالبک شما تعداد دلخواهی از آرگومانهای خط فرمان را مصرف کند. اینجاست که نوشتن کالبکها دشوار میشود؛ این موضوع بعداً در همین بخش پوشش داده میشود.
optparse همیشه چهار آرگومان مشخص را به کالبک شما ارسال میکند، و تنها در صورتی آرگومانهای اضافی را ارسال میکند که آنها را از طریق callback_args و callback_kwargs مشخص کرده باشید. بنابراین، حداقل امضای تابع کالبک به این صورت است:
def my_callback(option, opt, value, parser):
چهار آرگومان یک کالبک در زیر توضیح داده شدهاند.
چند ویژگی دیگر برای گزینه وجود دارد که میتوانید هنگام تعریف یک گزینه کالبک آنها را ارائه کنید:
typeمعنای معمول خود را دارد: مانند کنشهای
"store"یا"append"، بهoptparseدستور میدهد یک آرگومان را مصرف کند و آن را بهtypeتبدیل کند. البته بهجای ذخیره کردن مقدار(های) تبدیلشده در جایی،optparseآن را به تابع کالبک شما ارسال میکند.nargsهمچنین معنای معمول خود را دارد: اگر ارائه شود و بزرگتر از ۱ باشد،
optparsenargsآرگومان را مصرف میکند، که هر یک باید بتواند بهtypeتبدیل شود. سپس یک تاپل از مقادیر تبدیلشده را به کالبک شما میدهد.callback_argsیک تاپل از آرگومانهای جایگاهی اضافی برای ارسال به کالبک
callback_kwargsیک دیکشنری از آرگومانهای کلیدواژهای اضافی برای فرستادن به کالبک
نحوه فراخوانی کالبکها¶
تمام کالبکها بهصورت زیر فراخوانی میشوند:
func(option, opt_str, value, parser, *args, **kwargs)
که در آن
optionنمونهی Option است که کالبک را فراخوانی میکند
opt_strرشتهی گزینهی مشاهدهشده در خط فرمان است که باعث فراخوانی کالبک میشود. (اگر از یک گزینهی بلند مخففشده استفاده شده باشد،
opt_strرشتهی گزینهی کامل و کانونیکال خواهد بود---مثلاً اگر کاربر--fooرا بهعنوان مخفف--foobarدر خط فرمان وارد کند، آنگاهopt_strبرابر"--foobar"خواهد بود.)valueآرگومان این گزینه است که در خط فرمان دیده میشود.
optparseتنها در صورتی منتظر آرگومان است کهtypeتنظیم شده باشد؛ نوعvalueهمان نوعی خواهد بود که از نوع گزینه برداشت میشود. اگرtypeبرای این گزینهNoneباشد (آرگومانی انتظار نمیرود)، آنگاهvalueبرابرNoneخواهد بود. اگرnargs> 1 باشد،valueتاپلی از مقادیر با نوع مناسب خواهد بود.parserنمونهی OptionParser است که کل فرآیند را هدایت میکند و عمدتاً مفید است، زیرا میتوانید از طریق ویژگیهای نمونهی آن به برخی دادههای جالب دیگر دسترسی داشته باشید:
parser.largsفهرست کنونی آرگومانهای باقیمانده، یعنی آرگومانهایی که مصرف شدهاند اما نه گزینهها و نه آرگومانهای گزینه هستند. میتوانید
parser.largsرا تغییر دهید، برای مثال با افزودن آرگومانهای بیشتر به آن. (این فهرست بهargsتبدیل خواهد شد، دومین مقدار بازگشتیparse_args().)parser.rargsفهرست جاری آرگومانهای باقیمانده، یعنی فهرستی که
opt_strوvalue(در صورت اقتضا) از آن حذف شدهاند و تنها آرگومانهای پس از آنها هنوز موجودند. میتوانیدparser.rargsرا تغییر دهید، برای مثال با مصرف آرگومانهای بیشتر.parser.valuesشیءای که مقادیر گزینهها بهطور پیشفرض در آن ذخیره میشوند (نمونهای از optparse.OptionValues). این به کالبکها اجازه میدهد که برای ذخیرهی مقادیر گزینهها از همان مکانیزم بقیهی
optparseاستفاده کنند؛ شما نیازی نیست با متغیرهای سراسری (globals) یا بستهها (closures) سروکار داشته باشید. همچنین میتوانید به مقدار(های) هر یک از گزینههایی که پیشتر در خط فرمان با آنها مواجه شدهاید، دسترسی پیدا کنید یا آنها را تغییر دهید.
argsیک تاپل از آرگومانهای جایگاهی دلخواه است که از طریق ویژگی گزینهی
callback_argsتأمین میشود.kwargsدیکشنریای از آرگومانهای کلیدواژهای دلخواه است که از طریق
callback_kwargsارائه شده است.
پرتاب خطاها در کالبک¶
تابع کالبک باید در صورت وجود هرگونه مشکل در گزینه یا آرگومانهای آن، OptionValueError را پرتاب کند. optparse آن را میگیرد و برنامه را خاتمه میدهد و پیام خطایی را که شما ارائه میکنید در stderr چاپ میکند. پیام شما باید روشن، مختصر و دقیق باشد و گزینهی دارای خطا را ذکر کند. در غیر این صورت، کاربر برای فهمیدن اینکه چه اشتباهی کرده است دچار مشکل خواهد شد.
مثال کالبک ۱: کالبک ساده¶
در اینجا مثالی از یک گزینهی کالبک آمده است که هیچ آرگومانی نمیگیرد و بهسادگی دیدهشدن گزینه را ثبت میکند:
def record_foo_seen(option, opt_str, value, parser):
parser.values.saw_foo = True
parser.add_option("--foo", action="callback", callback=record_foo_seen)
البته، میتوانید این کار را با کنش "store_true" انجام دهید.
مثال کالبک ۲: بررسی ترتیب گزینهها¶
در اینجا مثالی کمی جالبتر آمده است: این واقعیت را ثبت میکند که -a دیده شده است، اما اگر در خط فرمان بعد از -b بیاید، با خطا مواجه میشود.
def check_order(option, opt_str, value, parser):
if parser.values.b:
raise OptionValueError("can't use -a after -b")
parser.values.a = 1
...
parser.add_option("-a", action="callback", callback=check_order)
parser.add_option("-b", action="store_true", dest="b")
مثال کالبک ۳: بررسی ترتیب گزینهها (تعمیمیافته)¶
اگر میخواهید از این کالبک برای چند گزینه مشابه مجدداً استفاده کنید (پرچمی را تنظیم کند، اما اگر -b قبلاً دیده شده باشد با خطا مواجه شود)، به کمی کار نیاز دارد: پیام خطا و پرچمی که تنظیم میکند باید تعمیم داده شوند.
def check_order(option, opt_str, value, parser):
if parser.values.b:
raise OptionValueError("can't use %s after -b" % opt_str)
setattr(parser.values, option.dest, 1)
...
parser.add_option("-a", action="callback", callback=check_order, dest='a')
parser.add_option("-b", action="store_true", dest="b")
parser.add_option("-c", action="callback", callback=check_order, dest='c')
مثال کالبک ۴: بررسی شرط دلخواه¶
البته، میتوانید هر شرطی را در آن قرار دهید—شما به بررسی مقادیر گزینههای از پیش تعریفشده محدود نیستید. برای مثال، اگر گزینههایی دارید که نباید هنگامی که ماه کامل است فراخوانی شوند، تنها کاری که باید انجام دهید این است:
def check_moon(option, opt_str, value, parser):
if is_moon_full():
raise OptionValueError("%s option invalid when moon is full"
% opt_str)
setattr(parser.values, option.dest, 1)
...
parser.add_option("--foo",
action="callback", callback=check_moon, dest="foo")
(تعریف is_moon_full() بهعنوان تمرینی برای خواننده باقی مانده است.)
مثال ۵ کالبک: آرگومانهای ثابت¶
هنگامی که گزینههای کالبکی تعریف میکنید که تعداد ثابتی آرگومان میگیرند، همهچیز کمی جالبتر میشود. مشخص کردن اینکه یک گزینه کالبکی آرگومان میگیرد، مشابه تعریف یک گزینه "store" یا "append" است: اگر type را تعریف کنید، گزینه یک آرگومان میگیرد که باید بتواند به آن نوع تبدیل شود؛ اگر nargs را نیز تعریف کنید، گزینه nargs آرگومان میگیرد.
در اینجا مثالی آمده است که فقط کنش استاندارد "store" را شبیهسازی میکند:
def store_value(option, opt_str, value, parser):
setattr(parser.values, option.dest, value)
...
parser.add_option("--foo",
action="callback", callback=store_value,
type="int", nargs=3, dest="foo")
توجه داشته باشید که optparse مصرف ۳ آرگومان و تبدیل آنها به اعداد صحیح را برای شما بر عهده میگیرد؛ تنها کاری که باید انجام دهید، ذخیره کردن آنها است. (یا هر چیز دیگر؛ بدیهی است که برای این مثال به کالبک نیازی ندارید.)
مثال کالبک ۶: آرگومانهای متغیر¶
هنگامی که بخواهید یک گزینه تعداد متغیری آرگومان بپذیرد، کار پیچیده میشود. در این حالت، باید یک کالبک بنویسید، زیرا optparse هیچ قابلیت توکاری برای آن فراهم نمیکند. و باید با برخی پیچیدگیهای تجزیهی مرسوم خط فرمان در یونیکس سروکار داشته باشید که optparse معمولاً آنها را برای شما مدیریت میکند. بهطور خاص، کالبکها باید قواعد مرسوم برای آرگومانهای خالی -- و - را پیادهسازی کنند:
هر یک از
--یا-میتوانند آرگومانهای گزینه باشند--بهتنهایی (اگر آرگومان یک گزینه نباشد): پردازش خط فرمان را متوقف میکند و--را نادیده میگیرد-خالی (اگر آرگومان یک گزینه نباشد): پردازش خط فرمان را متوقف میکند، اما-را نگه میدارد (آن را بهparser.largsاضافه میکند)
اگر گزینهای میخواهید که تعداد متغیری از آرگومانها را میپذیرد، چند مسئله ظریف و دشوار وجود دارد که باید به آنها توجه کنید. پیادهسازی دقیقی که انتخاب میکنید بر اساس مصالحههایی خواهد بود که حاضرید برای برنامه خود بپذیرید (به همین دلیل optparse بهطور مستقیم از این نوع موارد پشتیبانی نمیکند).
با این حال، در اینجا تلاشی برای پیادهسازی یک کالبک برای گزینهای با آرگومانهای متغیر ارائه شده است:
def vararg_callback(option, opt_str, value, parser):
assert value is None
value = []
def floatable(str):
try:
float(str)
return True
except ValueError:
return False
for arg in parser.rargs:
# stop on --foo like options
if arg[:2] == "--" and len(arg) > 2:
break
# stop on -a, but not on -3 or -3.0
if arg[:1] == "-" and len(arg) > 1 and not floatable(arg):
break
value.append(arg)
del parser.rargs[:len(value)]
setattr(parser.values, option.dest, value)
...
parser.add_option("-c", "--callback", dest="vararg_attr",
action="callback", callback=vararg_callback)
گسترش optparse¶
از آنجا که دو عامل اصلی کنترلکننده چگونگی تفسیر گزینههای خط فرمان توسط optparse، اکشن و نوع هر گزینه هستند، محتملترین مسیر توسعه، افزودن کنشهای جدید و انواع جدید است.
افزودن نوعهای جدید¶
برای افزودن نوعهای جدید، باید زیرکلاس خودتان از کلاس Option در optparse را تعریف کنید. این کلاس دارای چند ویژگی است که نوعهای optparse را تعریف میکنند: TYPES و TYPE_CHECKER.
- Option.TYPES¶
یک تاپلاز نامهای نوع؛ در زیرکلاس خود، بهسادگی یک تاپل جدید به نام
TYPESتعریف کنید که بر پایهی تاپل استاندارد ساخته میشود.
- Option.TYPE_CHECKER¶
یک دیکشنری که نام انواع را به توابع بررسی نوع نگاشت میکند. یک تابع بررسی نوع دارای امضای زیر است:
def check_mytype(option, opt, value)
که در آن
optionیک نمونه ازOption،optیک رشتهی گزینه (برای مثال-f) وvalueرشتهای از خط فرمان است که باید بررسی و به نوع دلخواه شما تبدیل شود.check_mytype()باید شیءای از نوع فرضیmytypeرا برگرداند. مقداری که یک تابع بررسی نوع بازمیگرداند، در نهایت در نمونهی OptionValues بازگشتی ازOptionParser.parse_args()قرار خواهد گرفت، یا بهعنوان پارامترvalueبه یک کالبک ارسال میشود.تابع بررسی نوع شما باید در صورت مواجهه با هرگونه مشکل،
OptionValueErrorرا پرتاب کند.OptionValueErrorتنها یک آرگومان رشتهای دریافت میکند که بههمانصورت به متدerror()ازOptionParserمنتقل میشود؛ این متد بهنوبه خود نام برنامه و رشته"error:"را به ابتدای آن اضافه میکند و همهچیز را پیش از خاتمه فرایند در stderr چاپ میکند.
در اینجا مثالی پیشپاافتاده آورده شده است که اضافه کردن نوع گزینهی "complex" برای تجزیهی اعداد مختلط بهسبک پایتون در خط فرمان را نشان میدهد. (این مثال حتی از قبل پیشپاافتادهتر است، زیرا optparse 1.3 پشتیبانی توکار از اعداد مختلط را اضافه کرده است، اما مهم نیست.)
ابتدا، ایمپورتهای لازم:
from copy import copy
from optparse import Option, OptionValueError
شما باید ابتدا بررسیکننده نوع خود را تعریف کنید، زیرا بعداً به آن ارجاع داده میشود (در ویژگی کلاس TYPE_CHECKER از زیرکلاس Option شما):
def check_complex(option, opt, value):
try:
return complex(value)
except ValueError:
raise OptionValueError(
"option %s: invalid complex value: %r" % (opt, value))
در نهایت، زیرکلاس Option:
class MyOption (Option):
TYPES = Option.TYPES + ("complex",)
TYPE_CHECKER = copy(Option.TYPE_CHECKER)
TYPE_CHECKER["complex"] = check_complex
(اگر یک copy() از Option.TYPE_CHECKER نمیساختیم، در نهایت ویژگی TYPE_CHECKER کلاس Optionِ optparse را تغییر میدادیم. از آنجا که اینجا پایتون است، هیچ چیز جز ادب و عقل سلیم شما را از انجام این کار باز نمیدارد.)
همین است! اکنون میتوانید اسکریپتی بنویسید که از نوع جدید گزینه درست مانند هر اسکریپت دیگری مبتنی بر optparse استفاده میکند، با این تفاوت که باید به OptionParser خود دستور دهید به جای Option از MyOption استفاده کند:
parser = OptionParser(option_class=MyOption)
parser.add_option("-c", type="complex")
بهعنوان جایگزین، میتوانید فهرست گزینههای خودتان را بسازید و آن را به OptionParser بدهید؛ اگر از add_option() به روش بالا استفاده نکنید، نیازی نیست به OptionParser بگویید از کدام کلاس گزینه استفاده کند:
option_list = [MyOption("-c", action="store", type="complex", dest="c")]
parser = OptionParser(option_list=option_list)
افزودن کنشهای جدید¶
افزودن کنشهای جدید کمی پیچیدهتر است، زیرا باید بدانید که optparse چند دستهبندی برای کنشها دارد:
- کنشهای "store"
کنشهایی که باعث میشوند
optparseیک مقدار را در یک ویژگی از نمونهی فعلی OptionValues ذخیره کند؛ این گزینهها نیاز دارند که یک ویژگیdestبه سازندهی Option ارائه شود.- کنشهای «نوعدار»
کنشهایی که یک مقدار را از خط فرمان میگیرند و انتظار دارند آن مقدار از یک نوع مشخص باشد؛ یا دقیقتر، رشتهای که بتوان آن را به یک نوع مشخص تبدیل کرد. این گزینهها به یک ویژگی
typeبرای سازندهی Option نیاز دارند.
اینها مجموعههای همپوشان هستند: برخی از کنشهای پیشفرض «store» عبارتند از "store"، "store_const"، "append" و "count"، در حالی که کنشهای پیشفرض «typed» عبارتند از "store"، "append" و "callback".
هنگامی که یک اکشناضافه میکنید، باید آن را با فهرست کردنش در حداقل یکی از ویژگیهای کلاس Option که در زیر آمده است دستهبندی کنید (همه فهرستهایی از رشتهها هستند):
- Option.ACTIONS¶
تمام اکشنها باید در ACTIONS فهرست شوند.
- Option.STORE_ACTIONS¶
کنشهای "store" همچنین در اینجا فهرست شدهاند.
- Option.TYPED_ACTIONS¶
کنشهای "typed" علاوه بر این، در اینجا نیز فهرستشدهاند.
- Option.ALWAYS_TYPED_ACTIONS¶
اکشنی که همیشه یک نوع میپذیرند (یعنی گزینههای آنها همیشه یک مقدار میپذیرند) علاوه بر این در اینجا فهرست شدهاند. تنها اثر این امر این است که
optparseنوع پیشفرض،"string"، را به گزینههای بدون نوع صریحی که اکشن آنها درALWAYS_TYPED_ACTIONSفهرست شده است، اختصاص میدهد.
برای پیادهسازی واقعی اکشن جدید خود، باید متد take_action() مربوط به Option را بازنویسی کنید و یک حالت اضافه کنید که اکشن شما را شناسایی کند.
برای مثال، بیایید یک اکشن "extend" اضافه کنیم. این شبیه اکشن استاندارد "append" است، اما به جای دریافت یک مقدار از خط فرمان و افزودن آن به یک فهرست موجود، "extend" چندین مقدار را در یک رشتهی جداشده با ویرگول دریافت میکند و یک فهرست موجود را با آنها گسترش میدهد. یعنی، اگر --names یک گزینهی "extend" از نوع "string" باشد، خط فرمان
--names=foo,bar --names blah --names ding,dong
منجر به یک فهرست میشود
["foo", "bar", "blah", "ding", "dong"]
باز هم یک زیرکلاس از Option تعریف میکنیم:
class MyOption(Option):
ACTIONS = Option.ACTIONS + ("extend",)
STORE_ACTIONS = Option.STORE_ACTIONS + ("extend",)
TYPED_ACTIONS = Option.TYPED_ACTIONS + ("extend",)
ALWAYS_TYPED_ACTIONS = Option.ALWAYS_TYPED_ACTIONS + ("extend",)
def take_action(self, action, dest, opt, value, values, parser):
if action == "extend":
lvalue = value.split(",")
values.ensure_value(dest, []).extend(lvalue)
else:
Option.take_action(
self, action, dest, opt, value, values, parser)
قابلیتهای قابلتوجه:
"extend"هم یک مقدار را در خط فرمان انتظار دارد و هم آن مقدار را جایی ذخیره میکند، بنابراین در هر دوSTORE_ACTIONSوTYPED_ACTIONSقرار میگیرد.برای اطمینان از اینکه
optparseنوع پیشفرض"string"را به کنشهای"extend"اختصاص میدهد، اکشن"extend"را نیز درALWAYS_TYPED_ACTIONSقرار دادیم.MyOption.take_action()فقط همین یک کنش جدید را پیادهسازی میکند و کنترل را برای کنشهای استانداردoptparseبهOption.take_action()بازمیگرداند.valuesنمونهای از کلاس optparse_parser.Values است که متد بسیار مفیدensure_value()را فراهم میکند.ensure_value()در اصل همانgetattr()با یک سوپاپ اطمینان است؛ این متد به این صورت فراخوانی میشودvalues.ensure_value(attr, value)
اگر ویژگی
attrدرvaluesوجود نداشته باشد یاNoneباشد، ensure_value() ابتدا آن را رویvalueتنظیم میکند و سپسvalueرا برمیگرداند. این برای کنشهایی مانند"extend"،"append"و"count"بسیار کاربردی است؛ همهی اینها داده را در یک متغیر انباشته میکنند و انتظار دارند آن متغیر از نوع خاصی باشد (برای دو مورد اول یک فهرست، برای مورد آخر یک عدد صحیح). استفاده ازensure_value()به این معناست که اسکریپتهایی که از کنش شما استفاده میکنند، نیازی به نگرانی دربارهی تنظیم مقدار پیشفرض برای مقصدهای گزینههای مورد بحث ندارند؛ آنها میتوانند فقط مقدار پیشفرض راNoneباقی بگذارند وensure_value()هنگام نیاز، آن را بهدرستی تنظیم میکند.
استثناها¶
- exception optparse.OptionError¶
اگر یک نمونه
Optionبا آرگومانهای نامعتبر یا ناسازگار ایجاد شود، پرتاب میشود.
- exception optparse.OptionConflictError¶
در صورتی که گزینههای متعارض به یک
OptionParserاضافه شوند، پرتاب میشود.
- exception optparse.OptionValueError¶
در صورت مواجهه با مقدار نامعتبر برای یک گزینه در خط فرمان، پرتاب میشود.
- exception optparse.BadOptionError¶
در صورتی که گزینهای نامعتبر در خط فرمان ارسال شود، پرتاب میشود.
- exception optparse.AmbiguousOptionError¶
در صورتی که یک گزینه مبهم در خط فرمان ارسال شود، پرتاب میشود.