您的位置:首页 > 编程语言 > Python开发

python abc II

2016-03-16 15:44 691 查看
http://python.usyiyi.cn/python_278/tutorial/errors.html

格式化输出

Python 有方法将任何值转换为字符串:将它传递给repr()或str()函数。

str()函数的用意在于返回人类可读的表现形式,而repr()的用意在于生成解释器可读的表现形式

(如果没有等价的语法将会引发SyntaxError异常)

>>> for x in range(1, 11):
...     print repr(x).rjust(2), repr(x*x).rjust(3),
...     # Note trailing comma on previous line
...     print repr(x*x*x).rjust(4)
...
1   1    1
2   4    8
3   9   27
4  16   64
5  25  125
6  36  216
7  49  343
8  64  512
9  81  729
10 100 1000
>>> for x in range(1,11):
...     print '{0:2d} {1:3d} {2:4d}'.format(x, x*x, x*x*x)
...
1   1    1
2   4    8
3   9   27
4  16   64
5  25  125
6  36  216
7  49  343
8  64  512
9  81  729
10 100 1000


(注意在第一个示例中,每列之间的一个空格由print自动添加:它总会在它的参数之间添加空格。)

上面的例子演示了字符串对象的str.rjust()方法,它通过在左侧填充空格使字符串在给定宽度的列右对齐。类似的方法还有str.ljust()和str.center()。这些方法不会输出任何内容,它们只返回新的字符串。如果输入的字符串太长,它们不会截断字符串,而是保持原样返回;这会使列的格式变得混乱,但是通常好于另外一种选择,那可能是一个错误的值。(如果你真的想要截断,可以加上一个切片操作,例如x.ljust(n)[:n]。)

另外一种方法 str.zfill(),它向数值字符串左侧填充零。该函数可以正确识别正负号:

>>> '12'.zfill(5)
'00012'
>>> '-3.14'.zfill(7)
'-003.14'
>>> '3.14159265359'.zfill(5)
'3.14159265359'


str.format()方法的基本用法如下所示:

>>> print 'We are the {} who say "{}!"'.format('knights', 'Ni')
We are the knights who say "Ni!"


使用json存储结构化数据

从文件中读写字符串很容易。数值就要多费点儿周折,因为read ()方法只会返回字符串,应将其传入int()这样的函数,就可以将’123’这样的字符串转换为对应的数值 123。当你想要保存更为复杂的数据类型,例如嵌套的列表和字典,手工解析和序列化它们将变得更复杂。

好在用户不是非得自己编写和调试保存复杂数据类型的代码,Python 允许你使用常用的数据交换格式JSON(JavaScript Object Notation)。标准模块json可以接受 Python 数据结构,并将它们转换为字符串表示形式;此过程称为序列化。从字符串表示形式重新构建数据结构称为反序列化。序列化和反序列化的过程中,表示该对象的字符串可以存储在文件或数据中,也可以通过网络连接传送给远程的机器。

注意

JSON 格式经常用于现代应用程序中进行数据交换。许多程序员都已经熟悉它了,使它成为相互协作的一个不错的选择。

如果你有一个对象x,你可以用简单的一行代码查看其 JSON 字符串表示形式:

>>> json.dumps([1, 'simple', 'list'])
'[1, "simple", "list"]'


dumps()函数的另外一个变体dump(),直接将对象序列化到一个文件。所以如果f是为写入而打开的一个文件对象,我们可以这样做:

json.dump(x, f)

为了重新解码对象,如果f是为读取而打开的文件对象 :

x = json.load(f)

这种简单的序列化技术可以处理列表和字典,但序列化任意类实例为 JSON 需要一点额外的努力

处理异常

可以通过编程来选择处理部分异常。看一下下面的例子,它会一直要求用户输入直到输入一个合法的整数为止,但允许用户中断这个程序(使用Control-C或系统支持的任何方法);注意用户产生的中断引发的是 KeyboardInterrupt 异常。

>>> while True:
...     try:
...         x = int(raw_input("Please enter a number: "))
...         break
...     except ValueError:
...         print "Oops!  That was no valid number.  Try again..."
...


Try语句按以下方式工作。

首先,执行try 子句(try和except关键字之间的语句)。
如果未发生任何异常,忽略except 子句且try语句执行完毕。
如果在 try 子句执行过程中发生异常,跳过该子句的其余部分。如果异常的类型与except关键字后面的异常名匹配, 则执行 except 子句,然后继续执行try语句之后的代码。
如果异常的类型与 except 关键字后面的异常名不匹配,它将被传递给上层的try语句;如果没有找到处理这个异常的代码,它就成为一个未处理异常,程序会终止运行并显示一条如上所示的信息。


Try语句可能有多个异常子句,用来指定多个不同的异常。不过至多只有一个处理程序将被执行。处理程序只处理发生在相应 try 子句中的异常,不会处理同一个try字句的其他处理程序中发生的异常。一个 except 子句可以用带括号的元组列出多个异常的名字,例如:

... except (RuntimeError, TypeError, NameError):
...     pass


注意,此元组周围的括号是必需的,因为except ValueError, e:是旧式的写法,在现代 Python 中通常写成 except ValueError as e: (如下所述)。为了保持向后兼容性,旧式语法仍然是支持的。这意味着except RuntimeError, TypeError不等同于except (RuntimeError, TypeError): 而等同于except RuntimeError as TypeError: , 这应该不是你想要的。

最后一个 except 子句可以省略异常名称,以当作通配符使用。使用这种方式要特别小心,因为它会隐藏一个真实的程序错误!它还可以用来打印一条错误消息,然后重新引发异常 (让调用者也去处理这个异常):

import sys
try:
f = open('myfile.txt')
s = f.readline()
i = int(s.strip())
except IOError as e:
print "I/O error({0}): {1}".format(e.errno, e.strerror)
except ValueError:
print "Could not convert data to an integer."
except:
print "Unexpected error:", sys.exc_info()[0]
raise


try…except语句有一个可选的else 子句,其出现时,必须放在所有 except 子句的后面。如果需要在 try 语句没有抛出异常时执行一些代码,可以使用这个子句。例如:

for arg in sys.argv[1:]:
try:
f = open(arg, 'r')
except IOError:
print 'cannot open', arg
else:
print arg, 'has', len(f.readlines()), 'lines'
f.close()


使用else子句比把额外的代码放在try子句中要好,因为它可以避免意外捕获不是由try … except语句保护的代码所引发的异常。

当异常发生时,它可能带有相关数据,也称为异常的参数。参数的有无和类型取决于异常的类型。

except 子句可以在异常名(或元组)之后指定一个变量。这个变量将绑定于一个异常实例,同时异常的参数将存放在实例的args中。为方便起见,异常实例定义了str() ,因此异常的参数可以直接打印而不必引用.args。

也可以在引发异常之前先实例化一个异常,然后向它添加任何想要的属性。

>>> try:
...    raise Exception('spam', 'eggs')
... except Exception as inst:
...    print type(inst)     # the exception instance
...    print inst.args      # arguments stored in .args
...    print inst           # __str__ allows args to be printed directly
...    x, y = inst.args
...    print 'x =', x
...    print 'y =', y
...
<type 'exceptions.Exception'>
('spam', 'eggs')
('spam', 'eggs')
x = spam
y = eggs


对于未处理的异常,如果它含有参数,那么参数会作为异常信息的最后一部分打印出来。

异常处理程序不仅处理直接发生在 try 子句中的异常,而且还处理 try 子句中调用的函数(甚至间接调用的函数)引发的异常。例如:

>>> def this_fails():
...     x = 1/0
...
>>> try:
...     this_fails()
... except ZeroDivisionError as detail:
...     print 'Handling run-time error:', detail
...
Handling run-time error: integer division or modulo by zero


raise语句允许程序员强行引发一个指定的异常。例如:

>>> raise NameError('HiThere')
Traceback (most recent call last):
File "<stdin>", line 1, in ?
NameError: HiThere


raise的唯一参数指示要引发的异常。它必须是一个异常实例或异常类(从Exception派生的类)。

如果你确定需要引发异常,但不打算处理它,一个简单形式的raise语句允许你重新引发异常:

>>> try:
...     raise NameError('HiThere')
... except NameError:
...     print 'An exception flew by!'
...     raise
...
An exception flew by!
Traceback (most recent call last):
File "<stdin>", line 2, in ?
NameError: HiThere


定义清理操作

Try语句有另一个可选的子句,目的在于定义必须在所有情况下执行的清理操作。例如:

>>> try:
...     raise KeyboardInterrupt
... finally:
...     print 'Goodbye, world!'
...
Goodbye, world!
KeyboardInterrupt


不管有没有发生异常,在离开try语句之前总是会执行finally 子句。当try子句中发生了一个异常,并且没有except字句处理(或者异常发生在try或else子句中),在执行完finally子句后将重新引发这个异常。try语句由于break、contine或return语句离开时,同样会执行finally子句。以下是一个更复杂些的例子 (同时有except和finally字句的try语句的工作方式与 Python 2.5 一样):

>>> def divide(x, y):
...     try:
...         result = x / y
...     except ZeroDivisionError:
...         print "division by zero!"
...     else:
...         print "result is", result
...     finally:
...         print "executing finally clause"
...
>>> divide(2, 1)
result is 2
executing finally clause
>>> divide(2, 0)
division by zero!
executing finally clause
>>> divide("2", "1")
executing finally clause
Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "<stdin>", line 3, in divide
TypeError: unsupported operand type(s) for /: 'str' and 'str'


正如您所看到的,在任何情况下都会执行finally子句。由两个字符串相除引发的 TypeError异常没有被except子句处理,因此在执行finally子句后被重新引发。

在真实的应用程序中, finally子句用于释放外部资源(例如文件或网络连接),不管资源的使用是否成功。

8.7. 清理操作的预定义

有些对象定义了在不需要该对象时的标准清理操作,无论该对象的使用是成功还是失败。看看下面的示例,它尝试打开一个文件并打印其内容到屏幕。

for line in open("myfile.txt"):
print line,


这段代码的问题就是代码执行完之后它还会让文件在一段不确定的时间内保持打开状态。这在简单的脚本中没什么,但是在大型应用程序中可能是一个问题。 With语句可以确保像文件这样的对象总能及时准确地被清理掉。

with open("myfile.txt") as f:
for line in f:
print line,


执行该语句后,文件f 将始终被关闭,即使在处理某一行时遇到了问题。其它对象是否提供了预定义的清理行为要查看它们的文档。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: