Periksa apakah argumen opsional argparse disetel atau tidak

112

Saya ingin memeriksa apakah argumen argparse opsional telah ditetapkan oleh pengguna atau tidak.

Bisakah saya memeriksa dengan aman menggunakan isset?

Sesuatu seperti ini:

if(isset(args.myArg)):
    #do something
else:
    #do something else

Apakah ini bekerja sama untuk argumen tipe float / int / string?

Saya bisa menyetel parameter default dan memeriksanya (misalnya, set myArg = -1, atau "" untuk string, atau "NOT_SET"). Namun, nilai yang akhirnya ingin saya gunakan hanya dihitung nanti dalam skrip. Jadi saya akan mengaturnya ke -1 sebagai default, dan kemudian memperbaruinya ke sesuatu yang lain nanti. Ini tampaknya sedikit kikuk dibandingkan dengan hanya memeriksa apakah nilainya ditetapkan oleh pengguna.

Madeleine P. Vincent
sumber
1
Apa jadinya isset()(petunjuk: Python bukan PHP)? Apakah yang Anda maksud hasattr()sebaliknya, mungkin? Mengapa tidak mengonfigurasi argparse untuk menyetel default untuk suatu opsi?
Martijn Pieters
@MartijnPieters - ya, benar. Jadi bisakah saya memeriksa apakah (args.myArg): ...
Madeleine P. Vincent

Jawaban:

146

Saya pikir argumen opsional (ditentukan dengan --) diinisialisasi Nonejika tidak diberikan. Jadi Anda bisa mengujinya dengan is not None. Coba contoh di bawah ini:

import argparse as ap

def main():
    parser = ap.ArgumentParser(description="My Script")
    parser.add_argument("--myArg")
    args, leftovers = parser.parse_known_args()

    if args.myArg is not None:
        print "myArg has been set (value is %s)" % args.myArg
Honza Osobne
sumber
Tes "is None" dan "is not None" bekerja persis seperti yang saya inginkan dan harapkan. Terima kasih.
Madeleine P. Vincent
39
Sayangnya itu tidak berhasil maka argumen itu defaultmenentukan nilainya.
kcpr
6
Jika Anda ingin menyetel default, Anda masih dapat menyetel nargs='?'dan memberikan constnilai, seperti yang dijelaskan di dokumen . Ketika arg tidak ada, defaultdigunakan, ketika arg diberikan nilai w / o, maka constdigunakan, jika tidak nilai yang diberikan digunakan. Dengan only defaultand nargs='?', defaultdigunakan jika tidak diberikan, Nonejika diberikan nilai w / o, sebaliknya nilai yang diberikan.
Ioannis Filippidis
@IoannisFilippidis jika Anda menggunakan action= "store_true"atau action="store_const", const="yourconst"Anda tidak dapat menggunakan argumen itu untuk menyimpan nilai lain. Ini tidak akan berfungsi saat menggunakan default. Secara pribadi, saya telah menghapus semua default dari argparser dan menangani semua di dalam fungsi lain di def defaults():mana saya mencampur ConfigParser, ArgumentParser dan nilai default dalam urutan yang saya inginkan
m3nda
@ erm3nda Saya tidak menyebutkan pengaturan action. Jawabannya tidak menggunakan action. Tindakan yang Anda sebutkan didokumentasikan untuk berperilaku dalam satu cara tertentu (seperti yang Anda amati). Tindakan tidak perlu didefinisikan.
Ioannis Filippidis
37

Karena catatan @Honza is Noneadalah ujian yang bagus. Ini default default, dan pengguna tidak dapat memberi Anda string yang menduplikasinya.

Anda dapat menentukan yang lain default='mydefaultvalue, dan mengujinya. Tetapi bagaimana jika pengguna menentukan string itu? Apakah itu dihitung sebagai pengaturan atau tidak?

Anda juga bisa menentukan default=argparse.SUPPRESS. Kemudian jika pengguna tidak menggunakan argumen, itu tidak akan muncul di argsnamespace. Tetapi pengujian itu mungkin lebih rumit:

args.foo # raises an AttributeError
hasattr(args, 'foo')  # returns False
getattr(args, 'foo', 'other') # returns 'other'

Secara internal parsermenyimpan daftar seen_actions, dan menggunakannya untuk pengujian 'diperlukan' dan 'mutually_exclusive'. Tapi itu tidak tersedia untuk Anda di luar parse_args.

hpaulj
sumber
22

Saya pikir menggunakan opsi default=argparse.SUPPRESSpaling masuk akal. Kemudian, alih-alih memeriksa apakah argumennya not None, memeriksa apakah argumen adalah innamespace yang dihasilkan.

Contoh:

import argparse

parser = argparse.ArgumentParser()
parser.add_argument("--foo", default=argparse.SUPPRESS)
ns = parser.parse_args()

print("Parsed arguments: {}".format(ns))
print("foo in namespace?: {}".format("foo" in ns))

Pemakaian:

$ python argparse_test.py --foo 1
Parsed arguments: Namespace(foo='1')
foo in namespace?: True
Argumen tidak diberikan:
$ python argparse_test.py
Parsed arguments: Namespace()
foo in namespace?: False
Erasmus Cedernaes
sumber
Ini tidak berfungsi untuk saya dengan Python 3.7.5 (Anaconda). Saya mendapatkan hasilnyatestfoo.py: error: argument --foo: expected one argument
Mike Wise
@MikeWise Jika Anda ingin menggunakan --footanpa nilai (misalnya 1dalam contoh saya), Anda harus menentukan nargs=0dalam add_argumentfungsinya.
Erasmus Cedernaes
Saya baru saja menyalin dan menempelkan kode Anda seperti yang ditentukan dalam jawaban. Mungkin Anda harus mengeditnya? Saya akhirnya menggunakan action='store_true'jawaban di bawah ini sebagai gantinya dalam kode saya yang sebenarnya.
Mike Wise
@MikeWise apakah Anda menjalankan skrip sebagai python argparse_test.py --foo 1?
Erasmus Cedernaes
11

Anda dapat memeriksa flag yang diteruskan secara opsional dengan store_truedan store_falseopsi tindakan argumen:

import argparse

argparser = argparse.ArgumentParser()
argparser.add_argument('-flag', dest='flag_exists', action='store_true')

print argparser.parse_args([])
# Namespace(flag_exists=False)
print argparser.parse_args(['-flag'])
# Namespace(flag_exists=True)

Dengan cara ini, Anda tidak perlu khawatir tentang memeriksa dengan bersyarat is not None. Anda cukup memeriksa Trueatau False. Baca lebih lanjut tentang opsi ini dalam dokumen di sini

Harry Sadler
sumber
1
ini tidak menyelesaikan untuk mengetahui apakah argumen yang memiliki nilai ditetapkan atau tidak. masalah utama di sini adalah untuk mengetahui apakah nilai args berasal dari defaul = "" atau diberikan oleh pengguna.
m3nda
5

Jika argumen Anda posisional (misalnya tidak memiliki awalan "-" atau "-", hanya argumennya, biasanya nama file) maka Anda dapat menggunakan parameter nargs untuk melakukan ini:

parser = argparse.ArgumentParser(description='Foo is a program that does things')
parser.add_argument('filename', nargs='?')
args = parser.parse_args()

if args.filename is not None:
    print('The file name is {}'.format(args.filename))
else:
    print('Oh well ; No args, no problems')
yPhil
sumber
3

Berikut adalah solusi saya untuk melihat apakah saya menggunakan variabel argparse

import argparse

ap = argparse.ArgumentParser()
ap.add_argument("-1", "--first", required=True)
ap.add_argument("-2", "--second", required=True)
ap.add_argument("-3", "--third", required=False) 
# Combine all arguments into a list called args
args = vars(ap.parse_args())
if args["third"] is not None:
# do something

Ini mungkin memberi lebih banyak wawasan untuk jawaban di atas yang saya gunakan dan sesuaikan untuk bekerja untuk program saya.

C. Radford
sumber
0

Untuk menanggapi komentar @ kcpr atas jawaban (yang diterima saat ini) oleh @Honza Osobne

Sayangnya itu tidak berfungsi maka argumen itu menetapkan nilai defaultnya.

pertama-tama kita dapat memeriksa apakah argumen disediakan dengan membandingkannya dengan Namespaceobjek abd yang menyediakan default=argparse.SUPPRESSopsi (lihat jawaban @ hpaulj dan @Erasmus Cedernaes dan dokumen python3 ini ) dan jika belum disediakan, setel ke nilai default.

import argparse

parser = argparse.ArgumentParser()
parser.add_argument('--infile', default=argparse.SUPPRESS)
args = parser.parse_args()
if 'infile' in args: 
    # the argument is in the namespace, it's been provided by the user
    # set it to what has been provided
    theinfile = args.infile
    print('argument \'--infile\' was given, set to {}'.format(theinfile))
else:
    # the argument isn't in the namespace
    # set it to a default value
    theinfile = 'your_default.txt'
    print('argument \'--infile\' was not given, set to default {}'.format(theinfile))

Pemakaian

$ python3 testargparse_so.py
argument '--infile' was not given, set to default your_default.txt

$ python3 testargparse_so.py --infile user_file.txt
argument '--infile' was given, set to user_file.txt
calocedrus.dll
sumber
0

Sangat sederhana, setelah mendefinisikan variabel args dengan 'args = parser.parse_args ()' itu berisi semua data variabel subset args juga. Untuk memeriksa apakah sebuah variabel disetel atau tidak dengan asumsi 'action = "store_true" digunakan ...

if args.argument_name:
   # do something
else:
   # do something else
vatsa287.dll
sumber