sys.stdin作为要迭代的文件

时间:2019-05-30 06:20:40

标签: python

我正在编写一个脚本,该脚本在文件(输入是文件路径)或在stdin中搜索正则表达式,以防输入“-”而不是文件路径。

我进行了一些调试,我认为问题出在“对于我来说,enumerate(file)中的行:”因为它不在其中。

当我在Python 3.x中执行此操作时,它可以工作,但是在python 2.7中,它不会进入该循环

这是脚本的一部分

def init_parser():
    parser = argparse.ArgumentParser(description="The script searches one or \
                                     more named input files for lines \
                                     containing a match to a regular \
                                     expression pattern.")
    parser.add_argument('regex', help='the regular expression.')
    parser.add_argument('infile', nargs='*', type=argparse.FileType('r'), default='-',
                        help='the name of the file(s) to search.')

    return parser


args = init_parser().parse_args()
for file in args.infile:
    if args.infile == '-':
        file = sys.stdin
    for i, line in enumerate(file):
        substrings = re.finditer(args.regex, line)
        if substrings:
            for substring in substrings:
                    print_line(file.name, i + 1, line[:-1])

1 个答案:

答案 0 :(得分:0)

Python 2使用与Python 3不同的缓冲方案来遍历文件。它希望在开始第一次迭代之前填充缓冲区或查看文件的末尾。您正在手动在stdin中输入输入,但输入的内容不足以填充缓冲区或没有信号通知文件结束,因此您永远无法到达第一次迭代。

要在没有此缓冲的情况下遍历文件,可以使用两个参数iter。这适用于Python 2和Python 3:

for line in iter(file.readline, ''):
    ...

此外,您(至少)还有两个错误。首先,以下两行没有按您认为的做:

if args.infile == '-':
    file = sys.stdin

args.infile是文件对象序列,而不是字符串。您没有注意到该错误,因为argparse.FileType实际上正在为您处理-

还有第二个错误,第一个错误恰好是隐藏的。 infile的默认值:

parser.add_argument('infile', nargs='*', type=argparse.FileType('r'), default='-',
                    help='the name of the file(s) to search.')

应为[sys.stdin],而不是'-'。默认值不会经过type处理,也不会自动包装在列表中,因此您必须自己进行操作。否则,此循环:

for file in args.infile:

最终遍历'-'的字符,而不是遍历文件。

要解决这些错误,请将infile的默认设置更改为[sys.stdin],然后删除if args.infile == '-':处理。