首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >有几个` `try`s‘s in `’s

有几个` `try`s‘s in `’s
EN

Stack Overflow用户
提问于 2012-09-24 20:39:54
回答 3查看 301关注 0票数 17

我有几个可能的文件可以保存我的数据;它们可以以不同的方式压缩,所以要打开它们,我需要使用file()gzip.GzipFile()和其他也返回文件对象(支持with接口)的文件。

我想尝试每一个,直到其中一个成功打开,这样我就可以这样做了

代码语言:javascript
复制
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中剔除。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-09-24 21:38:36

我会编写一个自定义的上下文管理器:

代码语言:javascript
复制
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)

或者可能只是一个返回上下文管理器的函数:

代码语言:javascript
复制
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"
票数 7
EN

Stack Overflow用户

发布于 2012-09-24 20:43:31

是的,你可以把你的所有变体放在一个列表中,然后尝试它们,直到其中一个可以工作,这样就取消了你的代码的嵌套:

代码语言:javascript
复制
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工厂,因为它们都具有相同的形式:

代码语言:javascript
复制
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),
]
票数 9
EN

Stack Overflow用户

发布于 2012-09-24 20:48:04

这样行得通吗:

代码语言:javascript
复制
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"

希望这能有所帮助

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/12565216

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档