运行 带有不需要指定输出文件名的可选参数的 argparse

Running argparse with optional arguments that won't require specifying output filename

我已经通读了一堆已经回答的问题,但我没有看到这一点——至少我没有意识到这一点。

我正在使用 argparse 获取文件并将其转换为不同的类型。输入文件名是必需的。输出文件名不是必需的,因为可选参数应该处理它。这是到目前为止的代码:

import sys
import argparse
parser = argparse.ArgumentParser(description='Convert file to new type')
parser.add_argument('--json', type=str, help='Converts to json format')
parser.add_argument('--bibtex', type=str, help='Converts to bibtex format')
parser.add_argument('--html', type=str, help='Converts to html format')
parser.add_argument('inputfilename', type=str, help='enter the original filename')
args = parser.parse_args()
filename=args.filename
if args.json:
    print('Converting to json ...')
    #conversion code here
elif args.bibtex:
    print('Converting to bibtex ...')
    #conversion code here
elif args.html:
    print('Converting to html ...')
    #conversion code here
else:
    print('No conversion type indicated')

问题是每当我使用其中一个标志时。如果我这样做

$ ./orsconvert.py --json inputfilename

我收到一条错误消息

orsconvert.py: error: the following arguments are required: inputfilename

它这样做是因为它将提供的 inputfilename 解释为连接到 --json 的输出文件名。它试图强迫我在可选参数之后和输入文件名之前实际声明输出文件名,类似于:

$ ./orsconvert.py --json outputfilename inputfileneame

但是,如果有解决办法,我不想这样做。我希望它接受 --json 作为指示,然后使用 inputfilename 作为输入,并根据代码指定的内容自动将其保存为 outputfilename

是的,我正在考虑将 3 个可选参数组成一个组以简化代码......但这仍然没有解释如何让它在可选参数之后和最终 [ 之前不需要另一个参数=15=] 需要参数。

我是否可以在 parser.add_argument('...') 字段中输入其他内容以不再要求我指定 outputfilename?我想尽可能少地更改代码,因为我已经突破了我的编码理解的极限。

问题是您将 --json 定义为需要一个参数,并且它将输入文件名作为该参数。您的三个转换器应使用 store_true 操作,而不是默认的 store 操作。

parser = argparse.ArgumentParser(description='Convert file to new type')
parser.add_argument('--json', action='store_true', help='Converts to json format')
parser.add_argument('--bibtex', action='store_true', help='Converts to bibtex format')
parser.add_argument('--html', action='store_true', help='Converts to html format')
parser.add_argument('inputfilename', help='enter the original filename')
args = parser.parse_args()

通过此更改,args.json 等都是您期望的布尔值。 store_true 操作负责将类型定义为 bool 并将默认值定义为 false.


不过,更好的是,一个必需的位置参数必须采用值 jsonbibtexhtml。然后 parse_args 本身会检测是否给出了不正确或缺失的转换类型。

parser = argparse.ArgumentParser(description='Convert file to new type')
parser.add_argument('inputfilename', help='enter the original filename')
parser.add_argument('conversion_type', choices=['json', 'bibtex', 'html'])
args = parser.parse_args()
filename = args.filename
conversion_type = args.conversion_type  # Guaranteed to be json, html, or bibtex
if conversion_type == "json":
    ...
elif conversion_type == "bibtex":
    ...
elif conversion_type == "html":

如果您想要具有 默认值 值的选项,系好安全带:) 我们将添加 4 选项:一个可以明确指定输出类型,以及设置它的三个快捷方式。

p = argparse.ArgumentParser()
p.add_argument('inputfilename')
p.add_argument('--type', choices=['json', 'bibtex', 'html'], default='json')
p.add_argument('--json', action='store_const', const='json', dest='type')
p.add_argument('--html', action='store_const', const='html', dest='type')
p.add_argument('--bibtex', action='store_const', const='bibtex', dest='type')

--json--bibtex--html分别与--type json--type bibtex--type html效果相同。和以前一样,--type 只能将这三个值作为其参数。如果有多个,以最后一个为准。

所以问题似乎是每个 argparse.arg 都需要指定一个参数,无论是什么。所以你可以将它设置为布尔值。但我认为也许这种方法会更好:

import sys
import argparse
parser = argparse.ArgumentParser(description='Convert file to new type')
parser.add_argument('--type', type=str, help='Converts to any of the following formats: 1 for json, 2 for bibtex and 3 for html')
parser.add_argument('--inputfilename', type=str, help='enter the original filename')
args = parser.parse_args()
filename=args.inputfilename
if args.type:
    conversion_type = int(args.type)
    if conversion_type == int(1):
        print('Converting to json ...')
        #conversion code here
    elif conversion_type == 2:
        print('Converting to bibtex ...')
        #conversion code here
    elif conversion_type == 3:
        print('Converting to html ...')
        #conversion code here
else:
    print('No conversion type indicated')

只需添加一个参数来指定类型。在此基础上,根据条件转换或不转换。

您的问题是 argparse 需要输入,尤其是因为您有 type=str

尝试用这个替换 json arg

parser.add_argument('--json', action="store_true", help='Converts to json format')

argparse 已经随附了您实际需要的所有东西,让您真正拥有 API 想要的东西,而不是您认为需要的东西。

  • 类型应该是几个 choices 之一,而不是三个单独的标志。
  • inputfilename 应该是必需的。
  • outputfilename 应该是可选的。
import argparse
parser = argparse.ArgumentParser(description='Convert file to new type')
parser.add_argument('format', choices=["json", "bibtex", "html"])
parser.add_argument('inputfilename', type=str)
parser.add_argument('outputfilename', type=str, nargs="?")
args = parser.parse_args()
print(args)

这会自动提供所需的用法,不会滥用可选值,而是获得错误处理。

$ ./converter json in.txt
Namespace(format='json', inputfilename='in.txt', outputfilename=None)
$ ./converter html in.txt out.html
Namespace(format='html', inputfilename='in.txt', outputfilename='out.html')
$ ./converter yaml in.txt         
usage: converter [-h] {json,bibtex,html} inputfilename [outputfilename]
converter: error: argument format: invalid choice: 'yaml' (choose from 'json', 'bibtex', 'html')