Python-精粹-二-

136 阅读18分钟

Python 精粹(二)

原文:Lean Python

协议:CC BY-NC-SA 4.0

九、访问网络

Python 有标准的 1 库,使程序员能够编写使用和实现互联网服务的客户机和服务器,比如电子邮件、文件传输协议(FTP),当然还有网站。

在这一章中,我们来看看如何使用 Python 来访问网站和服务。假设您想从网站下载一个页面,并保存检索到的 HTML。用户需要输入该网站的 URL。也许您希望能够向 URL 添加一个查询字符串,以便将数据传递给请求,然后您希望显示响应或将其保存到磁盘。

当然,你应该设计你的程序分阶段工作:

  1. 向用户询问 URL。

  2. 要求将查询字符串追加到 URL。

  3. 询问是否保存到磁盘。

这里显示了 webtest.py 程序的列表。

1   import requests
2   from urllib.parse import urlparse
3   
4   url=input('Web url to fetch:')
5   urlparts=urlparse(url)
6   if urlparts[0]=='':
7       url=''.join(('http://',url))
8   
9   qstring=input('Enter query string:')
10  if len(qstring)>0:
11      url='?'.join((url,qstring))
12  
13  save=input('Save downloaded page to disk [y/n]?')
14      
15  print('Requesting',url)
16  
17  try:
18      response = requests.get(url)
19      if save.lower()=='y':
20          geturl=response.url
21          urlparts=urlparse(geturl)
22          netloc=urlparts[1]
23          if len(netloc)==0:
24              fname='save.html'
25          else:
26              fname='.'.join((netloc,'html'))
27          print('saving to',fname,'...')
28          fp=open(fname,'w')
29          fp.write(response.text)
30          fp.close()
31      else:
32          print(response.text)
33  except Exception as e:
34      print(e.__class__.__name__,e)

让我们浏览一下这个程序。 2

  • 第 1 行和第 2 行导入所需的模块(请求和 urlparse)。

  • 第 4 行到第 7 行从用户那里获得一个 URL。如果用户不包括 URL 的 http://部分,程序会添加前缀。

  • 第 10 到 12 行要求用户输入一个查询字符串,并用?性格。

  • 第 14 行到第 16 行询问用户是否希望将输出保存到文件中,然后打印所请求的完整 URL。

  • 第 18 到 40 行完成了大部分工作;任何异常都被第 34 行和第 35 行捕获。

  • 第 19 行获取 URL 并保存响应。

  • 第 20 到 31 行根据网站的 URL 创建一个文件名(或使用 save.html ),并将输出保存到该文件。

  • 第 33 行将响应内容打印到屏幕上。

当我运行这个程序时,我看到的是:

D:\LeanPython\programs>python webtest.py
Web url to fetch:uktmf.com
Enter query string:q=node/5277
Save downloaded page to disk [y/n]?y
Requesting http://uktmf.com?q=node/5277
saving to uktmf.com.html ...

d:\LeanPython\programs>

下载页面的内容保存在 uktmf.com.html。

请求库非常灵活,因为您可以使用 requests.post()访问 HTTP“post”动词。

您可以为 post 命令提供数据,如下所示:

data = {'param1': 'value 1','param2': 'value 2'}
response = request.post(url,data=data)

在网站或 web 服务需要的地方,您可以提供用于身份验证的凭证,并以 JSON 数据的形式获取内容。您可以为请求提供定制的头,也可以很容易地看到响应中返回的头。

requests 模块可用于全面测试网站和 web 服务。

脚注

本章假设读者对 web 服务器、浏览器和 HTML 的操作有所了解。

是的,这是一个程序,第一个真正做一些你可能会发现有用的事情的程序。

十、搜索

搜索字符串

在字符串中搜索文本是一种常见的活动,内置的字符串函数 find()是简单搜索所需要的。它返回查找的位置(偏移量),如果没有找到则返回–1。

>>> txt="The quick brown fox jumps over the lazy dog"
>>> txt.find('jump')
20
>>> txt.find('z')
37
>>> txt.find('green')
-1

更复杂的搜索

通常情况下,搜索并不那么简单。我们需要寻找一种模式,从匹配的文本中提取我们真正想要的信息,而不是简单的字符串。例如,假设我们想要提取网页上链接中的所有 URL。这里有一些来自真实网页的 HTML 文本的例子。

1   <link rel="alternate" type="application/rss+xml" title="RSS: 40 newest packages" href="https://pypi.python.org/pypi?:action=packages_rss"/>
2   <link rel="stylesheet" media="screen" href="/static/styles/screen-switcher-default.css" type="text/css"/>
3   <li><a class="" href="/pypi?%3Aaction=browse">Browse&nbsp;packages</a></li>
4   <li><a href="http://wiki.python.org/moin/CheeseShopTutorial">PyPI Tutorial</a></li>

这篇文章中有很多内容。

  • 第 1 行引用了一个 RSS 提要。

  • 第 2 行有一个 href 属性,但是它引用了一个级联样式表(CSS)文件,而不是一个链接。

  • 第 3 行是一个真实的链接,但 URL 是相对的;它不包含 URL 的网站部分。

  • 第 4 行是到外部站点的链接。

怎么才能希望用一些软件找到自己关心的链接呢?这就是正则表达式的用武之地。

引入正则表达式 1

正则表达式 2 是一种利用模式匹配找到我们感兴趣的文本的方法。不仅模式匹配,re 模块还可以从匹配的文本中提取出我们真正想要的数据。

还可以写出更多的例子,事实上有很多关于正则表达式的书籍(例如,[16],[17])。有许多网站,但最有用的可能是 http://www . regular-expressions . info。

注意

正则表达式是包含文本和特殊字符的字符串,这些字符定义了 re 函数可以用来进行匹配的模式。

简单搜索

最简单的正则表达式是你想在另一个字符串中找到的文本字符串,如表 10-1 所示。

表 10-1。查找简单的字符串
|

正则表达式

|

字符串匹配

| | --- | --- | | 跳跃 | 跳跃 | | 女王 | 女王 | | Pqr123 | Pqr123 |

使用特殊字符

表 10-2 中列出了一些特殊字符,它们会影响比赛的进行方式。

表 10-2。使用特殊字符
|

标志

|

描述

|

例子

| | --- | --- | --- | | 逐字的 | 匹配文字字符串 | 跳跃 | | re1|re2 | 匹配字符串 re1 或 re2 | 是|否 | | 。 | 匹配任何单个字符(除了\n) | 国会议员 | | ^ | 匹配字符串的开头 | 这 | | 匹配字符串结尾 | 匹配字符串结尾 | 井 | | * | 匹配前面正则表达式的 0 次或多次出现 | [阿-兹]* | | + | 匹配前面正则表达式的一次或多次出现 | [A-Z]+ | | ? | 匹配前面正则表达式的 0 次或 1 次出现 | 【a-z0-9】? | | {m,n} | 匹配前面正则表达式的 m 个和 n 个匹配项(n 可选) | [0-9]{2,4} | | [...] | 匹配字符类中的任何字符 | [aeiou] | | [x-y] | 匹配范围内的任何字符 | [0-9],[A-Za-z] | | [...] | 不匹配字符类中的任何字符 | [^aeiou] |

表 10-3 中列出了许多可以匹配的特殊字符。

表 10-3。使用特殊字符搜索
|

特殊字符

|

描述

|

例子

| | --- | --- | --- | | \d | 匹配任何十进制数字 | 英国广播公司\d | | \w | 匹配任何字母数字字符 | 收音机\w+ | | \s | 匹配任何空白字符 | \sBBC |

表 10-4 给出了一些正则表达式的例子以及它们匹配的字符串。

表 10-4。正则表达式和匹配字符串
|

正则表达式

|

匹配的字符串

| | --- | --- | | 史密斯|琼斯 | 琼斯·史密斯 | | 一个-什么或者说 | UN 和 O 之间的任意两个字符;例如教科文组织、联合国教科文组织、联合国教科文组织 | | 这 | 任何以 | | 结束$ | 任何以 end 结尾的字符串 | | c[阿伊]t | cat、cit、cot、cut | | [dg][io][gp] | dig,dip,dop,gig,gip,gog,gop | | [阿-德][英-意] | 2 个字符 a/b/c/d,后跟 e/f/g/h/i |

注意正则表达式可以使用文本和特殊字符的任意组合,所以它们有时看起来非常复杂。从简单开始。

在文本中查找模式

在文本中查找子字符串是没问题的,但是我们经常希望在文本中查找模式,而不是文字字符串。假设我们想从文本中提取数值、电话号码或网站 URL。我们如何做到这一点?这就是正则表达式的真正威力所在。

下面是一个正则表达式示例:

\s[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}[\s]

你能猜到它会发现什么吗?这是一个在文本中查找电子邮件地址的正则表达式。乍一看,这看起来很令人生畏,所以让我们把它分成几个组成部分。 3

这个正则表达式有六个元素:

| 1 \s2 [A-Z0-9。_%+-]+3   @4[A-Z0 9。-]+5   \.6 [A-Z]{2,4}7 [\s\] | 前导空白一个或多个字符@字符 A-Z,0-9。-点字符 2 到 4 个文本字符空白或句号 |

显然,您需要知道您所搜索的模式的规则,并且有构建电子邮件地址的特定规则。

下面是文件 remail.py。

1   import re         # The RegEx library
2   #
3   # our regular expression (to find e-mails)
4   # and text to search
5   #
6   regex = '\s[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}[\s]'
7   text="""This is some text with x@y.z embedded e-mails
8   that we'll use as@example.com
9   some lines have no email addresses
10  others@have.two valid email@addresses.com
11  The re module is awonderful@thing."""
12  print('** Search text ***\n'+text)
13  print('** Regex ***\n'+regex+'\n***')
14  #
15  #   uppercase our text
16  utext=text.upper()
17  #
18  #   perform a search (any emails found?)
19  s = re.search(regex,utext)
20  if s:
21      print('*** At least one email found "'+s.group()+'"')
22  #
23  #   now, find all matches
24  #
25  m = re.findall(regex,utext)
26  if m:
27      for match in m:
28          print('Match found',match.strip())
  • 第 1 行导入了我们需要的模块。

  • 第 6 到 13 行定义了要搜索的文本字符串和我们将使用的正则表达式,然后打印它们。

  • 第 16 行大写字母代表文本。

  • 第 19 到 21 行对第一封(任何)电子邮件执行简单的搜索,并打印结果。请注意,匹配包含前导和尾随空白。

  • 第 25 到 28 行查找文本中的所有匹配项并打印结果。

注意,正则表达式匹配电子邮件地址和空白边界。在第 21 行中,我们打印了包含尾随换行符的匹配,但是在第 28 行中,我们去掉了多余的字符。

当我们运行这段代码时会得到什么?这是结果。

D:\LeanPython\programs\Python3>python remail.py
** Search text ***
This is some text with x@y.z embedded emails
that we'll use as@example.com
some lines have no email addresses
others@have.two valid email@addresses.com
The re module is awonderful@thing.
** Regex ***
\s[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}[\s]
***
*** At least one email found " AS@EXAMPLE.COM
"
Match found AS@EXAMPLE.COM
Match found OTHERS@HAVE.TWO
Match found EMAIL@ADDRESSES.COM

捕捉括号

我们应该提到的另一个方面是圆括号的使用。可以像搜索任何其他字符一样搜索它们,但是也可以使用它们来描述匹配的子字符串,re 模块可以捕获这些子字符串,并将它们放在搜索过程返回的列表中。在下面的例子中,这些所谓的捕捉括号提供了我们想要从 HTML 页面中提取的 URL。

在 HTML 中查找链接

以下程序使用 urlliblibrary 下载单个网页。然后使用复杂的正则表达式搜索下载的 HTML 内容的文本,该表达式提取文本链接并提供 URL 和用户看到的链接文本。

这个程序叫做 regex.py。

1   import urllib.request
2   import re         # The RegEx library
3   #
4   #   this code opens a connection to the leanpy.com website
5   #
6   response = urllib.request.urlopen('http://leanpy.com')
7   data1 = str(response.read())           # put response text in data
8   #
9   #   our regular expression (to find links)
10  #
11  regex = '<a\s[^>]*href\s*=\s*\"([^\"]*)\"[^>]*>(.*?)</a>'
12  #
13  #   compile the regex and perform the match (find all)
14  #
15  pm = re.compile(regex)
16  matches = pm.findall(data1)
17  #
18  #   matches is a list
19  #   m[0] - the url of the link
20  #   m[1] - text associated with the link
21  #
22  for m in matches:
23      ms=''.join(('Link: "',m[0],'" Text: "',m[1],'"'))
24      print(ms)

此处显示了该程序的输出。

1   D:\LeanPython\programs>python re.py
2   200 OK
3   Link: "http://leanpy.com/" Text: "Lean Python            "
4   Link: "#content" Text: "Skip to content"
5   Link: "http://leanpy.com/" Text: "Home"
6   Link: "http://leanpy.com/?page_id=33" Text: "About Lean Python            "
7   Link: "http://leanpy.com/" Text: "<img src="http://leanpy.com/wp-content/uploads/2014/04/cropped-LeanPythonHeader.jpg" class="header-image" width="950" height="247" alt="" />"
8   Link: "http://leanpy.com/?p=1" Text: "The Lean Python             Pocketbook"
9   Link: "http://leanpy.com/?p=1#respond" Text: "<span class="leave-reply">Leave a reply</span>"
10  Link: "http://leanpy.com/wp-content/uploads/2014/04/OnePieceCover1-e1396444631642.jpg" Text: "<img class="wp-image-17 alignleft" alt="OnePieceCover" src="http://leanpy.com/wp-content/uploads/2014/04/OnePieceCover1-e1396444631642-633x1024.jpg" width="305" height="491" />"
11  Link: "http://leanpy.com/?cat=3" Text: "Lean Python             Book"
12  Link: "http://leanpy.com/?tag=book" Text: "Book"
13  Link: "http://leanpy.com/?p=1" Text: "<time class="entry-date" datetime="2014-04-02T12:06:06+00:00">April 2, 2014</time>"
14  Link: "http://leanpy.com/?author=1" Text: "paulg"
15  Link: "http://leanpy.com/?p=1" Text: "The Lean Python             Pocketbook"
16  Link: "http://leanpy.com/?cat=3" Text: "Lean Python             Book"
17  Link: "http://leanpy.com/wp-login.php?action=register" Text: "Register"
18  Link: "http://leanpy.com/wp-login.php" Text: "Log in"
19  Link: "http://leanpy.com/?feed=rss2" Text: "Entries <abbr title="Really Simple Syndication">RSS</abbr>"
20  Link: "http://leanpy.com/?feed=comments-rss2" Text: "Comments <abbr title="Really Simple Syndication">RSS</abbr>"
21  Link: "http://wordpress.org/" Text: "WordPress.org"
22  Link: "http://wordpress.org/" Text: "Proudly powered by WordPress"

你可以看到程序识别了所有的链接,但是还没有我们希望的那么智能。

  • *第 4 行:*这个链接使用了同一个页面的书签。

  • *第 7 行:*链接文本实际上是一个图像(我们需要担心这个吗?).

作为练习,也许您可以改进所使用的正则表达式。

脚注

Python re 模块的完整文档可以在 docs.python.org/3/library/r… 的 ?? 找到。正则表达式是任何编程语言中的高级主题。

2 通常,正则表达式简称为 regex。

请注意,这个电子邮件查找器 regex 并不完美。它不会在字符串的开头找到地址,并且会忽略尾部元素中超过四个字符的电子邮件地址(例如。手机)。

十一、数据库

每个 1 应用都使用某种形式的(持久)存储。我们已经看过纯文本文件了。在这一章中,我们考虑 Python 程序如何访问和使用数据库,尤其是关系数据库。

Python 提供了访问所有流行数据库的标准函数。有许多开源和商业数据库产品,每个都有自己的适配器,允许 Python 连接和使用其中保存的数据。出于我们的目的,我们使用 SQLite 数据库,因为它不需要安装其他软件。

数据库

SQLite 是一个非常轻量级的无服务器工具。核心 Python 产品包括 SQLite 适配器,允许我们演示最重要的数据库特性。SQLite 的行为方式与大型系统相同,但是管理开销很低(接近于零)。这样做的结果是 SQLite 可以用于开发或原型制作,以后可以迁移到更复杂的数据库。出于我们的目的,SQLite 提供了我们需要的所有特性。

数据库功能

这些是我们将使用的关键 SQLite 数据库函数:

# open (or create) a database file and return
# the connection
conn = sqlite3                .connect(filename)

# executes a SQL statement
conn.executescript(sql)

# return a cursor
cursor = conn.cursor()

# execute the SQL query that returns rows of data
cursor.execute(sql)

# returns the data as a list of rows
rows = cursor.fetchall() 

将数据连接并加载到 SQLite 中

下面是一个示例程序,它创建一个新的数据库,一个单独的表,插入一些数据,执行一个查询,并尝试插入一个重复的行(dbcreate.py)。

1   import os
2   import sqlite3
3   
4   db_filename='mydatabase.db'
5   #
6   #   if DB exists - delete it
7   #
8   exists = os.path.exists(db_filename)
9   if exists:
10      os.unlink(db_filename)
11  #
12  #   connect to DB (create it if it doesn't exist)
13  #
14  conn = sqlite3.connect(db_filename)
15  #
16  #   create a table
17  #
18  schema="""create table person (
19    id integer primary key autoincrement not null,
20    name text not null,
21    dob  date,
22    nationality text,
23    gender text)
24   """
25  conn.executescript(schema)
26  #
27  # create some data
28  #
29  people="""insert into person (name, dob,nationality,gender)
30  values ('Fred Bloggs', '1965-12-25','British','Male');
31  insert into person (name, dob,nationality,gender)
32  values ('Santa Claus', '968-01-01','Lap','Male');
33  insert into person (name, dob,nationality,gender)
34  values ('Tooth Fairy', '1931-03-31','American','Female');
35  """
36  conn.executescript(people)
37  #
38  #   execute a query
39  #
40  cursor = conn.cursor()
41  cursor.execute("select id, name, dob,nationality,gender from person")
42  for row in cursor.fetchall():
43      id, name, dob,nationality,gender = row
44      print("%3d %15s %12s %10s %6s" % (id, name, dob,nationality,gender))
45  #
46  #   attempt to insert a person with no name
47  #
48  try:
49      dupe="insert into person (id, dob,nationality,gender) \
50      values (1,'1931-03-31','American','Female');"
51      conn.executescript(dupe)
52  except Exception as e:
53      print('Cannot insert record',e.__class__.__name__)
  • 第 1 行和第 2 行导入了我们需要的模块。

  • 第 4 行到第 10 行删除一个旧的数据库文件(注意不要将在这个程序中创建的数据库用于任何有用的用途!).

  • 第 14 行创建数据库文件。

  • 在第 18 到 25 行,模式是一组命令(一个 SQL 脚本),它将创建一个新表。

  • 第 26 行执行 SQL 脚本来创建新表。

  • 在第 29 到 36 行中,定义了一个新的脚本,其中包含在新表中插入三条记录的 SQL 命令。

  • 第 37 行执行脚本。

  • 在第 40 到 44 行,要执行一个查询,您需要创建一个游标,然后使用该游标执行查询。这将建立查询内容,但不会获取数据。cursor.fetchall()提供了一个可迭代的行列表,这些行被分配给命名变量,然后打印出来。

  • 第 48 行到第 53 行建立了一个行的插入,try…except 子句捕获插入中的错误。insert SQL 故意省略了 name 字段来触发异常。

这个程序的输出显示为 hee。

D:\LeanPython\programs>python dbcreate.py
  1     Fred Bloggs   1965-12-25    British   Male
  2     Santa Claus    968-01-01        Lap   Male
  3     Tooth Fairy   1931-03-31   American Female
Cannot insert record IntegrityError

第 52 行的 insert 语句导致的异常被触发,因为没有提供 name 字段(并且必须不为 null)。

在下面的清单(dbupdate.py)中,我们向程序传递两个参数,并在 SQL update 命令中使用它们来更改一个人的国籍。

1   import sqlite3
2   import sys
3   #
4   #   arguments from command line
5   #   use: python dbupdate.py   1  Chinese
6   #
7   db_filename = 'mydatabase.db'
8   inid = sys.argv[1]
9   innat = sys.argv[2]
10  #
11  #   execute update using command-line arguments
12  #
13  conn = sqlite3.connect(db_filename)
14  cursor = conn.cursor()
15  query = "update person set nationality = :nat where id = :id"
16  cursor.execute(query, {'id':inid, 'nat':innat})
17  #
18  #   list the persons to see changes
19  #   
20  cursor.execute("select id, name, dob,nationality,gender from person")
21  for row in cursor.fetchall():
22      id, name, dob,nationality,gender = row
23      print("%3d %15s %12s %10s %6s" % (id, name, dob,nationality,gender))
  • 第 8 行和第 9 行从命令行获取数据:inid 和 innat。

  • 第 13 行到第 16 行完成了大部分工作。第 13 和 14 行设置了光标。第 15 行和以前一样是 SQL,但是用于 SQL 中的字段(id 和 nat)的值是使用冒号符号(:id 和:nat)参数化的。第 16 行执行查询,并使用字典作为调用{'id':inid,' nat':innat}的第二个参数来提供参数的实际值。

这里显示了输出。

D:\LeanPython\programs>python dbupdate.py 1 Chinese
  1     Fred Bloggs   1965-12-25    Chinese   Male
  2     Santa Claus    968-01-01        Lap   Male
  3     Tooth Fairy   1931-03-31   American Female

冒号符号和字典可用于参数化任何 SQL 调用。

脚注

本章假定您了解关系数据库模型和简单结构化查询语言(SQL)命令。

十二、接下来呢?

在这本小书中,我介绍了我在自己的 Python 开发中使用的核心 Python 特性。如果您完成了所有的示例,使用交互式解释器进行了实验,并且使用了示例程序,那么您将会很好地掌握这种出色的编程语言的最基本的元素。

不过,Python 的其他方面可能看起来相当神秘。关于正则表达式、web 应用和 SQLite 的章节只是为了激起您学习更多内容的兴趣。

如果你像我一样,有编程缺陷,将没有什么能阻止你探索这门语言,以及你能用它做什么。如果你是一个使用另一种语言的有经验的程序员,我希望你能理解 Python 是如何工作的,以及编写代码的容易程度。您甚至可能会考虑放弃您的旧语言,转而使用 Python。你们中的一些人可能已经看够了。编程、Python 和所有那些废话可能不适合你。你以前怀疑过,至少现在你确定了。

如果你选择更进一步,这里有一些建议:

  1. 1.购买一本好的语言参考书,或者熟悉附录中给出的在线 Python 参考资料。

  2. 2.探索 PyPI 资源。无论你想用代码做什么,别人已经创建了一个库,这将使你的生活变得更加容易。利用这一点。

  3. 3.练习。就这么简单。就像口语和许多其他技能一样,如果你不使用它,你就会失去它。如果本周你不用 Python 来工作,那就用它来娱乐吧。

如果你用 Python 走得更远,我知道你会玩得很开心!

附录

参考

网页 1
  1. 1.www.artima.com/intv/pythonP.html。访 Python 的发明者吉多·范·罗苏姆。

  2. 2.en . Wikipedia . org/wiki/Python _(programming _ language。Python 语言的维基百科条目。

  3. 3.web2py.com。Web2py web 开发框架。

  4. 4.legacy.python.org/dev/peps/pep-0008/。Python 代码的(PEP 8)风格指南。

  5. 5.legacy.python.org/dev/peps/pep-0020/。Python 的禅。

  6. 6.wiki.python.org/moin/Python2orPython3。我应该用 Python 2 还是 Python 3?

  7. 7.pypi . python . org/pypi。Python 软件包索引。

  8. 8.docs.python.org/3/using/cmdline.html。使用 Python 命令行环境。

  9. 9.www.python.org。Python 语言的官方网站。

  10. 10.docs.python.org/。Python 标准文档。

  11. 11.docs.python.org/3/library/index.html。Python 标准库。

  12. 12.legacy.python.org/dev/peps/pep-0020/。Python 的禅(2014)。

  1. 13.*核心 Python 编程,*卫斯理·淳。

  2. 14.Python 标准库举例, Doug Hellmann。

  3. 15.Alex Martelli,David Ascher 和 Anna Martelli Ravenscroft。

  4. 16.*掌握 Python 正则表达式,*菲利克斯·洛佩兹和维克多·罗梅罗。

  5. 17.*掌握正则表达式,*杰弗里·弗里德尔。

工具
  1. 18.视觉塞斯尔:www.obelisk.me.uk/cesil/(2016)。

  2. 19.PIP 安装程序:www . pip-installer . org/(2014 年)。

  3. 20.Python 单元测试框架:docs.python.org/3.4/library/unittest.html

Python 内置的异常层次 2

在第七章中,我们描述了 Python 如何管理异常。我们在那里介绍了一些异常类型,但这里是完整的列表。

BaseException
 +-- SystemExit
 +-- KeyboardInterrupt
 +-- GeneratorExit
 +-- Exception
      +-- StopIteration
      +-- StandardError
      |    +-- BufferError
      |    +-- ArithmeticError
      |    |    +-- FloatingPointError
      |    |    +-- OverflowError
      |    |    +-- ZeroDivisionError
      |    +-- AssertionError
      |    +-- AttributeError
      |    +-- EnvironmentError
      |    |    +-- IOError
      |    |    +-- OSError
      |    |         +-- WindowsError (Windows)
      |    |         +-- VMSError (VMS)
      |    +-- EOFError
      |    +-- ImportError
      |    +-- LookupError
      |    |    +-- IndexError
      |    |    +-- KeyError
      |    +-- MemoryError
      |    +-- NameError
      |    |    +-- UnboundLocalError
      |    +-- ReferenceError
      |    +-- RuntimeError
      |    |    +-- NotImplementedError
      |    +-- SyntaxError
      |    |    +-- IndentationError
      |    |         +-- TabError
      |    +-- SystemError
      |    +-- TypeError
      |    +-- ValueError
      |         +-- UnicodeError
      |              +-- UnicodeDecodeError
      |              +-- UnicodeEncodeError
      |              +-- UnicodeTranslateError
      +-- Warning
           +-- DeprecationWarning
           +-- PendingDeprecationWarning
           +-- RuntimeWarning
           +-- SyntaxWarning
           +-- UserWarning
           +-- FutureWarning
                   +-- ImportWarning
                   +-- UnicodeWarning
                   +-- BytesWarning

脚注

1 这些 URL 在发布时有效,但可能会发生变化。

2 摘自 docs.python.org/3/library/e…