Kiểm tra xem đối số tùy chọn của argparse đã được đặt hay chưa


112

Tôi muốn kiểm tra xem một đối số argparse tùy chọn đã được người dùng đặt hay chưa.

Tôi có thể kiểm tra an toàn bằng cách sử dụng Isset không?

Một cái gì đó như thế này:

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

Điều này có hoạt động tương tự đối với các đối số kiểu float / int / string không?

Tôi có thể đặt một tham số mặc định và kiểm tra nó (ví dụ: đặt myArg = -1, hoặc "" cho một chuỗi hoặc "NOT_SET"). Tuy nhiên, giá trị cuối cùng tôi muốn sử dụng chỉ được tính sau trong kịch bản. Vì vậy, tôi sẽ đặt nó thành -1 làm mặc định, và sau đó cập nhật nó thành thứ khác sau. Điều này có vẻ hơi vụng về so với việc đơn giản kiểm tra xem giá trị có được đặt bởi người dùng hay không.


1
Điều gì sẽ isset()là (gợi ý: Python không phải là PHP)? Có hasattr()lẽ ý bạn là thay vào đó? Tại sao không cấu hình argparse để đặt mặc định cho một tùy chọn thay thế?
Martijn Pieters

@MartijnPieters - vâng, đúng. Vì vậy, tôi có thể chỉ cần kiểm tra xem (args.myArg): ...
Madeleine P. Vincent

Câu trả lời:


146

Tôi nghĩ rằng các đối số tùy chọn (được chỉ định bằng --) được khởi tạo Nonenếu chúng không được cung cấp. Vì vậy, bạn có thể kiểm tra với is not None. Hãy thử ví dụ dưới đây:

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

Các bài kiểm tra "là Không" và "không phải Không" hoạt động chính xác như tôi muốn và mong đợi. Cảm ơn.
Madeleine P. Vincent

39
Thật không may, nó không hoạt động sau đó đối số đã defaultxác định giá trị của nó .
kcpr

6
Nếu bạn muốn đặt a default, thì bạn vẫn có thể đặt nargs='?'và cung cấp một constgiá trị, như được mô tả trong tài liệu . Khi đối số vắng mặt, defaultđược sử dụng, khi đối số có giá trị w / o thì constđược sử dụng, nếu không thì giá trị đã cho được sử dụng. Chỉ với defaultnargs='?', defaultđược sử dụng nếu không cho trước, Nonenếu cho giá trị w / o, nếu không thì giá trị đã cho.
Ioannis Filippidis

@IoannisFilippidis nếu bạn sử dụng action= "store_true"hoặc action="store_const", const="yourconst"bạn không thể sử dụng đối số đó để lưu trữ giá trị khác. Điều này sẽ không hoạt động khi sử dụng mặc định. Trong riêng của tôi, tôi đã gỡ bỏ tất cả các giá trị mặc định từ argparser và xử lý tất cả các bên trong chức năng khác def defaults():mà tôi trộn ConfigParser, ArgumentParser và các giá trị mặc định theo thứ tự tôi muốn
m3nda

@ erm3nda Tôi không đề cập đến việc thiết lập một action. Câu trả lời không sử dụng dấu action. Các hành động mà bạn đề cập được ghi lại để hành xử theo một cách cụ thể (như bạn đã quan sát). Tuy nhiên, không cần thiết phải xác định một hành động.
Ioannis Filippidis

37

Như @Honza ghi chú is Nonelà một thử nghiệm tốt. Đó là mặc định defaultvà người dùng không thể cung cấp cho bạn một chuỗi sao chép nó.

Bạn có thể chỉ định một cái khác default='mydefaultvaluevà kiểm tra cái đó. Nhưng nếu người dùng chỉ định chuỗi đó thì sao? Điều đó có được coi là thiết lập hay không?

Bạn cũng có thể chỉ định default=argparse.SUPPRESS. Sau đó, nếu người dùng không sử dụng đối số, nó sẽ không xuất hiện trong argskhông gian tên. Nhưng thử nghiệm có thể phức tạp hơn:

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

Nội bộ parserlưu giữ một danh sách seen_actionsvà sử dụng nó để kiểm tra 'bắt buộc' và 'lẫn nhau'. Nhưng nó không có sẵn cho bạn bên ngoài parse_args.


22

Tôi nghĩ rằng việc sử dụng tùy chọn default=argparse.SUPPRESScó ý nghĩa nhất. Sau đó, thay vì kiểm tra xem đối số có phải là không not None, người ta kiểm tra xem đối số có phải là inkhông gian tên kết quả hay không.

Thí dụ:

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

Sử dụng:

$ python argparse_test.py --foo 1
Parsed arguments: Namespace(foo='1')
foo in namespace?: True
Đối số không được cung cấp:
$ python argparse_test.py
Parsed arguments: Namespace()
foo in namespace?: False

Điều này không hoạt động đối với tôi trong Python 3.7.5 (Anaconda). Tôi nhận được kết quảtestfoo.py: error: argument --foo: expected one argument
Mike Wise

@MikeWise Nếu bạn muốn sử dụng --foomà không có giá trị (tức là 1trong ví dụ của tôi), bạn phải chỉ định nargs=0trong add_argumenthàm.
Erasmus Cedernaes

Tôi chỉ sao chép và dán mã của bạn như được chỉ định trong câu trả lời. Có lẽ bạn nên chỉnh sửa nó? Tôi đã kết thúc bằng cách sử dụng action='store_true'câu trả lời bên dưới thay vì mã thực của tôi.
Mike Wise

@MikeWise, bạn đã chạy tập lệnh như python argparse_test.py --foo 1thế nào?
Erasmus Cedernaes

11

Bạn có thể kiểm tra một cờ được truyền tùy chọn với store_truestore_falsecác tùy chọn hành động đối số:

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)

Bằng cách này, bạn không phải lo lắng về việc kiểm tra theo điều kiện is not None. Bạn chỉ cần kiểm tra Truehoặc False. Đọc thêm về các tùy chọn này trong tài liệu tại đây


1
điều này không giải quyết được nếu một đối số có một giá trị được đặt hay không. vấn đề chính ở đây là biết giá trị args đến từ defaul = "" hay do người dùng cung cấp.
m3nda

5

Nếu đối số của bạn là vị trí (nghĩa là nó không có tiền tố "-" hoặc "-", chỉ là đối số, thường là tên tệp) thì bạn có thể sử dụng tham số tường thuật để thực hiện việc này:

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

Đây là giải pháp của tôi để xem liệu tôi có đang sử dụng biến argparse hay không

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

Điều này có thể cung cấp thêm thông tin chi tiết cho câu trả lời ở trên mà tôi đã sử dụng và điều chỉnh để làm việc cho chương trình của mình.


0

Để giải quyết nhận xét của @ kcpr về câu trả lời (hiện đang được chấp nhận) của @Honza Osobne

Thật không may, nó không hoạt động sau đó đối số đã xác định giá trị mặc định của nó.

trước tiên người ta có thể kiểm tra xem đối số có được cung cấp hay không bằng cách so sánh nó với Namespaceđối tượng Abd cung cấp default=argparse.SUPPRESStùy chọn (xem câu trả lời của @ hpaulj và @Erasmus Cedernaes và tài liệu python3 này ) và nếu nó chưa được cung cấp, thì hãy đặt nó thành giá trị mặc định.

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

Sử dụng

$ 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

Rất đơn giản, sau khi xác định biến args bằng 'args = parser.parse_args ()', nó cũng chứa tất cả dữ liệu của các biến tập hợp con args. Để kiểm tra xem biến có được đặt hay không, giả sử sử dụng 'action = "store_true" ...

if args.argument_name:
   # do something
else:
   # do something else
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.