Python 创建WSGI应用程序,首先使用一个简单的URL模式匹配表达式来定义应用程序中的唯一路由。在一个更大或更复杂的应用程序中,模式可能不止一种:
通过这种模式,可以在路径顶层定义一个关于WSGI的完整脚本。在本例中,该脚本是anscombe
。我们把下一级路径作为通过安斯库姆四重奏选取的数据集,数据集的值落于I
、II
、III
或IV
。
使用命名参数作为选取条件。在许多情况下,可以使用如下语法来描述RESTful API:
这种理想化的模式转化为了适当的正则表达式,并在路径中保留了数据集选择器的名称。
一些URL路径示例如下,它们演示了这种模式的工作原理:
这些示例都显示了从URL路径中解析得到的详细信息。如果指定了某个序列的名称,则它会出现在路径中;如果没有指定序列名称,则模式返回的是一个空字符串。
完整的WSGI应用程序如下:
该应用程序会从请求中提取两条信息:环境字典中的PATH_INFO
键和QUERY_STRING
键。PATH_INFO
请求会定义要提取的数据集。QUERY_STRING
请求将指定输出的格式。
请注意,查询字符串可能非常复杂。我们使用了urllib.parse
模块来准确定位查询字符串中所有名称和值的配对,而不是简单地假定它是一个类似于?form=json
的字符串。在通过查询字符串提取得到的字典中,可以在query['form'][0]
中找到以form
为键的值。这应该是定义过的格式之一,否则会引发异常,并显示一个错误页面。
定位到路径和查询字符串后,用粗体强调了应用程序的处理过程。这两条语句依赖三个函数来对结果进行收集、过滤和序列化。
- 函数
raw_data()
从文件中读取原始数据,结果是一个包含一组Pair
对象的字典。 - 函数
anscombe_filter()
接收一个选择字符串和源数据字典,并返回Pair
对象的单个列表。 serialize()
函数随后将该配对列表序列化为字节码。序列化器会生成字节码,这样就可以用合适的报头打包并返回了。
我们选择了生成一个HTTP的Content-Length
报头作为结果的一部分。这个报头并不是必需的,但有助于下载大文件。由于我们决定发送该报头,因此必须用序列化的数据创建字节对象,以便统计这些字节。
如果选择忽略Content-Length
报头,那么可以大规模地改变这个应用程序的结构。可以把每个序列化器都更改为生成器函数,并且它们在创建时会生成字节对象。对于大型数据集来说,这种优化可能有益,然而对于关注下载进度的用户可能不太友好,因为浏览器无法显示下载的完成情况。
一种常见的优化是将事务分解为两部分。第一部分用于计算结果并将文件放入Downloads目录。响应是一个带有Location
报头的302 FOUND
,用于标识需下载的文件。通常大部分客户端会基于这个原始响应来请求文件。可以用不涉及Python应用的Apache httpd或者Nginx下载文件。
本例将所有错误视为404 NOT FOUND
错误会引起误导,因为可能是其他环节出了问题。更复杂的错误处理会引入更多的try:/except:
块来提供更多信息反馈。
出于调试的目的,在生成的Web页面中提供了Python的栈跟踪。在没有调试需求的环境中,这是一种非常糟糕的做法。来自API的反馈应该只用于处理请求,无他。栈跟踪会向潜在的恶意用户提供过多信息。