2
try:
    content = open("/tmp/out").read()
except:
    content = ""

我可以比这更短或更优雅吗?我必须为多个文件做这件事,所以我想要更短的东西。

编写函数是唯一更短的方法吗?

我真正想要的是这个,但""如果有任何异常我想连接

lines = (open("/var/log/log.1").read() + open("/var/log/log").read()).split("\n")
4

4 回答 4

3

是的,你必须写一些类似的东西

def get_contents(filename):
    try:
        with open(filename) as f:
            return f.read()
    except EnvironmentError:
        return ''


lines = (get_contents('/var/log/log.1')
         + get_contents('/var/log/log')).split('\n')

NlightNFotis提出了一个有效的观点,如果文件很大,你不想这样做。也许您会编写一个接受文件名列表的行生成器:

def get_lines(filenames):
    for fname in filenames:
        try:
           with open(fname) as f:
               for line in f:
                   yield line
        except EnvironmentError:
            continue


...

for line in get_lines(["/var/log/log.1", "/var/log/log"]):
    do_stuff(line)

另一种方法是使用标准fileinput.FileInput类(感谢 JF Sebastian):

import fileinput

def eat_errors(f, mode):
    try:
        return open(f, mode)
    except IOError:
        return open(os.devnull)

for line in fileinput.FileInput(["/var/log/log.1", "/var/log/log"], openhook=eat_errors):
    do_stuff(line)
于 2013-02-03T11:58:04.267 回答
0

您可以尝试以下方法,但这可能不是最好的:

import os

def chk_file(filename):
    if os.stat(filename).st_size == 0:
        return ""
    else:
        with open(filename) as f:
            return f.readlines()


if __name__=="__main__":
    print chk_file("foobar.txt") #populated file
    print chk_file("bar.txt") #empty file
    print chk_file("spock.txt") #populated

有用。如果你愿意,你可以用你的 try-except 来包装它。

于 2013-02-03T12:14:43.750 回答
0

此代码将为open另一个打开创建一个 FakeFile 的猴子修补程序,如果抛出一个“IOException ”,该文件总是返回一个“空”字符串。open

虽然它的代码比您真正想要为手头的问题编写的代码多,但这确实意味着您有一个可重用的上下文管理器,以便open在需要再次出现时进行伪造(可能在未来十年内两次)

with monkey_patched_open():
     ...

实际代码。

#!/usr/bin/env python
from contextlib import contextmanager
from StringIO import StringIO
################################################################################
class FakeFile(StringIO):
    def __init__(self):
        StringIO.__init__(self)
        self.count = 0

    def read(self, n=-1):
        return "<empty#1>"

    def readlines(self, sizehint = 0):
        return ["<empty#2>"]

    def next(self):
        if self.count == 0:
            self.count += 1
            return "<empty#3>"
        else:
            raise StopIteration
################################################################################
@contextmanager
def monkey_patched_open():
    global open
    old_open = open

    def new_fake_open(filename, mode="r"):
        try:
            fh = old_open(filename, mode)
        except IOError:
            fh = FakeFile()
        return fh

    open = new_fake_open

    try:
        yield
    finally:
        open = old_open

################################################################################
with monkey_patched_open():
    for line in open("NOSUCHFILE"):
        print "NOSUCHFILE->", line
    print "Other", open("MISSING").read()
    print "OK", open(__file__).read()[:30]

运行上述给出:

NOSUCHFILE-> <empty#3>
Other <empty#1>
OK #!/usr/bin/env python
from co

我留下“空”字符串只是为了显示发生了什么。

StringIO只需阅读一次就足够了,但我认为 OP 正在寻求继续从文件中读取,因此需要 FakeFile - 除非有人知道更好的机制。

我知道有些人认为猴子修补是无赖的行为。

于 2013-02-03T22:54:12.593 回答
-1

您可以定义一个函数来捕获错误:

from itertools import chain

def readlines(filename):
    try:
        with open(filename) as file:
            return file.readlines() # or just `file` to return an iterator 
    except EnvironmentError:
        return []

files = (readlines(name) for name in ["/var/log/1", "/var/log/2"])
lines = list(chain.from_iterable(files))
于 2013-02-03T12:03:08.820 回答