Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/352.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/cmake/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 文件作为argparse的命令行参数-参数无效时显示错误消息_Python_Argparse - Fatal编程技术网

Python 文件作为argparse的命令行参数-参数无效时显示错误消息

Python 文件作为argparse的命令行参数-参数无效时显示错误消息,python,argparse,Python,Argparse,我目前使用的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"

我目前使用的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=open
type=argparse.FileType('r')
,它们都有效,但如果文件无效,我希望得到一条错误消息。我该怎么做呢?

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


我刚刚找到了这个:

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)

来源:

在Python3.4中实现这一点的方法是使用类。确保完成后关闭输入流。这也很有用,因为可以对STDIN/STDOUT使用伪参数
'-'
。从文件中:

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

例如:

#!/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'>)
    

@moose——另一条评论
os.path.isfile
可能比
os.path.exists
(取决于您是否也要接受目录)更合适。事实上,与检查existence@jarondl这是对的。这应该更改为使用
try:。。。IOError除外
,以避免潜在的竞争条件。在大多数情况下,这并不重要,但最近这让我感到痛苦。提高
argparse.ArgumentTypeError
会使代码更简洁。(正如moose的回答中所指出的那样)你不必
尝试打开文件,因为
打开
将自行处理所有错误情况。然后,您可能会在
except
子句中发现这一点,但我认为这种情况下不需要它。
argparse.FileType
在Python 2.7中也可用。如果对不同的输入参数有多个
argparse.FileType
用法,并且它们都使用
-
?@cmcdragokai,从文档中可以看到:如果sys.stdin被多次使用,第二次和以后的使用将不会返回任何行,除了交互使用,或者如果它已被显式重置(例如使用sys.stdin.seek(0))
$ ./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'>)