with 语句定义资源的使用上下文。当执行离开上下文时,资源被释放。with 语句仅适用于经过专门编程以支持它的某些对象。
练习 练习 3.8:触发异常在上一节中编写的 parse_csv() 函数允许选择用户指定的列,但是只有输入数据文件具有列标题时才会生效。
请修改代码,以便在同时传递 select 和 has_headers=False 参数时触发异常。例如:
>>> parse_csv('Data/prices.csv', select=['name','price'], has_headers=False) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "fileparse.py", line 9, in parse_csv raise RuntimeError("select argument requires column headers") RuntimeError: select argument requires column headers >>>添加此检查后,你可能会问是否应该在函数中执行其它类型的完整性检查。例如,检查文件名是字符串,列表还是其它类型?
一般来说,最好是跳过此类测试,输入错误的时候让程序运行失败。回溯信息会指出问题的根源,并且帮助调试。
添加上述检查的主要原因是为了避免在无意义的模式下运行代码(例如,使用要求列标题的特性,但是同时指定没有标题)。
这表明调用代码部分出现一个编程错误。检查“不应发生”的情况通常是个好主意。
练习 3.9:捕获异常你编写的 parse_csv() 函数用于处理文件的全部内容。但是,在现实世界中,输入文件可能包含损坏的数据,丢失的数据或者脏数据。尝试下面这个实验:
>>> portfolio = parse_csv('Data/missing.csv', types=[str, int, float]) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "fileparse.py", line 36, in parse_csv row = [func(val) for func, val in zip(types, row)] ValueError: invalid literal for int() with base 10: '' >>>请修改 parse_csv() 函数以便捕获所有在记录创建期间生成的 ValueError 异常,并为无法转换的行打印警告消息。
错误消息应该包括行号以及有关失败原因的信息。要测试函数,尝试读取上面的 Data/missing.csv 文件,例如:
>>> portfolio = parse_csv('Data/missing.csv', types=[str, int, float]) Row 4: Couldn't convert ['MSFT', '', '51.23'] Row 4: Reason invalid literal for int() with base 10: '' Row 7: Couldn't convert ['IBM', '', '70.44'] Row 7: Reason invalid literal for int() with base 10: '' >>> >>> portfolio [{'price': 32.2, 'name': 'AA', 'shares': 100}, {'price': 91.1, 'name': 'IBM', 'shares': 50}, {'price': 83.44, 'name': 'CAT', 'shares': 150}, {'price': 40.37, 'name': 'GE', 'shares': 95}, {'price': 65.1, 'name': 'MSFT', 'shares': 50}] >>> 练习 3.10:隐藏错误请修改 parse_csv()函数,以便用户明确需要时可以隐藏解析的错误消息,例如:
>>> portfolio = parse_csv('Data/missing.csv', types=[str,int,float], silence_errors=True) >>> portfolio [{'price': 32.2, 'name': 'AA', 'shares': 100}, {'price': 91.1, 'name': 'IBM', 'shares': 50}, {'price': 83.44, 'name': 'CAT', 'shares': 150}, {'price': 40.37, 'name': 'GE', 'shares': 95}, {'price': 65.1, 'name': 'MSFT', 'shares': 50}] >>>在大部分的程序中,错误处理是最难做好的事情之一。一般来说,不应该默默地忽略错误。相反,最好是报告问题,并且让用户选择是否隐藏错误信息(如果它们选择这样做)。
注:完整翻译见 https://github.com/codists/practical-python-zh