69

我目前正在使用这样的 argparse:

import argparse
from argparse import ArgumentParser

parser = ArgumentParser(description="ikjMatrix multiplication")
parser.add_argument("-i", dest="filename", required=True,
    help="input file with two matrices", metavar="FILE")
args = parser.parse_args()

A, B = read(args.filename)
C = ikjMatrixProduct(A, B)
printMatrix(C)

现在我想指出,参数-i应该是一个可读文件。我怎样才能做到这一点?

我尝试添加type=opentype=argparse.FileType('r')并且它们有效,但如果文件无效,我想收到一条错误消息。我怎样才能做到这一点?

4

3 回答 3

101

其实很容易。您只需要编写一个函数来检查文件是否有效,否则会写入错误。将该功能与type选项一起使用。请注意,您可以通过子类化来获得更多幻想并创建自定义操作argparse.Action,但我认为这里没有必要。在我的示例中,我返回一个打开的文件句柄(见下文):

#!/usr/bin/env python

from argparse import ArgumentParser
import os.path


def is_valid_file(parser, arg):
    if not os.path.exists(arg):
        parser.error("The file %s does not exist!" % arg)
    else:
        return open(arg, 'r')  # return an open file handle


parser = ArgumentParser(description="ikjMatrix multiplication")
parser.add_argument("-i", dest="filename", required=True,
                    help="input file with two matrices", metavar="FILE",
                    type=lambda x: is_valid_file(parser, x))
args = parser.parse_args()

A, B = read(args.filename)
C = ikjMatrixProduct(A, B)
printMatrix(C)
于 2012-07-18T12:33:00.327 回答
52

在 Python 3.4 中执行此操作的一种方法是使用argparse.FileType该类。完成后确保关闭输入流。这也很有用,因为您可以为 STDIN/STDOUT 使用伪参数'-'。从文档中:

FileType 对象理解伪参数'-'并自动将其转换sys.stdin为可读FileType对象和sys.stdout可写FileType对象

例子:

#!/usr/bin/env python3

import argparse

if __name__ == '__main__':
  parser = argparse.ArgumentParser()
  parser.add_argument('--infile', type=argparse.FileType('r', encoding='UTF-8'), 
                      required=True)
  args = parser.parse_args()
  print(args)
  args.infile.close()

然后跑的时候...

  • 没有论据:

    $ ./stack_overflow.py
    usage: stack_overflow.py [-h] --infile INFILE
    stack_overflow.py: error: the following arguments are required: --infile
    
  • 使用不存在的文件:

    $ ./stack_overflow.py --infile notme
    usage: stack_overflow.py [-h] --infile INFILE
    stack_overflow.py: error: argument --infile: can't open 'notme': [Errno 2] No such file or directory: 'notme'
    
  • 使用现有文件:

    $ ./stack_overflow.py --infile ./stack_overflow.py
    Namespace(infile=<_io.TextIOWrapper name='./stack_overflow.py' mode='r' encoding='UTF-8'>)
    
  • 用于'-'标准输入:

    $ echo 'hello' | ./stack_overflow.py --infile -
    Namespace(infile=<_io.TextIOWrapper name='<stdin>' mode='r' encoding='UTF-8'>)
    
于 2016-03-02T01:29:19.313 回答
19

我刚刚找到了这个:

def extant_file(x):
    """
    'Type' for argparse - checks that file exists but does not open.
    """
    if not os.path.exists(x):
        # Argparse uses the ArgumentTypeError to give a rejection message like:
        # error: argument input: x does not exist
        raise argparse.ArgumentTypeError("{0} does not exist".format(x))
    return x

if __name__ == "__main__":
    import argparse, sys, os
    from argparse import ArgumentParser

    parser = ArgumentParser(description="ikjMatrix multiplication")
    parser.add_argument("-i", "--input",
        dest="filename", required=True, type=extant_file,
        help="input file with two matrices", metavar="FILE")
    args = parser.parse_args()

    A, B = read(args.filename)
    C = ikjMatrixProduct(A, B)
    printMatrix(C, args.output)

来源:fhcrc.github.com

于 2012-07-18T12:34:58.757 回答