Argumen Baris Perintah dengan Python

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] untuk sys.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 getoptdan 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.

Referensi

Stempel Waktu:

Lebih dari penyalahgunaan