如何使用argparse打开文件?

91

我想使用 argparse 打开一个文件进行读取。在命令行中应该是这样的: my_program.py /filepath

这是我的尝试:

parser = argparse.ArgumentParser()
parser.add_argument('file', type = file)
args = parser.parse_args()
这给了我 [编辑:后来从评论中添加]:
parser.add_argument('file', type = file) NameError: name 'file' is not defined

5
它具体做了什么? - Ry-
你目前遇到了什么问题? - justhalf
运行时出现错误: parser.add_argument('file', type = file) NameError: name 'file' is not defined我不太理解argparse的工作原理... - nuT707
1
如果fnc是一个接受字符串并返回所需对象或引发错误的函数,则type = fnc有效。Python中没有file函数,因此type=open有效,因为有一个Python函数open(filename)。argparse提供了一个更好的函数argparse.FileType()(实际上是一个函数构造器)。但是像wim的答案中那样使用简单的字符串参数是更好的起点。 - hpaulj
4
type=file 在 Python2.7 (以及更早版本)中可用。但在 Python3 中,file 已被删除。https://dev59.com/4XVD5IYBdhLWcg3wBm1h - hpaulj
6个回答

229

65
虽然我认为在这里提供两个答案是很好的,但应该也要提到argparse.FileType的注意事项。例如,它会留下一个未关闭的文件句柄,这在我看来是实现不够严谨。通常情况下,我宁愿自己处理open()文件,以便可以正确地执行(使用上下文管理器),并且还可以自定义“文件未找到”错误的行为和输出。 - wim
44
Python开发人员在Python错误追踪器上发布了一个问题,称"FileType仅适用于可以放心地保持文件打开或关闭stdin和/或stdout的快速脚本之外的其他内容不适合使用。"具体内容请参考这个链接:http://bugs.python.org/issue13824。 - wim
20
你可以使用 with args.file as f: ... 的语法,在良好的情况下更早地关闭文件。 - Wernight
2
@Wernight:但这会关闭 stdoutstdin,对吧? - MestreLion
12
@Wernight说:“但是如果缺少参数或者参数为-argparse会自动将文件设置为<stdin>(或<stdout>,具体取决于mode),这是非常棒的功能,但是如果使用with args.file as f: ...,它会(或尝试)在不该关闭它们的情况下关闭文件。” - MestreLion
显示剩余9条评论

99

参数的类型应为字符串(默认情况下就是这样)。因此,请像这样设置:

parser = argparse.ArgumentParser()
parser.add_argument('filename')
args = parser.parse_args()
with open(args.filename) as file:
  # do stuff here

14
请查看Wim在ilent2答案下的评论,了解为什么这个答案在大多数情况下可能是最好的答案。 - L0j1k
3
不应使用变量名file,因为它是一个内置函数。 - jnrbsn
9
一般来说,这是正确的,但是file在现在的Python中从未被使用过——它在Python3中被删除了,在Python2中docstring甚至建议使用open代替。因此,重命名该名称是可以的,在核心库中甚至做了好几次。 - wim

40
为了使文件能够优雅地关闭,您可以将 argparse.FileTypewith 语句结合使用。
parser.add_argument('file', type=argparse.FileType('r'))
args = parser.parse_args()

with args.file as file:
    print(file.read())

with args.file 这一行中,“file” 是指参数的名称,对吗?如果我将参数命名为 -f,那么应该是 with args.-f,对吗?如果我理解有误,请纠正。我是 Argparse 的初学者。 - vishal
2
@vishal.k 是和不是。如果你使用 add_argument('-f', ...,那么你需要在没有破折号的情况下使用 with args.f as file - Ming
4
使用 type=argparse.FileType('r'),文件将在调用 parser.parse_args() 时打开。如果您的代码在上下文管理器之前崩溃,这是否意味着该文件仍然会保持打开状态?这不是一个大问题,但需要记住。 - LondonAppDev

30

我只是添加使用pathlib选项:

import argparse, pathlib

parser = argparse.ArgumentParser()
parser.add_argument('file', type=pathlib.Path)
args = parser.parse_args()

with args.file.open('r') as file:
    print(file.read())

9

简述

parser.add_argument(
    '-f', '--file',
    help='JSON input file',
    type=argparse.FileType('r'),
)

描述

这是一个简单的命令行脚本,用于重新格式化 JSON 文件。

reformat-json \
    -f package.json \
    --indent=2 \
    --sort-keys \
    --output=sorted_package.json

可以用以下Python代码编写

#!/usr/bin/env python3

import argparse, json, sys

EXIT_SUCCESS = 0
EXIT_FAILURE = 1

def main():
    parser = argparse.ArgumentParser()

    parser.add_argument(
        '-f', '--file',
        help='JSON input file',
        type=argparse.FileType('r'),
    )

    parser.add_argument(
        '-i', '--indent',
        help='Non-negative integer indent level',
        type=int
    )

    parser.add_argument(
        '-o', '--output',
        help='Write JSON into output file',
        type=argparse.FileType('w'),
    )

    parser.add_argument(
        '-s', '--sort-keys',
        action='store_true',
        help='Sort output JSON by keys',
    )

    args = parser.parse_args()

    if not args.file:
        parser.print_usage()
        return sys.exit(EXIT_FAILURE)

    gson = json.dumps(
        json.load(args.file),
        indent=args.indent,
        sort_keys=args.sort_keys
    )

    args.file.close()

    if args.output:
        args.output.write(gson)
        args.output.write('\n')
        args.output.close()
    else:
        print(gson)

    return sys.exit(EXIT_SUCCESS)

if __name__ == '__main__':
    main()

2
很好的例子,用法清晰明了,谢谢。 - Manuel

-2

这个实现允许“文件名”参数是可选的,同时在用户输入-h--help参数时提供简短的描述。

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

4
完全没有回答问题。OP询问如何使用argparse打开一个文件进行读取,而不是检查用户是否指定了文件名。 - Rakurai

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接