Python中Perl(<>)的等价物是什么? fileinput无法按预期工作

时间:2010-12-29 14:11:59

标签: python perl file-io file command-line-arguments

在Perl中使用:

while (<>) {
    # process files given as command line arguments
}

在Python中我找到了:

import fileinput
for line in fileinput.input():
    process(line)

但是,当命令行中给出的文件不存在时会发生什么?

python test.py test1.txt test2.txt filenotexist1.txt filenotexist2.txt test3.txt被作为参数。

我尝试了各种使用try: except: nextfile的方式,但我似乎无法使其正常工作。

对于上面的命令行,脚本应该为test1-3.txt运行,但是当找不到文件时,只需转到下一个文件。

Perl做得非常好。我已经在网上搜索了这个,但我无法在任何地方找到答案。

7 个答案:

答案 0 :(得分:5)

import sys
import os

for f in sys.argv[1:]:
    if os.path.exists(f):
        for line in open(f).readlines():
            process(line)

答案 1 :(得分:3)

像这样;

import sys

for f in sys.argv[1:]:
    try:
        data = open(f).readlines()
        process(data)
    except IOError:
        continue

答案 2 :(得分:3)

将@Brian的答案转换为生成器,并捕捉IOError而不是测试更多Pythonic的存在,然后在失败时向stderr发出警告:

import sys

def read_files(files = None):
  if not files:
    files = sys.argv[1:]
  for file in files:
    try:
      for line in open(file):
        yield line
    except IOError, e:
      print >>sys.stderr, 'Warning:', e

for line in read_files():
  print line,

输出(文件baz不存在):

$ python read_lines.py foo bar baz
line 1 of foo
line 2 of foo
line 1 of bar
line 2 of bar
Warning: [Errno 2] No such file or directory: 'baz'

您可能需要花一些精力来整理错误消息,但这可能不值得付出努力。

答案 3 :(得分:2)

您可以使用fileinput模块解决问题,如下所示:

import fileinput

input = fileinput.input()
while True:
    try:
        process(input.next())
    except IOError:
        input.nextfile()
    except StopIteration:
        break

不幸的是,您无法使用for循环,因为IOException会破坏它。

答案 4 :(得分:0)

也许您可以使用openhook参数来控制不存在的文件。

答案 5 :(得分:0)

我试图实施@VGE的建议,但我的尝试结果并不太优雅。我很感激有关如何改进这一点的任何建议。

import sys, fileinput, errno, os

class nosuchfile:
    def readlines(foo, bar):
        return []
    def close(arg):
        pass

EXITCODE=0

def skip_on_error (filename, mode):
    """Function to pass in as fileinput.input(openhook=...) hook function.
    Instead of give up on the first error, skip the rest of the file and
    continue with the next file in the input list.

    In case of an error from open() an error message is printed to standard
    error and the global variable EXITCODE gets overwritten by a nonzero
    value.
    """
    global EXITCODE
    try:
        return open(filename, mode)
    except IOError, e:
        sys.stderr.write ("%s: %s: %s\n" % (sys.argv[0], filename, os.strerror(e.errno)))
        EXITCODE = 1
        return nosuchfile()

def main ():
    do_stuff(fileinput.input(openhook=skip_on_error))
    return EXITCODE

占位符虚拟文件句柄类nosuchfile和全局变量EXITCODE都是非常严重的瑕疵。我试图找出如何传入对本地范围的exitcode变量的引用,但放弃了。

这也无法处理读取时发生的错误,但大多数错误情况似乎都发生在open中。

答案 6 :(得分:0)

简单,明确和沉默:

import fileinput
from os.path import exists
import sys

for line in fileinput.input(files=filter(exists, sys.argv[1:])):
    process(line)