סקירה כללית
מכיוון ש-Python היא שפת תכנות פופולרית מאוד, כמו גם בעלת תמיכה ברוב מערכות ההפעלה וספריות רבות המקלות על עיבוד טיעונים בשורת הפקודה - היא הפכה בשימוש נרחב ליצירת כלי שורת פקודה למטרות רבות. כלים אלה יכולים לנוע בין אפליקציות CLI פשוטות לאלו מורכבות יותר, כמו AWS' awscli כלי.
כלים מורכבים כמו זה נשלטים בדרך כלל על ידי המשתמש באמצעות טיעוני שורת פקודה, המאפשר למשתמש להשתמש בפקודות ספציפיות, להגדיר אפשרויות ועוד. לדוגמה, אפשרויות אלה יכולות לומר לכלי להוציא מידע נוסף, לקרוא נתונים ממקור מסוים או לשלוח פלט למיקום מסוים.
באופן כללי, ארגומנטים מועברים לכלי CLI בצורה שונה, בהתאם למערכת ההפעלה שלך:
- דמוי יוניקס:
-
ואחריו מכתב, כמו-h
, או--
ואחריו מילה, כמו--help
- Windows:
/
ואחריו אות או מילה כמו/help
גישות שונות אלו קיימות מסיבות היסטוריות. תוכניות רבות במערכות דמויות Unix תומכות הן בסימון המקף היחיד והן כפול. סימון המקף הבודד משמש בעיקר עם אפשרויות של אותיות בודדות, בעוד שמקפים כפולים מציגים רשימת אפשרויות קריאה יותר, וזה שימושי במיוחד עבור אפשרויות מורכבות שצריכות להיות מפורשות יותר.
הערות: במאמר זה נתמקד אך ורק בפורמט דמוי יוניקס של -
ו --
.
זכור שגם השם וגם המשמעות של טיעון הם ספציפיים לתוכנית - אין הגדרה כללית, מלבד כמה מוסכמות נפוצות כמו --help
למידע נוסף על השימוש בכלי. כמפתחים של סקריפט Python, תחליט אילו ארגומנטים לספק למתקשר ומה הם עושים. זה דורש הערכה נכונה.
ככל שרשימת הארגומנטים הזמינים שלך תגדל, הקוד שלך יהפוך מורכב יותר בניסיון לנתח אותם במדויק. למרבה המזל, ב-Python יש מספר ספריות זמינות שיעזרו לך בכך. נסקור כמה מהפתרונות הנפוצים ביותר, שנעים בין "עשה זאת בעצמך" עם sys.argv
, לגישת "עשה בשבילך" עם argparse
.
טיפול בטיעונים של שורת הפקודה עם Python
Python 3+ והמערכת האקולוגית מסביב תומכים במספר דרכים שונות לטיפול בארגומנטים של שורת הפקודה. יש רב ספריות המאפשרות ניתוח של ארגומנטים בשורת הפקודה.
הדרך המובנית היא להשתמש ב- sys
מודול. מבחינת שמות, והשימוש בו, הוא מתייחס ישירות לספריית C (libc
).
הדרך השנייה היא ה getopt
מודול, המטפל באפשרויות קצרות וארוכות כאחד, כולל הערכת ערכי הפרמטרים.
השמיים מודול argparse, אשר נגזר מה optparse
מודול (זמין עד Python 2.7).
השמיים docopt
מודול, כלומר זמין ב- GitHub, מאפשר גם את אותה פונקציונליות.
לאחרונה, absl
הספרייה גם צוברת קיטור, כאמצעי להחליף optparse
ו getopt()
.
לכל אחת מהדרכים הללו יש את היתרונות והחסרונות שלה, אז כדאי להעריך כל אחת מהן כדי לראות מה הכי מתאים לצרכים שלך.
מודול ה-sys
זהו מודול בסיסי שנשלח עם Python מהימים הראשונים. זה לוקח גישה דומה מאוד לספריית C באמצעות argc
/argv
כדי לגשת לטיעונים. ה מודול sys מיישם את הארגומנטים של שורת הפקודה במבנה רשימה פשוט בשם sys.argv
.
כל רכיב רשימה מייצג ארגומנט בודד. הפריט הראשון ברשימה,
sys.argv[0]
, הוא שמו של הסקריפט של Python. שאר מרכיבי הרשימה,sys.argv[1]
לsys.argv[n]
, הם ארגומנטים של שורת הפקודה 2 עד n.
כמפריד בין הטיעונים, נעשה שימוש ברווח. ערכי ארגומנט המכילים רווח בו חייבים להיות מוקפים במירכאות כדי לנתח כראוי על ידי sys
.
המקבילה ל- argc
הוא רק מספר האלמנטים ברשימה. כדי לקבל ערך זה, השתמש ב- Python len()
מַפעִיל. נציג זאת בדוגמה של קוד בהמשך.
הדפסת טיעון ה-CLI הראשון
בדוגמה הראשונה הזו, הסקריפט שלנו יקבע את הדרך שבה הוא נקרא. מידע זה נשמר בארגומנט שורת הפקודה הראשון, באינדקס עם 0. הקוד שלהלן מראה כיצד אתה משיג את השם של סקריפט Python שלך:
import sys
print("The script has the name %s" % (sys.argv[0])
שמור את הקוד הזה בקובץ בשם arguments-program-name.py
, ולאחר מכן קרא לזה כפי שמוצג להלן. הפלט הוא כדלקמן ומכיל את שם הקובץ, כולל הנתיב המלא שלו:
$ python arguments-program-name.py
The script has the name arguments-program-name.py
$ python /home/user/arguments-program-name.py
The script has the name /home/user/arguments-program-name.py
כפי שניתן לראות מהקריאה השנייה למעלה, אנו מקבלים לא רק את השם של קובץ Python, אלא גם את הנתיב המלא המשמש לקריאה שלו.
ספירת מספר הטיעונים
בדוגמה השנייה הזו אנו פשוט סופרים את מספר הארגומנטים של שורת הפקודה באמצעות המובנה len()
שִׁיטָה. sys.argv
היא הרשימה שעלינו לבחון. בקוד שלהלן, אנו מקבלים את מספר הארגומנטים ולאחר מכן מפחיתים את 1 מכיוון שאחד מהארגומנטים האלה (כלומר הראשון) מוגדר תמיד כשם הקובץ, מה שלא תמיד שימושי לנו. לפיכך, המספר האמיתי של הארגומנטים שעבר המשתמש הוא len(sys.argv) - 1
:
import sys
arguments = len(sys.argv) - 1
print ("The script is called with %i arguments" % (arguments))
שמור ותן שם לקובץ הזה arguments-count.py. כמה דוגמאות לקריאה לסקריפט זה מוצגות להלן. זה כולל שלושה תרחישים שונים:
- קריאה ללא ארגומנטים נוספים של שורת הפקודה
- שיחה עם שני טיעונים
- קריאה עם שני ארגומנטים, כאשר השני הוא מחרוזת במירכאות המכילה רווח
$ python arguments-count.py
The script is called with 0 arguments
$ python arguments-count.py --help me
The script is called with 2 arguments
$ python arguments-count.py --option "long string"
The script is called with 2 arguments
איטרציה באמצעות טיעונים
הדוגמה השלישית שלנו מפלטת כל ארגומנט בודד שנשלח לסקריפט של Python, מלבד שם התוכנית עצמה. לכן, אנו עוברים בלולאה דרך הארגומנטים של שורת הפקודה המתחילים ב- שני רכיב רשימה. זכור שזה אינדקס 1 מכיוון שרשימות מבוססות 0 ב-Python:
import sys
arguments = len(sys.argv) - 1
position = 1
while (arguments >= position):
print ("Parameter %i: %s" % (position, sys.argv[position]))
position = position + 1
להלן אנו קוראים לקוד שלנו, שנשמר בקובץ arguments-output.py. כפי שנעשה בדוגמה הקודמת שלנו, הפלט ממחיש שלוש קריאות שונות:
- שיחה ללא כל ויכוחים
- שיחה עם שני טיעונים
- קריאה עם שני ארגומנטים, כאשר הארגומנט השני הוא מחרוזת במירכאות המכילה רווח
$ python arguments-output.py
$ python arguments-output.py --help me
Parameter 1: --help
Parameter 2: me
$ python arguments-output.py --option "long string"
Parameter 1: --option
Parameter 2: long string
זכור, הטעם בהצגת דוגמה למחרוזת המצוטטת היא שהפרמטרים בדרך כלל מופרדים על ידי רווח, אלא אם כן הם מוקפים במרכאות.
דגלי סנפלינג (absl
)
ספריית הדגלים של Abseil נועדה להביא ארגומנטים של שורת פקודה לייצור, עם ארגומנטים של שורת פקודה מבוזרת. כאשר מודול משתמש בדגלי שורת פקודה, ומיובא למודול אחר - המודול השני מייבאת גם את הדגלים, ויכול לעבד אותם על ידי העברתם למודול המיובא.
זה הופך ארגומנטים מורכבים של שורת פקודה המשותפים בין מודולים לקלים יותר ופחות מילוליים.
בנוסף, הספרייה מאפשרת לך להגדיר את ערכי ברירת המחדל, התיאורים וסוג הנתונים של הארגומנטים, כך שאין צורך בבדיקות והמרות נוספות.
from absl import flags
import sys
flags.DEFINE_string('name', 'User', 'The name of the user.')
FLAGS = flags.FLAGS
FLAGS(sys.argv)
print(f"Hello {FLAGS.name}!")
סוגי הנתונים הנתמכים הם:
DEFINE_integer()
DEFINE_string()
DEFINE_bool()
DEFINE_enum()
DEFINE_list()
DEFINE_float()
בנוסף ל DEFINE_multi_integer()
, DEFINE_multi_string()
ו DEFINE_multi_enum()
עבור קלט רב-טיעונים. בנוסף, ריצה --help
, --helpfull
וכו' מדפיסים את הדגלים הקיימים ותיאוריהם, בפורמטים שונים.
עיין במדריך המעשי והמעשי שלנו ללימוד Git, עם שיטות עבודה מומלצות, סטנדרטים מקובלים בתעשייה ודף רמאות כלול. תפסיק לגוגל פקודות Git ולמעשה ללמוד זה!
הספרייה גם מאפשרת לך להגדיר אימותים - הן במונחים של טווח, כגון ערכים מבוססי מספרים שלמים בעלי upper_bound
or lower_bound
זה מקובל, והפעלת שיטות שרירותיות לבדיקת ערכים:
def validate_name(value):
return len(value) > 15
flags.register_validator('name',
validate_name,
message='Name is over 15 characters long.',
flag_values=FLAGS)
איסוף אלה לדוגמא קונקרטית:
from absl import flags
import sys
flags.DEFINE_string('name', 'User', 'The name of the user.')
flags.DEFINE_integer('tasks', 0, 'The number of tasks a user has.', lower_bound=0)
FLAGS = flags.FLAGS
FLAGS(sys.argv)
print(f"{FLAGS.name} has {FLAGS.tasks} tasks to work on.")
$ python flags.py --name=John --tasks=5
John has 5 tasks to work on.
$ python flags.py --name=John --tasks=-1
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/absl/flags/_flag.py", line 180, in _parse
return self.parser.parse(argument)
File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/absl/flags/_argument_parser.py", line 168, in parse
raise ValueError('%s is not %s' % (val, self.syntactic_help))
ValueError: -1 is not a non-negative integer
...
מודול argparse
השמיים מודול argparse זמין מאז Python 3.2, ושיפור של optparse
מודול שקיים עד Python 2.7. התיעוד של Python מכיל תיאור API ומדריך המכסה את כל השיטות בפירוט.
המודול מציע ממשק שורת פקודה עם פלט סטנדרטי, בעוד ששני הפתרונות הראשונים משאירים הרבה מהעבודה בידיים שלך. argparse
מאפשר אימות של ארגומנטים קבועים ואופציונליים, עם בדיקת שמות כסגנון קצר או ארוך. כארגומנט אופציונלי ברירת מחדל, הוא כולל -h
, יחד עם הגרסה הארוכה שלו --help
. טיעון זה מלווה בהודעת עזרה ברירת מחדל המתארת את הטיעונים המקובלים.
הקוד שלהלן מציג את האתחול מנתח, ואת הפלט למטה שמציג את הקריאה הבסיסית, ואחריו הודעת העזרה. בניגוד לקריאות Python שבהן השתמשנו בדוגמאות הקודמות, זכור להשתמש ב- Python 3 עם הדוגמאות הבאות:
import argparse
parser = argparse.ArgumentParser()
parser.parse_args()
$ python3 arguments-argparse-basic.py
$ python3 arguments-argparse-basic.py -h
usage: arguments-argparse-basic.py [-h]
optional arguments:
-h, --help show this help message and exit
$ python3 arguments-argparse-basic.py --verbose
usage: arguments-argparse-basic.py [-h]
arguments-argparse-basic.py: error: unrecognized arguments: --verbose
בשלב הבא, נוסיף תיאור מותאם אישית להודעת העזרה עבור המשתמשים שלנו. אתחול המנתח בצורה זו מאפשר טקסט נוסף. הקוד שלהלן מאחסן את התיאור ב- text
משתנה, שניתן במפורש ל- argparse
מחלקה כמו description
פָּרָמֶטֶר. קורא לקוד זה למטה, אתה יכול לראות איך נראה הפלט:
import argparse
text = 'This is a test program. It demonstrates how to use the argparse module with a program description.'
parser = argparse.ArgumentParser(description=text)
parser.parse_args()
$ python3 arguments-argparse-description.py --help
usage: arguments-argparse-description.py [-h]
This is a test program. It demonstrates how to use the argparse module with a
program description.
optional arguments:
-h, --help show this help message and exit
כשלב הסופי נוסיף ארגומנט אופציונלי בשם -V
, שיש לו ארגומנט סגנון ארוך תואם בשם --version
. לשם כך אנו משתמשים בשיטה add_argument()
שאנו קוראים עם שלושה פרמטרים (מוצג עבור --version
, רק):
- שם הפרמטר:
--version
- טקסט העזרה של הפרמטר:
help="show program version"
- פעולה (ללא ערך נוסף):
action="store_true"
קוד המקור לכך מוצג למטה. קריאת הארגומנטים לתוך המשתנה שנקרא args
נעשה באמצעות ה parse_args()
שיטה מתוך parser
לְהִתְנַגֵד. שימו לב שאתם שולחים גם את הגרסה הקצרה וגם את הגרסה הארוכה בשיחה אחת. לבסוף, אתה בודק אם התכונות args.V
or args.version
מוגדרים ומוציאים את הודעת הגרסה:
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("-V", "--version", help="show program version", action="store_true")
args = parser.parse_args()
if args.version:
print("This is myprogram version 0.1")
$ python3 arguments-argparse-optional.py -V
This is myprogram version 0.1
$ python3 arguments-argparse-optional.py --version
This is myprogram version 0.1
השמיים --version
הארגומנט אינו מחייב לתת ערך בשורת הפקודה. לכן הגדרנו את טיעון הפעולה ל "store_true"
. במקרים אחרים ייתכן שתזדקק לערך מוקצה נוסף, למשל אם תציין נפח, גובה או רוחב מסוימים. זה מוצג בדוגמה הבאה. כמקרה ברירת מחדל, שים לב שכל הטיעונים מתפרשים כמחרוזות:
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("--width", "-w", help="set output width")
args = parser.parse_args()
if args.width:
print("Set output width to %s" % args.width)
כאן אנו מראים מה קורה בעת הגשת ערכי ארגומנט שונים. זה כולל גם את הגרסה הקצרה וגם את הגרסה הארוכה, כמו גם את הודעת העזרה:
$ python3 arguments-argparse-optional2.py -w 10
Set output width to 10
$ python3 arguments-argparse-optional2.py --width 10
Set output width to 10
$ python3 arguments-argparse-optional2.py -h
usage: arguments-argparse-optional2.py [-h] [--width WIDTH]
optional arguments:
-h, --help show this help message and exit
--width WIDTH, -w WIDTH
set output width
מודול getopt
כפי שאולי שמתם לב בעבר, ה sys
מודול מפצל את מחרוזת שורת הפקודה להיבטים בודדים בלבד. הפייתון מודול getopt הולך קצת יותר רחוק ומרחיב את ההפרדה של מחרוזת הקלט על ידי אימות פרמטר. מבוסס על ה getopt
פונקציית C, היא מאפשרת אפשרויות קצרות וארוכות, כולל הקצאת ערך.
בפועל, זה דורש את sys
מודול לעיבוד נתוני קלט כראוי. כדי לעשות זאת, הן ה sys
מודול ו getopt
יש לטעון את המודול מראש. לאחר מכן, מרשימת פרמטרי הקלט אנו מסירים את רכיב הרשימה הראשון (ראה את הקוד למטה), ומאחסנים את הרשימה הנותרת של ארגומנטים של שורת הפקודה במשתנה שנקרא argument_list
:
import getopt, sys
full_cmd_arguments = sys.argv
argument_list = full_cmd_arguments[1:]
print argument_list
הטיעונים ב argument_list
כעת ניתן לנתח באמצעות ה getopts()
שיטה. אבל לפני שנעשה את זה, אנחנו צריכים לספר getopts()
לגבי אילו פרמטרים תקפים. הם מוגדרים כך:
short_options = "ho:v"
long_options = ["help", "output=", "verbose"]
משמעות הדבר היא שהטיעונים הללו הם אלה שאנו רואים כתקינים, יחד עם מידע נוסף:
------------------------------------------
long argument short argument with value
------------------------------------------
--help -h no
--output -o yes
--verbose -v no
------------------------------------------
אולי שמתם לב שה o
האופציה הקצרה בוצעה על ידי נקודתיים, :
. זה אומר getopt
שיש להקצות לאפשרות זו ערך.
זה מאפשר לנו כעת לעבד רשימה של טיעונים. ה getopt()
השיטה דורשת להגדיר שלושה פרמטרים - רשימת הארגומנטים בפועל מ argv
, כמו גם האפשרויות הקצרות והארוכות התקפות (הוצגו בקטע הקוד הקודם).
קריאת השיטה עצמה נשמרת בהצהרת try-catch כדי לכסות שגיאות במהלך ההערכה. מועלה חריג אם מתגלה טיעון שאינו חלק מהרשימה כפי שהוגדרה קודם לכן. הסקריפט של Python ידפיס את הודעת השגיאה למסך ויצא עם קוד שגיאה 2:
try:
arguments, values = getopt.getopt(argument_list, short_options, long_options)
except getopt.error as err:
print (str(err))
sys.exit(2)
לבסוף, הארגומנטים עם הערכים המתאימים מאוחסנים בשני המשתנים הנקובים בשם arguments
ו values
. כעת, אתה יכול בקלות להעריך את המשתנים האלה בקוד שלך. אנחנו יכולים להשתמש ב-a for
-לולאה כדי לחזור על רשימת הארגומנטים המוכרים, ערך אחד אחרי השני.
for current_argument, current_value in arguments:
if current_argument in ("-v", "--verbose"):
print ("Enabling verbose mode")
elif current_argument in ("-h", "--help"):
print ("Displaying help")
elif current_argument in ("-o", "--output"):
print (("Enabling special output mode (%s)") % (current_value))
להלן אתה יכול לראות את הפלט מביצוע קוד זה. נראה כיצד התוכנית מגיבה עם ארגומנטים חוקיים ובלתי חוקיים של תוכנית:
$ python arguments-getopt.py -h
Displaying help
$ python arguments-getopt.py --help
Displaying help
$ python arguments-getopt.py --output=green --help -v
Enabling special output mode (green)
Displaying help
Enabling verbose mode
$ python arguments-getopt.py -verbose
option -e not recognized
השיחה האחרונה לתוכנית שלנו עשויה להיראות מעט מבלבלת בהתחלה. כדי להבין את זה, אתה צריך לדעת שניתן להשתמש באפשרויות הקיצור (לעיתים נקראות גם דגלים) יחד עם מקף בודד. זה מאפשר לכלי שלך לקבל בקלות רבה יותר אפשרויות רבות. למשל, להתקשר python arguments-getopt.py -vh
זהה להתקשרות python arguments-getopt.py -v -h
. אז בשיחה האחרונה למעלה, ה getopt
המודול חשב שהמשתמש ניסה לעבור -e
כאופציה, שאינה חוקית.
סיכום
במאמר זה הראינו שיטות רבות ושונות לאחזור ארגומנטים של שורת הפקודה ב-Python, כולל שימוש sys
, getopt
, ו argparse
. מודולים אלה משתנים בפונקציונליות, חלקם מספקים הרבה יותר מאחרים. sys
גמיש לחלוטין, בעוד שניהם getopt
ו argparse
דורש מבנה כלשהו. לעומת זאת, הם מכסים את רוב העבודה המורכבת ש sys
משאיר בידיך. לאחר עיון בדוגמאות שסופקו, אתה אמור להיות מסוגל לקבוע איזה מודול מתאים ביותר לפרויקט שלך.
במאמר זה לא דיברנו על פתרונות אחרים כמו ה docopts
מודול, רק הזכרנו את זה. מודול זה נוקט בגישה שונה לחלוטין, ויוסבר בפירוט באחד מהמאמרים הבאים.