我现在正在学习python几天,并且正在努力学习它的“精神”。 我是从C / C ++ / Java / Perl学校来的,我知道python不是C(根本就是)这就是为什么我试图理解精神来充分利用它(到目前为止很难) ...
我的问题特别关注异常处理和清理: 本文末尾的代码用于模拟文件打开/解析的相当常见的情况,如果出现错误,您需要关闭文件...
我见过的大多数样本使用try语句的'else'子句来关闭文件......这对我来说很有意义,直到我意识到错误可能是由于
这里的陷阱是,如果你使用try bloc的'else'子句,那么如果在解析期间发生错误,文件永远不会被关闭! 另一方面,使用'finally'子句导致额外的必要检查,因为如果在打开期间发生错误,则file_desc变量可能不存在(参见下面代码中的注释)......
这个额外的检查是低效的,并且充满了糟糕,因为任何合理的程序可能包含数百个符号并且解析dir()的结果是痛苦的...更不用说这样的语句缺乏可读性。 ..
大多数其他语言允许变量定义,这可以节省一天...但在python中,一切似乎都是隐含的......
通常,只需要声明一个file_desc变量,然后为每个任务使用许多try / catch块...一个用于打开,一个用于解析,最后一个用于关闭()...不需要嵌套它们......在这里,我不知道一种声明变量的方法......所以我在问题的开头就陷入了困境!
那么这里的python精神是什么?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..."
答案 0 :(得分:6)
处理此问题的最简单方法是使用Python 2.5+中的文件对象context managers这一事实。您可以使用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!"
open hello.txt句柄将自动关闭,with scope中的异常将在外部传播。
答案 1 :(得分:2)
只需注意:你总是可以声明一个变量,然后就会变成这样:
file_desc = None
try:
file_desc = open(file_name, 'r')
except IOError, err:
pass
finally:
if file_desc:
close(file_desc)
当然,如果您使用的是较新版本的Python,那么使用上下文管理器的构造会更好;但是,我想指出如何在Python中一般处理异常和变量范围。
答案 2 :(得分:1)
从Python 2.5开始,有一个with
命令可以简化您正在与之抗争的内容。阅读更多相关信息here。这是您的代码的转换版本:
class FormatError(Exception):
def __init__(self, message):
self.strerror = message
def __str__(self):
return repr(message)
file_name = raw_input("Input a filename please: ")
with open(file_name, 'r') as file_desc:
try:
# 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)
if 'file_desc' in dir():
print "The file exists and closed={0}".format(file_desc.closed)
else:
print "The file has never been defined..."
答案 3 :(得分:0)
下面的代码可以解决问题。 您必须使用'with as'语句创建一个嵌套块,以确保清除该文件:
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:
#
# THIS IS PYTHON'S SPIRIT... no else/finally
#
with open(file_name, 'r') as file_desc:
# read the file...
while True:
current_line = file_desc.readline()
if not current_line: break
print current_line.rstrip("\n")
raise FormatError("oops... the file format is wrong...")
print "will never get here"
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)
if 'file_desc' in dir():
print "The file exists and closed={0}".format(file_desc.closed)
else:
print "The file has never been defined..."
答案 4 :(得分:0)
关闭我的知识永远不会返回错误。
实际上,文件句柄将在收集垃圾时关闭,因此您不必在Python中显式执行。虽然这样做仍然是很好的编程,显然。