try:
content = open("/tmp/out").read()
except:
content = ""
我可以比这更短或更优雅吗?我必须为多个文件做这件事,所以我想要更短的东西。
编写函数是唯一更短的方法吗?
我真正想要的是这个,但""
如果有任何异常我想连接
lines = (open("/var/log/log.1").read() + open("/var/log/log").read()).split("\n")
try:
content = open("/tmp/out").read()
except:
content = ""
我可以比这更短或更优雅吗?我必须为多个文件做这件事,所以我想要更短的东西。
编写函数是唯一更短的方法吗?
我真正想要的是这个,但""
如果有任何异常我想连接
lines = (open("/var/log/log.1").read() + open("/var/log/log").read()).split("\n")
是的,你必须写一些类似的东西
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)
您可以尝试以下方法,但这可能不是最好的:
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 来包装它。
此代码将为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 - 除非有人知道更好的机制。
我知道有些人认为猴子修补是无赖的行为。
您可以定义一个函数来捕获错误:
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))