在python中使用异常和文件时清理

3 python file-io exception

我现在正在学习python几天,并且正在努力学习它的"精神".我是从C/C++/Java/Perl学校来的,我知道python不是C(根本就是)这就是为什么我试图理解精神来充分利用它(到目前为止很难) ...

我的问题主要集中在异常处理和清理上:本文末尾的代码用于模拟文件打开/解析的相当常见的情况,如果出现错误,您需要关闭文件...

我见过的大多数样本使用try语句的'else'子句来关闭文件......这对我来说很有意义,直到我意识到错误可能是由于

  • 开放本身(在这种情况下,不需要关闭未打开的文件)
  • 解析(在这种情况下需要关闭文件)

这里的陷阱是,如果你使用try bloc的'else'子句,那么如果在解析期间发生错误,文件永远不会被关闭!在另一端使用'finally'子句导致额外的必要检查,因为如果在打开期间发生错误,file_desc变量可能不存在(请参阅下面代码中的注释)...

这个额外的检查是低效的,并且充满了糟糕,因为任何合理的程序可能包含数百个符号并且解析dir()的结果是痛苦的...更不用说这样的声明缺乏可读性......

大多数其他语言允许变量定义,这可以节省一天...但在python中,一切似乎是隐含的......

通常,只会声明一个file_desc变量,然后为每个任务使用许多try/catch块...一个用于打开,一个用于解析,最后一个用于关闭()...不需要嵌套它们......在这里我不知道一种声明变量的方法......所以我在问题开始时就陷入了困境!

那么这里的python精神是什么?

  • 用两种不同的方法拆分开头/解析?怎么样 ?
  • 使用某种嵌套的try/except子句??? 怎么样 ?
  • 也许有一种方法来声明file_desc变量,然后就不需要额外的检查......它是否可能?可取的???
  • 怎么样的close()语句??? 怎么会引起错误?

thanx为您的提示...这里是示例代码:

class FormatError(Exception):
    def __init__(self, message):
        self.strerror = message
    def __str__(self):
        return repr(message)


file_name = raw_input("Input a filename please: ")
try:
    file_desc = open(file_name, 'r')
    # read the file...
    while True:
        current_line = file_desc.readline()
        if not current_line: break
        print current_line.rstrip("\n")
    # lets simulate some parsing error...
    raise FormatError("oops... the file format is wrong...")
except FormatError as format_error:
    print "The file {0} is invalid: {1}".format(file_name, format_error.strerror)
except IOError as io_error:
    print "The file {0} could not be read: {1}".format(file_name, io_error.strerror)
else:
    file_desc.close()
# finally:
#     if 'file_desc' in dir() and not file_desc.closed:
#        file_desc.close()

if 'file_desc' in dir():
    print "The file exists and closed={0}".format(file_desc.closed)
else:
    print "The file has never been defined..."
Run Code Online (Sandbox Code Playgroud)

AKX*_*AKX 6

解决这个问题最简单的方法是使用Python 2.5+中的文件对象是上下文管理器.您可以使用该with语句输入上下文; __exit__退出此with范围时,将自动调用上下文管理器的方法.然后,文件对象的上下文管理会自动关闭文件.

try:
    with file("hello.txt") as input_file:
        for line in input_file:
            if "hello" not in line:
                 raise ValueError("Every line must contain 'hello'!")
except IOError:
    print "Damnit, couldn't open the file."
except:
    raise
else:
    print "Everything went fine!"
Run Code Online (Sandbox Code Playgroud)

打开的hello.txt句柄将自动关闭,with范围内的异常将在外部传播.