Saya ingin menggunakan argumen argparse untuk mem-parsing baris perintah boolean yang ditulis sebagai "--foo True" atau "--foo False". Sebagai contoh:
my_program --my_boolean_flag False
Namun, kode tes berikut tidak melakukan apa yang saya inginkan:
import argparse
parser = argparse.ArgumentParser(description="My parser")
parser.add_argument("--my_bool", type=bool)
cmd_line = ["--my_bool", "False"]
parsed_args = parser.parse(cmd_line)
Sedihnya, parsed_args.my_bool
dievaluasi menjadi True
. Ini adalah kasus bahkan ketika saya berubah cmd_line
menjadi ["--my_bool", ""]
, yang mengejutkan, sejak bool("")
dievakuasi False
.
Bagaimana saya bisa mendapatkan argparse untuk mengurai "False"
, "F"
dan huruf kecil mereka varian untuk menjadi False
?
python
boolean
argparse
command-line-parsing
SuperElectric
sumber
sumber
parser.add_argument('--feature', dest='feature', default=False, action='store_true')
. Solusi ini akan menjamin Anda selalu mendapatkanbool
jenis dengan nilaiTrue
atauFalse
. (Solusi ini memiliki kendala: opsi Anda harus memiliki nilai default.)parser.add_argument('--feature', dest='feature', type=lambda x:bool(distutils.util.strtobool(x)))
. Ketika opsi ini digunakan, solusi ini akan memastikanbool
jenis dengan nilaiTrue
atauFalse
. Ketika opsi tidak digunakan, Anda akan mendapatkanNone
. (distutils.util.strtobool(x)
dari pertanyaan stackoverflow lainnya )parser.add_argument('--my_bool', action='store_true', default=False)
Jawaban:
Namun solusi lain menggunakan saran sebelumnya, tetapi dengan kesalahan parse "benar" dari
argparse
:Ini sangat berguna untuk membuat sakelar dengan nilai default; contohnya
memungkinkan saya untuk menggunakan:
dan masih menggunakan nilai default (khusus untuk pengaturan pengguna). Satu kelemahan (terkait tidak langsung) dengan pendekatan itu adalah bahwa 'nargs' mungkin menangkap argumen posisi - lihat pertanyaan terkait ini dan laporan bug argparse ini .
sumber
str2bool(v)
dapat diganti denganbool(distutils.util.strtobool(v))
. Sumber: stackoverflow.com/a/18472142/2436175if args.nice:
karena jika argumen diatur ke False, itu tidak akan pernah melewati kondisi. Jika ini benar maka mungkin lebih baik untuk kembali daftar daristr2bool
fungsi dan set daftar sebagaiconst
parameter, seperti ini[True]
,[False]
. Perbaiki saya jika saya salahSaya pikir cara yang lebih kanonik untuk melakukan ini adalah melalui:
dan
argparse
mendukung versi ini dengan baik:Tentu saja, jika Anda benar-benar menginginkan
--arg <True|False>
versi tersebut, Anda dapat lulusast.literal_eval
sebagai "tipe", atau fungsi yang ditentukan pengguna ...sumber
type=bool
harus bekerja di luar kotak (pertimbangkan argumen posisi!). Bahkan ketika Anda menentukan tambahanchoices=[False,True]
, Anda berakhir dengan "False" dan "True" dianggap Benar (karena pemain dari string ke bool?). Mungkin masalah terkaitbool()
harus dilakukan fungsi Python , atau apa argumen yang harus diterimatype=fn
? Semuaargparse
cek adalah yangfn
bisa dipanggil. Itu mengharapkanfn
untuk mengambil satu argumen string, dan mengembalikan nilai. Perilakufn
adalah tanggung jawab programmer, bukanargparse's
.Saya merekomendasikan jawaban mgilson tetapi dengan grup yang saling eksklusif
sehingga Anda tidak dapat menggunakan
--feature
dan--no-feature
pada saat yang sama.dan
tapi tidak
Naskah:
Anda kemudian dapat menggunakan pembantu ini jika Anda akan mengatur banyak dari mereka:
sumber
add_argument
dipanggil dengandest='feature'
.set_defaults
disebut denganfeature=True
. Memahami?--flag False
, bagian dari jawaban SO harus tentang APA yang mereka coba selesaikan, bukan hanya tentang BAGAIMANA. Seharusnya sama sekali tidak ada alasan untuk melakukan--flag False
atau--other-flag True
menggunakan parser khusus untuk mengonversi string menjadi boolean ..action='store_true'
danaction='store_false'
merupakan cara terbaik untuk menggunakan bendera boolean... can be “don’t do that”, but it should also include “try this instead”
jawaban yang (setidaknya bagi saya) menyiratkan jawaban harus masuk lebih dalam jika sesuai. Pasti ada saat-saat ketika sebagian dari kita memposting pertanyaan dapat mengambil manfaat dari panduan tentang praktik yang lebih baik / terbaik, dll. Menjawab "sebagaimana dinyatakan" sering kali tidak melakukannya. Yang sedang berkata, frustrasi Anda dengan jawaban sering menganggap terlalu banyak (atau salah) benar-benar valid.parser.set_defaults(feature=None)
help=
entri untuk argumen ini, kemana perginya? Dalamadd_mutually_exclusive_group()
panggilan? Dalam satu atau keduaadd_argument()
panggilan? Di tempat lain?Berikut adalah variasi lain tanpa baris tambahan untuk menetapkan nilai default. Bool selalu memiliki nilai yang ditetapkan sehingga dapat digunakan dalam pernyataan logis tanpa pemeriksaan awal.
sumber
required=True
atau Anda akan selalu mendapatkan argumen True.python3 test.py --do-something False
gagal denganerror: unrecognized arguments: False
, sehingga tidak benar-benar menjawab pertanyaan.oneliner:
sumber
type=lambda x: (str(x).lower() in ['true','1', 'yes'])
Tampaknya ada beberapa kebingungan tentang apa
type=bool
dan apatype='bool'
artinya. Haruskah satu (atau keduanya) berarti 'menjalankan fungsibool()
, atau' mengembalikan boolean '? Seperti berdiritype='bool'
tidak ada artinya.add_argument
memberikan'bool' is not callable
kesalahan, sama seperti jika Anda menggunakantype='foobar'
, atautype='int'
.Tetapi
argparse
apakah memiliki registri yang memungkinkan Anda menentukan kata kunci seperti ini. Ini sebagian besar digunakan untukaction
, misalnya `action = 'store_true'. Anda dapat melihat kata kunci yang terdaftar dengan:yang menampilkan kamus
Ada banyak tindakan yang ditentukan, tetapi hanya satu jenis, yang standar
argparse.identity
,.Kode ini mendefinisikan kata kunci 'bool':
parser.register()
tidak didokumentasikan, tetapi juga tidak disembunyikan. Untuk sebagian besar programmer tidak perlu tahu tentang hal itu karenatype
danaction
fungsi mengambil dan kelas nilai-nilai. Ada banyak contoh stackoverflow mendefinisikan nilai-nilai khusus untuk keduanya.Dalam hal ini tidak jelas dari diskusi sebelumnya,
bool()
tidak berarti 'mengurai string'. Dari dokumentasi Python:Bandingkan ini dengan
sumber
Saya mencari masalah yang sama, dan solusi yang bagus adalah:
dan menggunakannya untuk mengurai string ke boolean seperti yang disarankan di atas.
sumber
distutils.util.strtobool(v)
.distutils.util.strtobool
1 atau 0, bukan boolean yang sebenarnya.Cara yang sangat mirip adalah dengan menggunakan:
dan jika Anda mengatur argumen - fitur dalam perintah Anda
argumennya adalah True, jika Anda tidak menyetel tipe --feature, argumen default selalu False!
sumber
--feature False
Selain apa yang dikatakan @mgilson, perlu dicatat bahwa ada juga
ArgumentParser.add_mutually_exclusive_group(required=False)
metode yang membuatnya sepele untuk menerapkannya--flag
dan--no-flag
tidak digunakan pada saat yang sama.sumber
Ini berfungsi untuk semua yang saya harapkan:
Kode:
sumber
_str_to_bool(s)
untuk mengkonversis = s.lower()
sekali, lalu mengujiif s not in {'true', 'false', '1', '0'}
, dan akhirnyareturn s in {'true', '1'}
.Cara yang lebih sederhana adalah menggunakan seperti di bawah ini.
sumber
Paling sederhana. Ini tidak fleksibel, tetapi saya lebih suka kesederhanaan.
EDIT: Jika Anda tidak percaya input, jangan gunakan
eval
.sumber
eval
adalah fungsi bawaan. docs.python.org/3/library/functions.html#eval Ini bisa merupakan fungsi yang tidak disadari yang memanfaatkan pendekatan lain yang lebih fleksibel.Cara paling sederhana adalah menggunakan pilihan :
Tidak lewat --my-flag mengevaluasi ke False. Opsi diperlukan = Benar dapat ditambahkan jika Anda selalu ingin pengguna untuk secara eksplisit menentukan pilihan.
sumber
Saya pikir cara yang paling kanonik adalah:
sumber
sumber
Cara paling sederhana & paling benar adalah
Perhatikan bahwa nilai True adalah y, ya, t, benar, dan 1; nilai false adalah n, no, f, false, off dan 0. Meningkatkan ValueError jika val adalah hal lain.
sumber
Cepat dan mudah, tetapi hanya untuk argumen 0 atau 1:
Output akan menjadi "Salah" setelah menelepon dari terminal:
sumber
Mirip dengan @Akash tapi di sini ada pendekatan lain yang pernah saya gunakan. Ini menggunakan
str
daripadalambda
karena pythonlambda
selalu memberi saya perasaan asing.sumber
Sebagai peningkatan jawaban @Akash Desarda, Anda bisa melakukannya
Dan itu mendukung
python test.py --foo
sumber