Memeriksa apakah sys.argv [x] sudah ditentukan


Jawaban:


64

Pada akhirnya, perbedaan antara try, exceptdan pengujian len(sys.argv)tidak terlalu signifikan. Keduanya agak sedikit hackish dibandingkan argparse.

Ini terjadi pada saya, meskipun - sebagai semacam argumen anggaran rendah:

arg_names = ['command', 'x', 'y', 'operation', 'option']
args = dict(zip(arg_names, sys.argv))

Anda bahkan dapat menggunakannya untuk menghasilkan namedtupledengan nilai yang default None- semuanya dalam empat baris!

Arg_list = collections.namedtuple('Arg_list', arg_names)
args = Arg_list(*(args.get(arg, None) for arg in arg_names))

Jika Anda tidak terbiasa namedtuple, itu hanya tupel yang bertindak seperti objek, memungkinkan Anda mengakses nilainya menggunakan tup.attributesintaks alih-alih tup[0]sintaks.

Jadi baris pertama membuat namedtupletipe baru dengan nilai untuk setiap nilai dalam arg_names. Baris kedua meneruskan nilai dari argskamus, menggunakan getuntuk mengembalikan nilai default saat nama argumen yang diberikan tidak memiliki nilai terkait di kamus.


Saya semakin menyukai Python, semua berkat jawaban seperti itu dan tentu saja Stack Overflow! Sayang sekali kami tidak memiliki penjelasan tentang dua baris terakhir. Saya percaya untuk pemula itu akan bagus.
Goujon

2
Suka! Mudah solusi terbaik yang pernah saya lihat dari masalah ini. Untuk orang lain: Tidak langsung jelas bagi saya (newb) bahwa: 1) 'perintah' akan dikirimkan sebagai argumen pertama setiap kali dan 2) Anda dapat memanggil hasil dengan args [0] dll.
Matt D

Ini memang keren, tapi apa gunanya menguji panjangnya?
colorlace

1
@timwiz Saya hanya berbicara dibandingkan dengan menggunakan argparse. Namun, akhir-akhir ini, saya menyalahkan diri sendiri setiap kali saya kembali ke skrip lama dan ternyata saya tidak menggunakan argparse.
pengirim

116

Periksa panjang sys.argv:

if len(sys.argv) > 1:
    blah = sys.argv[1]
else:
    blah = 'blah'

Beberapa orang lebih suka pendekatan berbasis pengecualian yang Anda sarankan (misalnya, try: blah = sys.argv[1]; except IndexError: blah = 'blah'), tetapi saya tidak terlalu menyukainya karena tidak “menskalakan” sebaik yang Anda inginkan (misalnya, ketika Anda ingin menerima dua atau tiga argumen) dan berpotensi menyembunyikan kesalahan (misalnya, jika Anda menggunakan blah = foo(sys.argv[1]), tetapi foo(...)memunculkan IndexError, itu IndexErrorakan diabaikan).


1
Selama Anda bersikap atom tentang itu, tidak ada yang perlu dikhawatirkan try, except. Tunggu saja fooargumen Anda sampai elseklausulnya.
pengirim

3
Selain itu, setelah Anda memikirkan tentang penskalaan, inilah saatnya beralih ke argparse.
pengirim

1
+1 di argparse. Saya memiliki argparse.pysemua proyek baris perintah saya.
David Wolever

2
@senderle: tentu, jika Anda rajin, tidak apa-apa. Namun menurut pengalaman saya, sebagian besar programmer tidak rajin dan memasukkan semua logika dalam tryklausa… Jadi, mengingat itu tidak lebih sulit (dan, IMO, sedikit lebih cantik), saya lebih suka memeriksa panjangnya (juga, Anda menghindari orang berteriak pada Anda karena menggunakan pengecualian untuk kontrol aliran).
David Wolever

2
@ David, ya, saya mengerti maksud Anda. Saya seorang tryapologis, harus saya akui. Saya hanya merasa terkadang hal itu mengungkapkan maksud saya dengan lebih jelas daripada ifpernyataan.
pengirim

22

Cara lain yang belum saya lihat adalah dengan mengatur nilai sentinel Anda sebelumnya. Metode ini memanfaatkan evaluasi malas Python, di mana Anda tidak selalu harus memberikan elsepernyataan. Contoh:

startingpoint = 'blah'
if len(sys.argv) >= 2:
  startingpoint = sys.argv[1]

Atau jika Anda menggunakan sintaks CRAZY, Anda dapat menggunakan operator terner Python :

startingpoint = sys.argv[1] if len(sys.argv) >= 2 else 'blah'

1
Jawaban operator terner adalah yang paling cantik di mata saya. Saya duduk di sini diam-diam mengutuk fakta bahwa beberapa perangkat lunak yang saya pelihara terkait dengan Python 2.4, yang tidak memilikinya.
Richard Barrell

11

Saya menggunakan ini - tidak pernah gagal:

startingpoint = 'blah'
if sys.argv[1:]:
   startingpoint = sys.argv[1]

Itu bukan untuk memeriksa jika ditentukan. Lebih seperti definisikan jika ada, yang tidak sama. Saya menggunakan cara itu juga untuk menilai variabel fallback, tetapi bukan jawaban untuk pertanyaan saat ini.
m3nda

@ erm3nda Saya dapat menghapus startingpointvariabel dari contoh, tetapi pertanyaannya adalah menetapkan variabel mundur, jadi saya hanya membuat hal yang sama.
anatoly techtonik

1
Jika Anda menghapusnya, Anda akan mendapatkan error tentang variabel tidak ditentukan. Saya telah membaca lagi pertanyaannya, dan apa yang dia harapkan adalah, penggantian variabel :) jadi tidak apa-apa. Terima kasih atas saran singkatnya jika sys.argv[1:]:. Ini bekerja dengan argumen posisi sementara hitungan tidak.
m3nda

10

Ini daftar Python biasa. Pengecualian yang Anda tangkap untuk ini adalah IndexError, tetapi Anda lebih baik memeriksa panjangnya saja.

if len(sys.argv) >= 2:
  startingpoint = sys.argv[1]
else:
  startingpoint = 'blah'

2

Sebuah solusi yang bekerja dengan fonction built-in map!

arg_names = ['command' ,'operation', 'parameter']
args = map(None, arg_names, sys.argv)
args = {k:v for (k,v) in args}

Maka Anda hanya perlu memanggil parameter Anda seperti ini:

if args['operation'] == "division":
    if not args['parameter']:
        ...
    if args['parameter'] == "euclidian":
        ...

1

Anda cukup menambahkan nilai argv [1] ke argv dan kemudian memeriksa apakah argv [1] tidak sama dengan string yang Anda masukkan. Contoh:

from sys import argv
argv.append('SomeString')
if argv[1]!="SomeString":
            print(argv[1])

bagi mereka yang memilih saya, malu pada Anda, karena tidak mengklarifikasi kesalahan.
Hassan Abdul-Kareem

Saya rasa itu karena itu hackish. Bagaimana jika seseorang melewatkan SomeString sebagai argumen? Bagaimana cara menggunakannya jika Anda dapat menerima katakanlah 1 sampai 5 argumen?
pbogut

Cool (tapi masih hackish) untuk menyetel nilai default jika pengguna tidak memberikan argumen. Cukup tambahkan dan kemudian gunakan argv [1].
Felizett

1

Cukup dekat dengan apa yang coba dilakukan oleh pencetusnya. Berikut adalah fungsi yang saya gunakan:

def get_arg(index):
    try:
        sys.argv[index]
    except IndexError:
        return ''
    else:
        return sys.argv[index]

Jadi penggunaannya akan seperti ini:

if __name__ == "__main__":
    banner(get_arg(1),get_arg(2))
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.