ตรวจสอบว่ามีการตั้งค่าอาร์กิวเมนต์ที่เป็นทางเลือก argparse หรือไม่


113

ฉันต้องการตรวจสอบว่าอาร์กิวเมนต์อาร์กิวเมนต์ที่เป็นทางเลือกถูกตั้งค่าโดยผู้ใช้หรือไม่

ฉันสามารถตรวจสอบโดยใช้ isset ได้อย่างปลอดภัยหรือไม่?

สิ่งนี้:

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

การทำงานนี้เหมือนกันสำหรับอาร์กิวเมนต์ประเภท float / int / string หรือไม่

ฉันสามารถตั้งค่าพารามิเตอร์เริ่มต้นและตรวจสอบได้ (เช่นตั้งค่า myArg = -1 หรือ "" สำหรับสตริงหรือ "NOT_SET") อย่างไรก็ตามค่าที่ฉันต้องการใช้ในท้ายที่สุดจะคำนวณในภายหลังในสคริปต์เท่านั้น ดังนั้นฉันจะตั้งค่าเป็น -1 เป็นค่าเริ่มต้นแล้วอัปเดตเป็นอย่างอื่นในภายหลัง ดูเหมือนจะงุ่มง่ามเล็กน้อยเมื่อเทียบกับการตรวจสอบว่าผู้ใช้กำหนดค่าหรือไม่


1
จะisset()เป็นอย่างไร (คำใบ้: Python ไม่ใช่ PHP) คุณหมายถึงhasattr()แทนหรือไม่? ทำไมไม่กำหนดค่า argparse เพื่อตั้งค่าเริ่มต้นสำหรับตัวเลือกแทน?
Martijn Pieters

@MartijnPieters - ใช่จริง ดังนั้นฉันสามารถตรวจสอบได้ว่า (args.myArg): ...
Madeleine P. Vincent

คำตอบ:


147

ฉันคิดว่าอาร์กิวเมนต์ที่เป็นทางเลือก (ระบุด้วย--) ถูกเตรียมใช้งานNoneหากไม่ได้ให้มา is not Noneดังนั้นคุณสามารถทดสอบด้วย ลองดูตัวอย่างด้านล่าง:

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

การทดสอบ "ไม่มี" และ "ไม่ใช่ไม่มี" ทำงานตรงตามที่ฉันต้องการและคาดหวัง ขอบคุณ.
Madeleine P. Vincent

39
น่าเสียดายที่มันไม่ได้ผลจากนั้นอาร์กิวเมนต์ได้defaultกำหนดค่าแล้ว
kcpr

6
หากคุณต้องการตั้งค่าdefaultแล้วคุณยังสามารถตั้งค่าnargs='?'และให้constความคุ้มค่าตามที่อธิบายไว้ในเอกสาร เมื่อไม่มีอาร์กิวเมนต์จะdefaultใช้เมื่อระบุค่า w / o จากนั้นconstจะใช้ค่าที่กำหนดจะถูกใช้ มีเพียงdefaultและnargs='?', defaultจะใช้ในกรณีที่ไม่ได้รับNoneหากได้รับ w / o ค่ามิฉะนั้นค่าที่กำหนด
Ioannis Filippidis

@IoannisFilippidis ถ้าคุณใช้action= "store_true"หรือaction="store_const", const="yourconst"คุณไม่สามารถใช้อาร์กิวเมนต์นั้นเพื่อเก็บค่าอื่น ๆ สิ่งนี้จะไม่ทำงานเมื่อใช้ค่าเริ่มต้น ด้วยตัวฉันเองฉันได้ลบค่าเริ่มต้นทั้งหมดออกจาก argparser และจัดการทั้งหมดภายในฟังก์ชันอื่นdef defaults():ที่ฉันผสม ConfigParser, ArgumentParser และค่าเริ่มต้นตามลำดับที่ฉันต้องการ
m3nda

@ erm3nda ฉันไม่ได้พูดถึงการตั้งค่าactionไฟล์. คำตอบไม่ใช้actionไฟล์. การดำเนินการที่คุณกล่าวถึงได้รับการบันทึกว่ามีพฤติกรรมในลักษณะเฉพาะอย่างใดอย่างหนึ่ง (ตามที่คุณสังเกตเห็น) ไม่จำเป็นต้องกำหนดการกระทำ
Ioannis Filippidis

37

บันทึกของ @Honza is Noneเป็นการทดสอบที่ดี เป็นค่าเริ่มต้นdefaultและผู้ใช้ไม่สามารถให้สตริงที่ซ้ำกับคุณได้

คุณสามารถระบุรายการอื่นdefault='mydefaultvalueและทดสอบได้ แต่ถ้าผู้ใช้ระบุสตริงนั้นล่ะ? นั่นนับเป็นการตั้งค่าหรือไม่?

default=argparse.SUPPRESSนอกจากนี้คุณยังสามารถระบุ จากนั้นหากผู้ใช้ไม่ใช้อาร์กิวเมนต์ก็จะไม่ปรากฏในargsเนมสเปซ แต่การทดสอบที่อาจซับซ้อนกว่านี้:

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

ภายในparserจะเก็บรายการseen_actionsและใช้สำหรับการทดสอบ 'จำเป็น' และ 'mutually_exclusive' parse_argsแต่มันไม่ได้มีให้คุณออกด้านข้างของ


22

ฉันคิดว่าการใช้ตัวเลือกdefault=argparse.SUPPRESSนี้เหมาะสมที่สุด จากนั้นแทนที่จะตรวจสอบว่าอาร์กิวเมนต์คือnot Noneใครจะตรวจสอบว่าอาร์กิวเมนต์เป็นinเนมสเปซที่เป็นผลลัพธ์หรือไม่

ตัวอย่าง:

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))

การใช้งาน:

$ python argparse_test.py --foo 1
Parsed arguments: Namespace(foo='1')
foo in namespace?: True
ไม่ได้ให้อาร์กิวเมนต์:
$ python argparse_test.py
Parsed arguments: Namespace()
foo in namespace?: False

สิ่งนี้ใช้ไม่ได้สำหรับฉันภายใต้ Python 3.7.5 (Anaconda) ฉันได้รับผลtestfoo.py: error: argument --foo: expected one argument
Mike Wise

@MikeWise หากคุณต้องการใช้--fooโดยไม่มีค่า (เช่น1ในตัวอย่างของฉัน) คุณต้องระบุnargs=0ในadd_argumentฟังก์ชัน
Erasmus Cedernaes

ฉันแค่คัดลอกและวางรหัสของคุณตามที่ระบุไว้ในคำตอบ บางทีคุณควรแก้ไข? ฉันลงเอยด้วยการใช้action='store_true'คำตอบด้านล่างแทนในรหัสจริงของฉัน
Mike Wise

@MikeWise คุณเรียกใช้สคริปต์เป็นpython argparse_test.py --foo 1?
Erasmus Cedernaes

11

คุณสามารถตรวจสอบแฟล็กที่ส่งผ่านซึ่งเป็นตัวเลือกstore_trueและstore_falseตัวเลือกการดำเนินการโต้แย้ง

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)

is not Noneวิธีนี้คุณจะได้ไม่ต้องกังวลเกี่ยวกับการตรวจสอบโดยมีเงื่อนไข คุณเพียงแค่ตรวจสอบหรือTrue Falseอ่านเพิ่มเติมเกี่ยวกับตัวเลือกเหล่านี้ในเอกสารที่นี่


1
สิ่งนี้ไม่สามารถแก้ปัญหาได้เพื่อให้ทราบว่าอาร์กิวเมนต์ที่มีค่าถูกตั้งค่าหรือไม่ ปัญหาหลักที่นี่คือการทราบว่าค่า args มาจาก defaul = "" หรือเป็นค่าที่กำหนดโดยผู้ใช้
m3nda

5

หากอาร์กิวเมนต์ของคุณเป็นตำแหน่ง (กล่าวคือไม่มีคำนำหน้า "-" หรือ "-" เพียงแค่อาร์กิวเมนต์โดยทั่วไปคือชื่อไฟล์) คุณสามารถใช้พารามิเตอร์ nargsเพื่อทำสิ่งนี้:

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')

3

นี่คือวิธีแก้ปัญหาของฉันเพื่อดูว่าฉันใช้ตัวแปร 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

สิ่งนี้อาจให้ข้อมูลเชิงลึกมากขึ้นสำหรับคำตอบข้างต้นซึ่งฉันใช้และปรับให้เข้ากับโปรแกรมของฉัน


0

เพื่อที่จะแสดงความคิดเห็นของ @ kcpr เกี่ยวกับคำตอบ (ที่ยอมรับในปัจจุบัน) โดย @Honza Osobne

น่าเสียดายที่มันใช้ไม่ได้เนื่องจากอาร์กิวเมนต์ได้รับค่าเริ่มต้นที่กำหนดไว้

ก่อนอื่นสามารถตรวจสอบได้ว่ามีการจัดเตรียมอาร์กิวเมนต์หรือไม่โดยการเปรียบเทียบกับNamespaceอ็อบเจ็กต์ abd โดยให้default=argparse.SUPPRESSตัวเลือก (ดูคำตอบของ @ hpaulj และ @Erasmus Cedernaes และเอกสาร python3นี้) และหากไม่ได้ระบุไว้ให้ตั้งเป็นค่าเริ่มต้น

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))

การใช้งาน

$ 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

0

ง่ายมากหลังจากกำหนดตัวแปร args โดย 'args = parser.parse_args ()' มันมีข้อมูลทั้งหมดของตัวแปรย่อยของ args ด้วย หากต้องการตรวจสอบว่ามีการตั้งค่าตัวแปรหรือไม่โดยสมมติว่าใช้ 'action = "store_true" ...

if args.argument_name:
   # do something
else:
   # do something else
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.