Ringkasan
Dengan Python menjadi bahasa pemrograman yang sangat populer, serta memiliki dukungan untuk sebagian besar sistem operasi dan banyak pustaka yang membuat pemrosesan argumen baris perintah menjadi mudah โ ini digunakan secara luas untuk membuat alat baris perintah untuk berbagai tujuan. Alat ini dapat berkisar dari aplikasi CLI sederhana hingga yang lebih kompleks, seperti aplikasi AWS. awscli tool.
Alat kompleks seperti ini biasanya dikendalikan oleh pengguna melalui argumen baris perintah, yang memungkinkan pengguna untuk menggunakan perintah tertentu, mengatur opsi, dan lainnya. Misalnya, opsi ini dapat memberi tahu alat untuk mengeluarkan informasi tambahan, membaca data dari sumber tertentu, atau mengirim keluaran ke lokasi tertentu.
Secara umum, argumen diteruskan ke alat CLI secara berbeda, bergantung pada sistem operasi Anda:
- Seperti Unix:
-
diikuti dengan surat, seperti-h
, atau--
diikuti dengan kata, seperti--help
- Windows:
/
diikuti oleh salah satu huruf, atau kata, seperti/help
Pendekatan yang berbeda ini ada karena alasan historis. Banyak program pada sistem mirip Unix mendukung notasi tanda hubung tunggal dan ganda. Notasi tanda hubung tunggal sebagian besar digunakan dengan opsi satu huruf, sedangkan tanda hubung ganda menyajikan daftar opsi yang lebih mudah dibaca, yang sangat berguna untuk opsi kompleks yang perlu lebih eksplisit.
Note: Pada artikel ini kita hanya akan berfokus pada format mirip Unix dari -
dan --
.
Perlu diingat bahwa nama dan arti dari sebuah argumen khusus untuk sebuah program โ tidak ada definisi umum, selain beberapa konvensi umum seperti --help
untuk informasi lebih lanjut tentang penggunaan alat ini. Sebagai pengembang skrip Python, Anda akan memutuskan argumen mana yang akan diberikan kepada pemanggil dan apa yang mereka lakukan. Ini membutuhkan evaluasi yang tepat.
Seiring bertambahnya daftar argumen yang tersedia, kode Anda akan menjadi lebih kompleks dalam mencoba menguraikannya secara akurat. Untungnya, di Python ada sejumlah pustaka yang tersedia untuk membantu Anda dalam hal ini. Kami akan membahas beberapa solusi yang paling umum, mulai dari "lakukan sendiri". sys.argv
, ke pendekatan "selesai untuk Anda" dengan argparse
.
Menangani Argumen Baris Perintah dengan Python
Python 3+ dan ekosistem di sekitarnya mendukung sejumlah cara berbeda dalam menangani argumen baris perintah. Ada banyak perpustakaan yang memfasilitasi parsing argumen baris perintah.
Cara bawaan adalah dengan menggunakan sys
modul. Dalam hal nama, dan penggunaannya, ini berhubungan langsung dengan pustaka C (libc
).
Cara kedua adalah getopt
modul, yang menangani opsi pendek dan panjang, termasuk evaluasi nilai parameter.
Grafik modul argparse, yang diturunkan dari optparse
modul (tersedia hingga Python 2.7).
Grafik docopt
modul, yaitu tersedia di GitHub, juga memungkinkan fungsi yang sama.
Baru-baru ini absl
perpustakaan juga telah mendapatkan tenaga, sebagai sarana untuk menggantikan optparse
dan getopt()
.
Masing-masing cara ini memiliki pro dan kontra, jadi ada baiknya mengevaluasi masing-masing untuk melihat mana yang paling sesuai dengan kebutuhan Anda.
Modul sys
Ini adalah modul dasar yang telah dikirimkan dengan Python sejak awal. Dibutuhkan pendekatan yang sangat mirip dengan menggunakan perpustakaan C argc
/argv
untuk mengakses argumen. Itu modul sys mengimplementasikan argumen baris perintah dalam struktur daftar sederhana bernama sys.argv
.
Setiap elemen daftar mewakili satu argumen. Item pertama dalam daftar,
sys.argv[0]
, adalah nama skrip Python. Elemen daftar lainnya,sys.argv[1]
untuksys.argv[n]
, adalah argumen baris perintah 2 sampai n.
Sebagai pembatas antara argumen, spasi digunakan. Nilai argumen yang berisi spasi di dalamnya harus diapit oleh tanda kutip agar dapat diuraikan dengan benar sys
.
Setara dengan argc
hanyalah jumlah elemen dalam daftar. Untuk mendapatkan nilai ini, gunakan Python len()
operator. Kami akan menunjukkan ini dalam contoh kode nanti.
Mencetak Argumen CLI Pertama
Dalam contoh pertama ini, skrip kita akan menentukan cara pemanggilannya. Informasi ini disimpan dalam argumen baris perintah pertama, diindeks dengan 0. Kode di bawah ini menunjukkan bagaimana Anda mendapatkan nama skrip Python Anda:
import sys
print("The script has the name %s" % (sys.argv[0])
Simpan kode ini dalam file bernama arguments-program-name.py
, lalu beri nama seperti yang ditunjukkan di bawah ini. Outputnya adalah sebagai berikut dan berisi nama file, termasuk path lengkapnya:
$ 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
Seperti yang Anda lihat dari panggilan kedua di atas, kami tidak hanya mendapatkan nama file Python, tetapi juga path lengkap yang digunakan untuk memanggilnya.
Menghitung Jumlah Argumen
Dalam contoh kedua ini kami hanya menghitung jumlah argumen baris perintah menggunakan built-in len()
Metode. sys.argv
adalah daftar yang harus kita periksa. Pada kode di bawah ini, kita mendapatkan jumlah argumen dan kemudian kurangi 1 karena salah satu dari argumen tersebut (yaitu yang pertama) selalu ditetapkan sebagai nama file, yang tidak selalu berguna bagi kita. Jadi, jumlah sebenarnya dari argumen yang diberikan oleh pengguna adalah len(sys.argv) - 1
:
import sys
arguments = len(sys.argv) - 1
print ("The script is called with %i arguments" % (arguments))
Simpan dan beri nama file ini argument-count.py. Beberapa contoh pemanggilan skrip ini ditunjukkan di bawah ini. Ini mencakup tiga skenario berbeda:
- Panggilan tanpa argumen baris perintah lebih lanjut
- Panggilan dengan dua argumen
- Panggilan dengan dua argumen, di mana yang kedua adalah string yang dikutip berisi spasi
$ 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
Iterasi Melalui Argumen
Contoh ketiga kami menampilkan setiap argumen yang dikirim ke skrip Python, kecuali nama program itu sendiri. Oleh karena itu, kami mengulangi argumen baris perintah yang dimulai dengan the kedua elemen daftar. Ingatlah bahwa ini adalah indeks 1 karena daftar berbasis 0 di Python:
import sys
arguments = len(sys.argv) - 1
position = 1
while (arguments >= position):
print ("Parameter %i: %s" % (position, sys.argv[position]))
position = position + 1
Di bawah ini kami memanggil kode kami, yang disimpan ke file argument-output.py. Seperti yang dilakukan pada contoh kita sebelumnya, output mengilustrasikan tiga panggilan berbeda:
- Panggilan tanpa argumen
- Panggilan dengan dua argumen
- Panggilan dengan dua argumen, di mana argumen kedua adalah string yang dikutip berisi spasi
$ 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
Ingat, tujuan menunjukkan contoh string yang dikutip adalah bahwa parameter biasanya dibatasi oleh spasi, kecuali kalau mereka dikelilingi oleh tanda kutip.
Bendera Abseil (absl
)
Pustaka Bendera Abseil dimaksudkan untuk membawa argumen baris perintah ke produksi, dengan argumen baris perintah terdistribusi. Ketika sebuah modul menggunakan flag baris perintah, dan diimpor ke modul lain โ modul lain mengimpor bendera juga, dan dapat memprosesnya dengan meneruskannya ke modul yang diimpor.
Hal ini membuat argumen baris perintah kompleks yang dibagikan di antara modul menjadi lebih mudah dan tidak terlalu bertele-tele.
Selain itu, pustaka memungkinkan Anda menentukan nilai default, deskripsi, dan tipe data argumen, sehingga pemeriksaan dan konversi tambahan tidak diperlukan.
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}!")
Tipe data yang didukung adalah:
DEFINE_integer()
DEFINE_string()
DEFINE_bool()
DEFINE_enum()
DEFINE_list()
DEFINE_float()
Sebaik DEFINE_multi_integer()
, DEFINE_multi_string()
dan DEFINE_multi_enum()
untuk input multi-argumen. Selain itu, berlari --help
, --helpfull
, dll. cetak bendera yang ada dan deskripsinya, dalam format yang berbeda.
Lihat panduan praktis dan praktis kami untuk mempelajari Git, dengan praktik terbaik, standar yang diterima industri, dan termasuk lembar contekan. Hentikan perintah Googling Git dan sebenarnya belajar itu!
Pustaka juga memungkinkan Anda untuk menentukan validasi โ baik dari segi rentang, seperti nilai berbasis bilangan bulat yang memiliki upper_bound
or lower_bound
itu dapat diterima, dan menjalankan metode sewenang-wenang untuk memeriksa nilai:
def validate_name(value):
return len(value) > 15
flags.register_validator('name',
validate_name,
message='Name is over 15 characters long.',
flag_values=FLAGS)
Mengumpulkan ini menjadi contoh nyata:
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
...
Modul argparse
Grafik modul argparse telah tersedia sejak Python 3.2, dan peningkatan dari optparse
modul yang ada hingga Python 2.7. Dokumentasi Python berisi deskripsi API dan tutorial yang mencakup semua metode secara mendetail.
Modul ini menawarkan antarmuka baris perintah dengan keluaran standar, sedangkan dua solusi sebelumnya meninggalkan sebagian besar pekerjaan di tangan Anda. argparse
memungkinkan verifikasi argumen tetap dan opsional, dengan pemeriksaan nama sebagai gaya pendek atau panjang. Sebagai argumen opsional default, itu termasuk -h
, beserta versi panjangnya --help
. Argumen ini disertai dengan pesan bantuan default yang menjelaskan argumen yang diterima.
Kode di bawah ini menunjukkan inisialisasi parser, dan output di bawah ini menunjukkan panggilan dasar, diikuti dengan pesan bantuan. Berbeda dengan panggilan Python yang kita gunakan pada contoh sebelumnya, ingatlah untuk menggunakan Python 3 dengan contoh berikut:
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
Pada langkah selanjutnya, kami akan menambahkan deskripsi khusus ke pesan bantuan untuk pengguna kami. Menginisialisasi parser dengan cara ini memungkinkan teks tambahan. Kode di bawah ini menyimpan deskripsi di text
variabel, yang secara eksplisit diberikan kepada argparse
kelas sebagai description
parameter. Memanggil kode ini di bawah, Anda dapat melihat seperti apa hasilnya:
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
Sebagai langkah terakhir kita akan menambahkan argumen opsional bernama -V
, yang memiliki argumen gaya panjang yang sesuai bernama --version
. Untuk melakukannya kita menggunakan metode add_argument()
yang kita panggil dengan tiga parameter (ditampilkan untuk --version
, hanya):
- Nama parameternya:
--version
- Teks bantuan untuk parameter:
help="show program version"
- Tindakan (tanpa nilai tambahan):
action="store_true"
Kode sumber untuk itu ditampilkan di bawah ini. Membaca argumen ke dalam variabel yang disebut args
dilakukan melalui parse_args()
metode dari parser
obyek. Perhatikan bahwa Anda mengirimkan versi pendek dan panjang dalam satu panggilan. Terakhir, Anda memeriksa apakah atributnya args.V
or args.version
diatur dan menampilkan pesan versi:
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
Grafik --version
argumen tidak memerlukan nilai untuk diberikan pada baris perintah. Itu sebabnya kami menyetel argumen tindakan ke "store_true"
. Dalam kasus lain, Anda mungkin memerlukan nilai tambahan yang ditetapkan, misalnya jika Anda menentukan volume, tinggi, atau lebar tertentu. Ini ditunjukkan pada contoh berikutnya. Sebagai kasus default, perlu diketahui bahwa semua argumen ditafsirkan sebagai string:
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)
Di sini kami menunjukkan apa yang terjadi saat mengirimkan nilai argumen yang berbeda. Ini termasuk versi pendek dan panjang, serta pesan bantuan:
$ 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
Modul getopt
Seperti yang mungkin telah Anda perhatikan sebelumnya, the sys
module membagi string baris perintah menjadi satu sisi saja. Piton modul getopt melangkah lebih jauh dan memperluas pemisahan string input dengan validasi parameter. Berdasarkan getopt
C, ini memungkinkan opsi pendek dan panjang, termasuk penugasan nilai.
Dalam prakteknya, itu membutuhkan sys
modul untuk mengolah data masukan dengan baik. Untuk melakukannya, kedua sys
modul dan getopt
modul harus dimuat terlebih dahulu. Selanjutnya, dari daftar parameter input, kami menghapus elemen daftar pertama (lihat kode di bawah), dan menyimpan daftar argumen baris perintah yang tersisa dalam variabel yang disebut argument_list
:
import getopt, sys
full_cmd_arguments = sys.argv
argument_list = full_cmd_arguments[1:]
print argument_list
Argumen dalam argument_list
sekarang dapat diuraikan menggunakan getopts()
metode. Tapi sebelum melakukan itu, kita perlu memberi tahu getopts()
tentang parameter mana yang valid. Mereka didefinisikan seperti ini:
short_options = "ho:v"
long_options = ["help", "output=", "verbose"]
Ini berarti argumen ini adalah argumen yang kami anggap valid, bersama dengan beberapa info tambahan:
------------------------------------------
long argument short argument with value
------------------------------------------
--help -h no
--output -o yes
--verbose -v no
------------------------------------------
Anda mungkin telah memperhatikan bahwa o
opsi pendek dilanjutkan dengan tanda titik dua, :
. Ini memberitahu getopt
bahwa opsi ini harus diberi nilai.
Ini sekarang memungkinkan kita untuk memproses daftar argumen. Itu getopt()
metode membutuhkan tiga parameter untuk dikonfigurasi - daftar argumen aktual dari argv
, serta opsi short dan long yang valid (ditampilkan di cuplikan kode sebelumnya).
Pemanggilan metode itu sendiri disimpan dalam pernyataan try-catch untuk menutupi kesalahan selama evaluasi. Pengecualian dimunculkan jika ditemukan argumen yang bukan bagian dari daftar seperti yang didefinisikan sebelumnya. Skrip Python akan mencetak pesan kesalahan ke layar, dan keluar dengan kode kesalahan 2:
try:
arguments, values = getopt.getopt(argument_list, short_options, long_options)
except getopt.error as err:
print (str(err))
sys.exit(2)
Akhirnya, argumen dengan nilai yang sesuai disimpan dalam dua variabel bernama arguments
dan values
. Sekarang, Anda dapat dengan mudah mengevaluasi variabel-variabel ini dalam kode Anda. Kita dapat menggunakan a for
-loop untuk beralih melalui daftar argumen yang dikenali, satu entri demi entri berikutnya.
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))
Di bawah ini Anda dapat melihat output dari mengeksekusi kode ini. Kami akan menunjukkan bagaimana program bereaksi dengan argumen program yang valid dan tidak valid:
$ 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
Panggilan terakhir ke program kami mungkin tampak agak membingungkan pada awalnya. Untuk memahaminya, Anda perlu mengetahui bahwa opsi steno (terkadang juga disebut bendera) dapat digunakan bersama dengan satu tanda hubung. Ini memungkinkan alat Anda untuk lebih mudah menerima banyak opsi. Misalnya menelepon python arguments-getopt.py -vh
adalah sama dengan menelepon python arguments-getopt.py -v -h
. Jadi pada panggilan terakhir di atas, the getopt
modul pikir pengguna sedang mencoba untuk lulus -e
sebagai opsi, yang tidak valid.
Kesimpulan
Pada artikel ini kami menunjukkan banyak metode berbeda untuk mengambil argumen baris perintah dengan Python, termasuk menggunakan sys
, getopt
, dan argparse
. Modul-modul ini bervariasi dalam fungsinya, beberapa menyediakan lebih dari yang lain. sys
sepenuhnya fleksibel, sedangkan keduanya getopt
dan argparse
memerlukan beberapa struktur. Sebaliknya, mereka menutupi sebagian besar pekerjaan rumit itu sys
terserah padamu. Setelah mengerjakan contoh-contoh yang diberikan, Anda harus dapat menentukan modul mana yang paling sesuai dengan proyek Anda.
Pada artikel ini kami tidak berbicara tentang solusi lain seperti docopts
modul, kami baru saja menyebutkannya. Modul ini mengikuti pendekatan yang sama sekali berbeda, dan akan dijelaskan secara rinci di salah satu artikel berikutnya.