我有几个可能的文件可以保存我的数据;它们可以以不同的方式压缩,所以要打开它们,我需要使用file()、gzip.GzipFile()和其他也返回文件对象(支持with接口)的文件。
我想尝试每一个,直到其中一个成功打开,这样我就可以这样做了
try:
with gzip.GzipFile(fn + '.gz') as f:
result = process(f)
except (IOError, MaybeSomeGzipExceptions):
try:
with xCompressLib.xCompressFile(fn + '.x') as f:
result = process(f)
except (IOError, MaybeSomeXCompressExceptions):
try:
with file(fn) as f:
result = process(f)
except IOError:
result = "some default value"如果我有几十种可能的压缩变体,这显然是不可行的。(嵌套会越来越深,代码看起来总是非常相似。)
有没有更好的方式来表达这一点?
编辑:如果可能的话,我希望在process(f)中意外地捕捉到异常时,将process(f)从try/except中剔除。
发布于 2012-09-24 21:38:36
我会编写一个自定义的上下文管理器:
from contextlib import contextmanager
filetypes = [('.gz', gzip.GzipFile, (IOError, MaybeSomeGzipExceptions)),
('.x', xCompressLib.xCompressFile, (IOError, MaybeSomeXCompressExceptions))]
@contextmanager
def open_compressed(fn):
f = None
try:
for ext, cls, exs in filetypes:
try:
f = cls(fn + ext)
except exs:
pass
else:
break
yield f
finally:
if f is not None:
f.close()
with open_compressed(fn) as f:
result = "some default value" if f is None else process(f)或者可能只是一个返回上下文管理器的函数:
filetypes = [('.gz', gzip.GzipFile, (IOError, MaybeSomeGzipExceptions)),
('.x', xCompressLib.xCompressFile, (IOError, MaybeSomeXCompressExceptions))]
class UnknownCompressionFormat(Exception):
pass
def open_compressed(fn):
for ext, cls, exs in filetypes:
try:
return cls(fn + ext)
except exs:
pass
raise UnknownCompressionFormat
try:
with open_compressed(fn) as f:
result = process(f)
except UnknownCompressionFormat:
result = "some default value"发布于 2012-09-24 20:43:31
是的,你可以把你的所有变体放在一个列表中,然后尝试它们,直到其中一个可以工作,这样就取消了你的代码的嵌套:
def process_gzip(fn):
with gzip.GzipFile(fn + '.gz') as f:
return process(f)
def process_xlib(fn):
with xCompressLib.xCompressFile(fn + '.x') as f:
return process(f)
def process_builtin(fn):
with file(fn) as f:
return process(f)
process_funcs = [process_gzip, process_xlib, process_builtin]
#processing code:
for process_f in process_funcs:
try:
result = process_f(fn)
break
except IOError:
#error reading the file, keep going
continue
except:
#processing error, re-raise the exception
raise或者,为了减少代码量,您可以创建一个process_func工厂,因为它们都具有相同的形式:
def make_process_func(constructor, filename_transform):
with constructor(filename_transform) as f:
return process(f)
process_funcs = [
make_process_func(gzip.GzipFile, lambda fn: fn + '.gz'),
make_process_func(xCompressLib.xCompressFile, lambda fn: fn + '.x'),
make_process_func(file, lambda fn: fn),
]发布于 2012-09-24 20:48:04
这样行得通吗:
extensions = [('.gz', gzip.GzipFile, (IOError, MaybeSomeGzipExceptions)),
('.x', xCompressLib.xCompressFile, (IOError, MaybeSomeXCompressExceptions))] # and other such entries
processed = False
for ext, (compressor, errors) in extensions.iteritems():
try:
with compressor(fn+ext) as f:
try:
result = process(f)
processed = True
break
except:
raise
except errors:
pass
if not processed:
result = "some default value"希望这能有所帮助
https://stackoverflow.com/questions/12565216
复制相似问题