Что эквивалентно Perl (<>) в Python? fileinput не работает должным образом - PullRequest
7 голосов
/ 29 декабря 2010

В 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 ]

5 голосов
/ 29 декабря 2010
import sys
import os

for f in sys.argv[1:]:
    if os.path.exists(f):
        for line in open(f).readlines():
            process(line)
3 голосов
/ 29 декабря 2010

Превращение ответа @ Брайана в генератор и перехват 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 голосов
/ 29 декабря 2010

Как то так;

import sys

for f in sys.argv[1:]:
    try:
        data = open(f).readlines()
        process(data)
    except IOError:
        continue
2 голосов
/ 29 декабря 2010

Вы можете решить вашу проблему с модулем fileinput следующим образом:

import fileinput

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

К сожалению, вы не можете использовать цикл for, потому что IOException нарушает его.

1 голос
/ 06 ноября 2018

Простой, явный и тихий:

import fileinput
from os.path import exists
import sys

for line in fileinput.input(files=filter(exists, sys.argv[1:])):
    process(line)
1 голос
/ 21 августа 2012

Я пытался реализовать предложение @ 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.

0 голосов
/ 29 декабря 2010

Может быть, вы можете поиграть с параметром openhook для управления несуществующим файлом.

...