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セバスティアン):

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

このコードは、「IOException」がスローされた場合に常に「空」の文字列を返す FakeFile を作成するopen別のオープンに対してモンキー パッチを適用します。open

目の前の問題に対して実際に書きたいと思うよりも多くのコードですがopen、必要が再び発生した場合に偽造するための再利用可能なコンテキストマネージャーがあることを意味します(おそらく今後 10 年間で 2 回)。

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 に答える
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 に答える
-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 に答える