鉴于文件类型未知的文件,我想用多个处理程序之一打开该文件。如果无法打开文件,则每个处理程序都会引发异常。 我想尝试所有这些,如果没有成功,就提出异常。
我想出的设计是
filename = 'something.something'
try:
content = open_data_file(filename)
handle_data_content(content)
except IOError:
try:
content = open_sound_file(filename)
handle_sound_content(content)
except IOError:
try:
content = open_image_file(filename)
handle_image_content(content)
except IOError:
...
这个级联似乎不是正确的方法。
有什么建议吗?
答案 0 :(得分:5)
也许您可以对所有处理程序进行分组并在for
循环中对它们进行评估,如果没有成功则在最后引发异常。您还可以继续查看引发的异常,从中获取一些信息,如下所示:
filename = 'something.something'
handlers = [(open_data_file, handle_data_context),
(open_sound_file, handle_sound_content),
(open_image_file, handle_image_content)
]
for o, h in handlers:
try:
o(filename)
h(filename)
break
except IOError as e:
pass
else:
# Raise the exception we got within. Also saves sub-class information.
raise e
答案 1 :(得分:1)
完全无法检查?
>>> import urllib
>>> from mimetypes import MimeTypes
>>> guess = MimeTypes()
>>> path = urllib.pathname2url(target_file)
>>> opener = guess.guess_type(path)
>>> opener
('audio/ogg', None)
我知道try/except
和eafp
在Python中非常流行,但有时愚蠢的一致性只会干扰手头的任务。
此外,IMO的try / except循环可能不一定会因为您期望的原因而中断,并且正如其他人指出的那样,如果您想要查看实际发生的情况,您将需要以有意义的方式报告错误您尝试迭代文件切换器,直到您成功或失败。无论哪种方式,都会编写内省的代码:深入了解try / excepts并获得有意义的代码,或者阅读文件路径并使用类型检查器,甚至只是拆分文件名来获取扩展名...... {{1 }}
答案 2 :(得分:0)
与其他人一样,我也建议使用循环,但使用更严格的try/except
范围。
另外,重新提升原始异常总是更好,以便保留有关失败的额外信息,包括追溯。
openers_handlers = [ (open_data_file, handle_data_context) ]
def open_and_handle(filename):
for i, (opener, handler) in enumerate(openers_handlers):
try:
f = opener(filename)
except IOError:
if i >= len(openers_handlers) - 1:
# all failed. re-raise the original exception
raise
else:
# try next
continue
else:
# successfully opened. handle:
return handler(f)
答案 3 :(得分:0)
您可以使用上下文管理器:
class ContextManager(object):
def __init__(self, x, failure_handling):
self.x = x
self.failure_handling = failure_handling
def __enter__(self):
return self.x
def __exit__(self, exctype, excinst, exctb):
if exctype == IOError:
if self.failure_handling:
fn = self.failure_handling.pop(0)
with ContextManager(fn(filename), self.failure_handling) as context:
handle_data_content(context)
return True
filename = 'something.something'
with ContextManager(open_data_file(filename), [open_sound_file, open_image_file]) as content:
handle_data_content(content)