Python高级编程(第2版)(txt+pdf+epub+mobi电子书下载)


发布时间:2020-07-15 02:33:24

点击下载

作者:(波兰)Micha Jaworski 贾沃斯基 (法)Tarek Ziadé 莱德

出版社:人民邮电出版社

格式: AZW3, DOCX, EPUB, MOBI, PDF, TXT

Python高级编程(第2版)

Python高级编程(第2版)试读:

前言

Python很棒!

从20世纪80年代末出现的最早版本到当前版本,Python的发展一直遵循着相同的理念:提供一个同时具备可读性和生产力的多范式编程语言。

人们曾经将Python看作另一种脚本语言,认为它不适合构建大型系统。但多年以来,在一些先驱公司的努力下,Python显然可以用于构建几乎任何类型的系统。

实际上,许多其他语言的开发者也醉心于Python,并将它作为首选语言。

如果你购买了这本书,可能已经知道这些内容了,所以无需再向你证明这门语言的优点。

本书展现了作者多年构建各种Python应用的经验,从几个小时完成的小型系统脚本,到许多开发人员历经数年编写的大型应用。

本书描述了开发人员使用Python的最佳实践。

本书包含了一些主题,这些主题并不关注语言本身,而是更多地关注如何利用相关的工具和技术。

换句话说,本书描述了高级Python开发人员每天的工作方式。

本书内容

第1章介绍了Python语言及其社区的现状。本章展示了Python不断变化的方式及原因,还解释了为什么这些事实对任何想要自称Python专家的人来说是很重要的。本章还介绍了最流行和最公认的Python工作方式——常用的生产力工具和现已成为标准的约定。

第2章深入介绍迭代器、生成器、描述符等内容。本章还包括关于Python习语和CPython类型内部实现的有用注释,这些类型的计算复杂度是对这些习语的阐释。

第3章介绍了语法最佳实践,但重点放在类级别以上。本章包括Python中更高级的面向对象的概念和机制。学习这些知识是为了理解本章最后一节的内容,其中介绍的是Python元编程的各种方法。

第4章介绍了如何选择好的名称。它是对PEP 8中命名最佳实践的扩展,并且给出了一些如何设计良好API的提示。

第5章介绍如何创建Python包以及使用哪些工具,以便在官方的Python包索引或其他包仓库中正确地分发。对于Python包还补充了一些工具的简要回顾,这些工具可以让你用Python源代码创建独立可执行文件。

第6章主要针对Python Web开发人员和后端工程师,因为讲的是代码部署。本章解释了如何构建Python应用,使其可以轻松部署到远程服务器,还介绍了可以将这个过程自动化的工具。本章是第5章的延续,因此还介绍了如何使用包和私有包仓库来简化应用部署。

第7章解释了为什么为Python编写C扩展程序有时可能是一个好的解决方案。本章还展示了只要使用了正确的工具,它并不像想象中那么难。

第8章深入介绍了项目代码库的管理方式,还介绍了如何设置各种持续开发流程。

第9章包含文档相关的内容,提供了有关技术写作和Python项目文档化方式的建议。

第10章解释了测试驱动开发的基本原理,还介绍了可用于这种开发方法的工具。

第11章解释了何为优化,介绍了分析技术和优化策略指南。

第12章是对第11章的扩展,为Python程序中经常出现的性能问题提供了一些常用的解决方案。

第13章介绍了Python并发这一宏大的主题。本章解释了并发的概念、何时需要编写并发应用,以及Python程序员主要使用的并发方法。

第14章用一套有用的设计模式以及Python的代码示例对本书进行了总结。

阅读本书的前提

本书面向的是可以在任何操作系统上使用Python 3进行软件开发的人员。

这不是一本面向初学者的书,所以我假设你已经在开发环境中安装了Python,或者知道如何安装Python。不管怎样,本书考虑到以下事实:不是每个人都需要充分了解Python的最新功能或官方推荐的工具。因此,第1章概述了常见的实用程序(例如虚拟环境和pip),这些实用程序现在已经成为Python专业开发人员的标准工具。

目标读者

本书面向的是想要进一步掌握 Python 的开发人员。开发人员主要指的是专业人士,即用Python编写软件的程序员。这是因为本书主要侧重于工具和实践,它们对于创建高性能的、可靠且可维护的Python软件至关重要。

这并不意味着业余爱好者无法从本书中发现有趣的内容。对于任何对学习Python高级概念感兴趣的人来说,本书都是很棒的。任何具备Python基本技能的人都应该能够读懂本书的内容,虽然经验不足的程序员可能需要一些额外的努力。对于有点落后仍在继续使用Python 2.7或更老版本的人来说,本书也是对Python 3.5的全面介绍。

最后,从阅读本书中受益最多的人群应该是Web开发者和后端工程师。这是因为本书重点介绍了在他们的工作领域中特别重要的两个主题:可靠的代码部署与并发。

本书约定

本书用多种文本样式来区分不同种类的信息。下面是这些样式的示例及其含义解释。

文本中的代码、数据库表的名称、文件夹名称、文件名称、文件扩展名、路径名称、虚拟 URL、用户输入和 Twitter 句柄的格式如下所示:“利用 str.encode(encoding,errors)方法,用注册编解码器对字符串进行编码。”

代码块的格式如下所示:

[print("hello world")

print "goodbye python2"

如果我们想让你将注意力集中在代码块的特定区域,相关的几行或几项将会被设成粗体,如下所示:

cdef long long fibonacci_cc(unsigned int n) nogil:

if n < 2:

return n

else:

return fibonacci_cc(n - 1) + fibonacci_cc(n - 2)

命令行的输入或输出如下所示:

$ pip show pip

---

Metadata-Version: 2.0

Name: pip

Version: 7.1.2

Summary: The PyPA recommended tool for installing Python packages.

Home-page: https://pip.pypa.io/

Author: The pip developers

Author-email: python-virtualenv@groups.google.com

License: MIT

Location: /usr/lib/python2.7/site-packages

Requires:

新术语和重要词语将以粗体显示。你会在屏幕上看到的单词(例如在菜单或对话框中)将以下面这种文本形式出现:“单击Next按钮可跳转至下一屏”。

读者反馈

我们十分欢迎读者的反馈意见。让我们了解你对本书的看法——喜欢哪些内容,不喜欢哪些内容。这些反馈对我们很重要,因为它有助于我们编写出对读者真正有帮助的书。

一般性的反馈请发送邮件至feedback@packtpub.com,并在邮件主题中注明本书的标题。

如果你是某个领域的专家,并且有兴趣写一本书或者参与出版一本书,请参阅我们的作者指南。

客户支持

现在你已经成为这本 Packt 图书的拥有者,为了让你的购买物超所值,我们还为你提供了许多其他方面的服务。

下载示例代码

你可以用自己的账号在 Packt 的官方网站下载本书的示例代码文件。如果你是在其他地方购买的本书,可以访问Packt的官方网站并注册,文件会直接通过邮件发送给你。

下载代码文件的步骤如下所示。

·用你的电子邮件地址和密码登录或注册我们的网站。

·将鼠标指针悬停在顶部的SUPPORT选项卡上。

·单击Code Downloads & Errata。

·在Search框中输入本书的名字。

·选择你要下载代码文件的书籍。

·从下拉菜单中选择本书的购买途径。

·单击Code Download。

你还可以在Packt网站的本书页面单击Code Files按钮来下载代码文件。在Search框输入本书的书名即可访问该页面。请注意,你需要登录Packt账号。

文件下载完成后,请确保用下列软件的最新版本对文件夹进行解压或提取。

·在Windows上用WinRAR或7-Zip。

·在Mac上用Zipeg、iZip或UnRarX。

·在Linux上用7-Zip或PeaZip。

本书的代码包也托管在GitHub,网址为https://github.com/PacktPublishing/Expert-Python-Programming_Second-Edition。在GitHub上还有大量图书和视频资源。快去看一下吧!

勘误

尽管我们已经竭尽全力确保本书内容的准确性,但错误在所难免。如果你发现了书中的错误,无论是正文错误还是代码错误,希望你能将其报告给我们,我们将不胜感激。这样不仅能够减少其他读者的困惑,还能帮助我们改进本书后续版本的质量。如果你需要提交勘误,请访问http://www.packtpub.com/submit-errata,选择相应的书名,单击Errata Submission Form链接,然后输入你的勘误信息并提交。一旦通过验证,我们将接受你提交的勘误,同时勘误内容也将被上传到我们的网站,或者被添加到对应勘误区的现有勘误列表中。

想要查看之前提交的勘误,请访问https://www.packtpub.com/books/content/support,并在搜索框中输入相应的书名。你想查看的信息将出现在Errata下面。

侵权行为

所有媒体在互联网上都一直饱受版权侵害的困扰。Packt坚持对版权和授权进行全力保护。如果你在互联网上发现我社图书任何形式的盗版,请立即为我们提供网址或网站名称,以便我们采取进一步的措施。

请将疑似盗版材料的链接发送到copyright@packtpub.com。

我们感谢你对作者的保护,这有助于我们继续为你提供更有价值的内容。

疑难解答

如果你对本书的某个方面抱有疑问,请通过 questions@packtpub.com 联系我们,我们会尽力为你解决。第1章Python现状

Python很适合开发者使用。

无论你或你的客户用的是什么操作系统,都可以使用Python。例如你可以在Linux上工作,然后部署到其他系统上,除非你的代码与特定平台相关,或者用到了特定平台的库。但这一特性已经不新鲜了(Ruby、Java等很多其他语言都可以做到这一点)。本书还会讲到Python的其他特性,所有这些特性是使得Python成为一家公司主力开发语言的重要原因。

本书主要讲的是Python的3.5版本,如果没有明确说明的话,书中所有代码示例都是用这个版本的Python编写的。由于这一版本尚未被广泛使用,本章将会向读者介绍一下Python 3的当前现状,同时介绍Python的现代开发方法。本章主要包括以下内容。

·如何保持Python 2和Python 3之间的兼容性。

·为了开发的顺利进行,在应用层面和操作系统层面如何解决开发环境隔离的问题。

·如何增强Python提示符的功能。

·如何使用pip安装Python包。

每本书的开头都要来点开胃小菜。如果你对Python已经很熟悉了(特别是最新的3.x版本),并且掌握了开发中做环境隔离的正确方法,你可以跳过本章的前两节,快速阅读其他小节即可。其他小节会讲到一些工具和资源,它们并非必不可少,但可以大大提高Python开发效率。不过一定要读一下关于应用层环境隔离和 pip的一节,因为这一节提到的工具会在本书后面的内容中用到。1.1 Python的现状与未来

Python的历史最早可追溯到20世纪80年代末,但是1.0版的发行时间是在1994年,所以Python并不是一门非常年轻的语言。这里本该介绍Python主要版本发布的整个时间线,但其实真正重要的日期只有一个:2008年12月3日,也就是Python 3.0的发布日期。

在写作本书时,Python 3的首次发布已经过去了7年。PEP 404也已经创建了4年,PEP404是“取消发布"(un-release)Python 2.8并正式关闭Python 2.x分支的官方文档。虽然过去了这么长的时间,Python社区中依然存在明显的分歧。语言本身在迅速发展,但大量用户却并不想更新版本。1.2 Python升级及其原因

原因很简单。Python升级是因为有这样的需求。语言之间的竞争随时都在上演。每隔几个月都会突然冒出一门新语言,声称解决了之前所有语言中存在的问题。对于大多数类似的项目,开发人员很快就会失去兴趣,它们的名气也只是一时炒作。

不管怎样,这也表示存在着更严重的问题。人们之所以设计新的编程语言,是因为他们发现现有的语言无法以最佳方式来解决问题。认识不到这样的需求是目光短浅的。此外, Python的使用范围也越来越广泛,人们发现它有许多可以改进的地方,也应该做出这样的改进。

Python的很多改进往往是由特定应用领域的需求驱动的。其中最重要的领域是Web开发,这一领域需要Python改进对并发的处理。

有些变化只是由于Python项目的历史原因导致的。这些年已经发现了 Python 的一些不合理之处,有些是标准库模块结构混乱或冗余,有些是程序设计缺陷。最初,发布Python 3是要对这门语言进行较大的清理与更新,但结果显示,这个计划并没有收到预期的效果。在很长一段时间内,很多开发人员对Python 3只是抱着好奇的态度而已,但希望这种情形正在好转。1.3 追踪Python最新变化——PEP文档

Python社区有一种应对变化的固定方法。虽然各种各样的Python语言修改意见主要在邮件列表(python-ideas@python.org)中进行讨论,但只有发布了名为PEP的新文档,新的变化才会生效。PEP的全称是Python改进提案(Python Enhancement Proposal, PEP)。它是提交Python变化的书面文档,也是社区对这一变化进行讨论的出发点。这些文档的整个目的、格式和工作流程的标准格式也都包含在一份Python改进提案中,也就是PEP 1文档(http://www.python.org/dev/peps/pep-0001)。

PEP文档对Python的作用十分重要,根据讨论的主题,PEP主要有以下3种用途。

·通知:汇总Python核心开发者需要的信息,并通知Python发布日程。

·标准化:提供代码风格、文档或其他指导意见。

·设计:对提交的功能进行说明。

所有提交过的PEP都被汇总在一个文档中,就是PEP 0(https://www.python.org/dev/peps/)。由于这些 PEP 都在同一个网站上很容易找到,其URL也很容易猜到,因此本书一般用编号来指代这些文档。

如果你对 Python 语言的未来发展方向感兴趣,但又没时间跟踪 Python 邮件列表中的讨论,那么PEP 0会是很好的信息来源。它会告诉你,哪些文档已被接受但尚未实施,哪些文档仍在审议中。

PEP还有其他的用途。人们通常会问这样的问题:

·A功能为什么要以这样的方式运行?

·Python为什么没有B功能?

大多数情况下,关于该功能的某个PEP文档已经给出了上述问题的详细回答。很多提交的关于Python语言功能的PEP文档并没有通过。这些文档可作为历史资料来参考。1.4 当前Python 3的普及程度

Python 3有许多强大的新功能,那么它在社区中广泛普及了吗?遗憾的是,并没有。有一个著名的网站叫“Python 3荣耀之墙(Python 3 Wall of Superpowers)”,里面记录了大多数常用软件包与 Python 3 的兼容性,不久前这个网站刚刚改名为“Python 3 耻辱之墙(Python 3 Wall of Shame)”。目前这种状况正在逐步改善,上述网站的软件包列表中绿色的比例也在每月缓慢增加[1]。尽管如此,但这并不代表很快所有应用开发团队都只使用Python 3。当所有常用软件包都支持Python 3时,“我们所用的软件包还没有迁移到Python 3”这一常用借口将不再适用。

造成目前这种状况的主要原因是,将现有应用从Python 2迁移到Python 3上总是一项不小的挑战。像2to3之类的工具可以进行代码自动转换,但无法保证转换后的代码100%正确。而且,如果不做人工修改的话,转换后的代码性能可能不如转换前。将现有的复杂代码库迁移到Python 3上可能需要付出巨大的精力和成本,某些公司可能无法负担这些成本。但这些成本可以分割成小份来逐步完成。一些优秀的软件架构设计方法可以帮助其逐步实现这一目标,如面向服务的架构或者微服务。新的项目组件(服务或微服务)可以用新方法编写,现有的项目组件可以逐步迁移。

长远来看,将项目迁移到Python 3只有好处。根据PEP-404这份文档,Python 2.x分支将不会发布2.8 版本。而且未来所有重要的项目(如Django、Flask和NumPy)可能都将放弃2.x的兼容性,仅支持Python 3。

我个人对这个问题的观点可能会引发争议。我认为在创建新的软件包时,最好鼓励社区完全放弃支持Python 2。当然,这一做法极大地限制了这些软件的适用范围,但对于那些坚持使用Python 2.x的人来说,这可能是改变他们想法的唯一方法。1.5 Python 3和Python 2的主要差异

前面已经说过,Python 3打破了对Python 2的向后兼容。但它并不是完全重新设计的。而且,也并不是说2.x版本的Python模块在Python 3下都无法运行。代码可以完全跨版本兼容,无需其他工具或技术在两大版本上都可以运行,但一般只有简单应用才能做到这一点。1.5.1 为什么要关注这些差异

本章前面说过我个人对Python 2兼容性的看法,但是目前不可能完全忽视这一点。还有一些Python包(例如第6章将讲到的fabric)十分实用,但可能短期内不会迁移到Python 3。

另外,有时我们还会受到所在公司的制约。现有的遗留代码可能非常复杂,迁移代码的费用难以承受。所以即使我们现在决定只用Python 3,短期内也不可能完全放弃Python 2。

如今想要自称专业开发者,没有对社区的回馈是说不过去的,所以帮助开源软件开发者向现有软件包中添加对Python 3的兼容,可以很好地偿还在使用这些软件包时产生的“道德债(moral debt)”。当然,不了解Python 2和Python 3的差异是无法做到这一点的。顺便提一下,对于Python 3新手来说,这也是一项很好的练习。1.5.2 主要的语法差异和常见陷阱

要比较不同版本之间的差异,最好的参考资料就是Python文档。不过为了方便读者,本节总结了其中最重要的内容。但不熟悉Python 3的读者还是要去阅读官方文档。

Python 3引入的重要差异一般可分为以下几个方面。

·语法变化,删除/修改了一些语法元素,并添加了一些新的语法元素。

·标准库中的变化。

·数据类型与集合的变化。

1.语法变化

有些语法变化会导致当前代码无法运行,这些变化是最容易发现的,它们会导致代码根本无法运行。包含新语法元素的Python 3代码在Python 2中无法运行,反之亦然。由于删除了某些元素,导致Python 2代码显然无法与Python 3兼容。运行有这些问题的代码时,解释器很快就会抛出SyntaxError异常。下面是一个无法运行的脚本示例,只包含两个语句,都会引发语法错误而无法运行:

print("hello world")

print "goodbye python2"

上述代码在Python 3中的实际运行结果如下:

$ python3 script.py

File "script.py",line 2

print "goodbye python2"

^

SyntaxError: Missing parentheses in call to 'print'

列出所有的语法差异会比较长,而且Python 3.x的新版本也会不时添加新的语法元素,在较早版本的Python中就会引发错误(即使在相同的3.x版本上也会报错)。其中最重要的语法差异将会在第2章和第3章中讲到,所以这里无需全部列出。

与Python 2.7相比,删除或改动的内容要相对少一些,下面给出最重要的变化内容。

·print不再是一条语句而是一个函数,所以必须加上括号。

·捕获异常的语法由except exc,var改为except exc as var。

·弃用比较运算符<>,改用!=。

·from module import *(https://docs.python.org/3.0/reference/simple_stmts.html#import)现在只能用于模块,不能用在函数中。

·现在from .[module] import name是相对导入的唯一正确的语法。所有不以点字符开头的导入都被当作绝对导入。

·sorted函数与列表的sort方法不再接受cmp参数,应该用key参数来代替。

·整数除法表达式(如1/2)返回的是浮点数。取整运算可以用//运算符,如1//2。这样做的好处是浮点数也可以用这个运算符,所以5.0//2.0 == 2.0。

2.标准库中的变化

语法变化很容易发现,标准库中的重大变化也是非常容易发现的。Python的每个后续版本都会向标准库模块中添加、弃用、改进或完全删除某些内容。在旧版 Python(1.x 和2.x)中也会定期有这样的变化,所以出现在Python 3中并不让人吃惊。大多数情况下,对于删除或重组的模块(例如urlparse移到了urllib.parse),在运行解释器时会对导入语句抛出异常。这样的问题很容易发现。无论如何,为了确保能够发现所有类似的问题,完整的代码测试覆盖率是必不可少的。在某些情况下(例如使用延迟加载模块时),这个通常在全局导入时出现的问题并不会出现,直到在代码中将某些模块作为函数调用时才会出现。因此,在测试期间确保每行代码都要实际运行是很重要的。

延迟加载模块

延迟加载模块是指在全局导入时并不加载的模块。在Python中,import语句可以包含在函数内部,这样导入是在函数调用时才会发生,而不是在全局导入时发生。在某些情况下,模块的这种加载方式可能比较合理,但大多数情况下,这只是对设计不佳的模块结构的变通方法(例如避免循环导入),通常应避免这种加载方式。当然,对于标准库模块来说,没有理由使用延迟加载。

3.数据类型与集合的变化

开发人员在努力保持兼容性或只是将现有代码迁移到 Python 3 上时,需要特别注意Python中数据类型与集合的表示方式的变化。虽然不兼容的语法变化或标准库变化很容易发现,也很容易修复,但集合与数据类型的变化要么难以察觉,要么需要大量的重复工作。这样的变化列表会很长,再次重申,官方文档是最好的参考资料。

不过,这一节必须讲一下Python 3中字符串处理方式的变化,因为这是Python 3中最具争议也是讨论最多的变化,尽管这是一件好事,使很多问题变得更加明确。

现在所有字符串都是Unicode,字节(bytes)需要加一个b或B的前缀。Python 3.0和3.1不支持使用u前缀(例如u"foo"),使用的话会引发语法错误。不支持这个前缀是引发所有争议的主要原因。这导致难以编写能够兼容 Python 不同分支的代码,2.x 版需要用这个前缀来创建Unicode。Python 3.3又恢复了这个前缀,虽然没有任何语法上的意义,只是为了简化兼容过程。1.5.3 用于保持跨版本兼容性的常用工具和技术

在Python不同版本之间保持兼容性是一项挑战。根据项目的大小不同,这项挑战可能会增加许多额外的工作量,但绝对可行,也很值得去做。对于在许多环境中都会用到的Python包来说,必须要保持跨版本兼容性。如果开源包没有定义明确并经过测试的兼容范围(compatibility bound),是不太可能流行起来的。而且,对于只在公司网络封闭使用的第三方代码来说,也可以大大受益于在不同环境中的测试。

这里应该注意,虽然这一部分内容主要关注Python不同版本之间的兼容,但这些方法也适用于保持与外部依赖项之间的兼容,外部依赖项包括不同的包版本、二进制库、系统或外部服务等。

整个过程主要分为3个部分,按重要性排序如下。

·定义并记录目标兼容范围的及其管理方法。

·在每个环境中进行测试,并对每个兼容的依赖版本进行测试。

·实现实际的兼容代码。

告知兼容范围是整个过程中最重要的一部分,因为这可以让代码使用者(开发人员)对代码的工作原理和未来的变化方式有一定的预期和假设。我们的代码可能用于多个不同项目的依赖,这些项目也在努力管理兼容性,所以把代码兼容性说清楚还是很重要的。

本书总是尽量给出几个选择,而不会强烈推荐某个特定选项,而这里是少数几个例外之一。目前来看,管理兼容性未来变化的最佳方法,就是正确使用语义化版本(Semantic Versioning semver)的版本号。它是一个广为接受的标准,用仅包含3个数字的版本标识符来标记代码的变化范围。它还给出了如何处理弃用的方法建议。下面是摘录semver官网的摘要。

版本格式:主版本号.次版本号.修订号,版本号递增规则如下。

·主版本号(MAJOR):当你做了不兼容的API修改。

·次版本号(MINOR):当你做了向后兼容的功能性新增。

·修订号(PATCH):当你做了向后兼容的问题修正。

先行版本号及版本编译信息可以加到“主版本号.次版本号.修订号”的后面,作为延伸。

测试时就会发现一个悲伤的事实,为了保证代码与每个依赖版本和每个环境(这里环境指的是Python版本)都保持兼容,必须在所有可能的组合中对代码进行测试。当然,如果项目的依赖很多,做到这一点基本是不可能的,因为随着依赖版本数目的增加,组合的数目也会迅速增加。因此,通常需要做一些权衡,使得运行所有兼容性测试无需花费数年的时间。第10章中介绍一般的测试,里面也介绍了所谓的矩阵测试中工具的选择。

项目遵循semver的好处在于,通常只有主版本才需要测试,因为次版本和修订版本中保证没有向后不兼容的变化。只有项目不违背这样的约定,这种说法才能成立。不幸的是,每个人都会犯错,许多项目中都出现了后向不兼容的变化,甚至在修订版本中也出现了这种变化。尽管如此,由于semver声称对次版本和修订版本的变化保持严格的向后兼容,那么打破这个规则就可以视为bug,可以在修订版本中进行修复。

如果明确定义了兼容范围并严格测试,那么实现兼容层就是最后一步,也是最不重要的一步。但是,每一位对这个话题感兴趣的程序员都应该知道下列工具和技术。

最基本的就是Python的__future__模块。它将Python新版本中的一些功能反向迁移到旧版本中,采用的是导入语句的形式:

from __future__ import

future 语句提供的功能是和语法相关的元素,其他方法很难处理这些元素。这个语句只能影响它所在的模块。下面是Python 2.7交互式会话的实例,从Python 3.0中引入Unicode:

Python 2.7.10 (default,May 23 2015,09:40:32) [MSC v.1500 32 bit (Intel)] on win32

Type "help","copyright","credits" or "license" for more

information.

>>> type("foo") # 旧的字面值

>>> from __future__ import unicode_literals

>>> type("foo") # 现在变成了unicode

下面列出了所有可用的__future__语句,关注2/3兼容性的开发者都应该知道。

·division:Python 3新增的除法运算符(PEP 238)。

·absolute_import:将所有不以点字符开头的import语句格式解释为绝对导入(PEP 328)。

·print_function:将print语句变为函数调用,所以在print后面必须加括号(PEP 3112)。

·unicode_literals:将每个字符串解释为Unicode(PEP 3112)。

__future__中的可选语句列表很短,只包含几个语法功能。对于其他变化的内容,例如元类语法(第3章会讲到这一高级特性),维持其兼容性则困难得多。future语句也无法完全解决多个标准库重组的问题。幸运的是,有些工具旨在提供一致可用的兼容层。最有名的就是Six模块,提供了常用的2/3兼容性的整个样板。另一个很有前途但名气稍逊的工具是future模块。

在某些情况下,开发人员可能不想在一些小型Python包里添加其他依赖项。通常的做法是将所有兼容性代码放在一个附加模块中,该模块通常命名为compat.py。下面是来自python-gmaps项目的compat模块实例:

# -*- coding: utf-8 -*-

import sys

if sys.version_info < (3,0,0):

import urlparse # noqa

def is_string(s):

return isinstance(s,basestring)

else:

from urllib import parse as urlparse # noqa

def is_string(s):

return isinstance(s,str)

这样的compat.py模块十分常见,即使是利用Six保持2/3兼容性的项目也很常见,因为这种方法非常方便,用于保存在不同版本的依赖包之间保持兼容性的代码。

下载示例代码

你可以用自己的账号在Packt的官方网站下载本书的示例代码文件。如果你是在其他地方购买的本书,你可以访问Packt的官方网站并注册,文件会直接通过邮件发送给你。

下载代码文件的步骤如下。

·用你的电子邮件地址和密码登录或注册我们的网站。

·将鼠标指针悬停在顶部的SUPPORT选项卡上。

·单击Code Downloads & Errata。

·在Search框中输入本书的名字。

·选择你要下载代码文件的书籍。

·从下拉菜单中选择本书的购买途径。

·单击Code Download。

文件下载完成后,请确保用下列软件的最新版本对文件夹进行解压或提取。

·在Windows上用WinRAR或7-Zip。

·在Mac上用Zipeg、iZip或UnRarX。

·在Linux上用7-Zip或PeaZip。

本书的代码包也托管在GitHub,网址为https://github.com/PacktPublishing/Expert-Python-Programming_Second-Edition。在GitHub上还有大量图书和视频资源。去看一下吧!1.6 不只是CPython

最重要的Python实现是用C语言编写的,叫作CPython。大多数人在讨论Python时指的都是 CPython。随着语言的进化,C 语言实现也相应发生变化。除了 C 之外,Python还有其他几种实现方式,这些实现方式都在努力地跟上主流。大多数实现方式的时间表都要落后于CPython,但它们提供了一个好机会,可以在具体环境中使用并推广Python语言。1.6.1 为什么要关注Python实现

Python实现有许多种。在Python官网上关于这一话题的维基百科页面中,主要介绍了20多种语言变体、方言或除C语言之外的Python解释器实现。其中一些只是实现了语言核心语法、功能和内置扩展的一个子集,但至少有几个与CPython几乎完全兼容。最重要的是,虽然其中一些只是玩具项目或实验,但大部分都是为了解决某些实际问题而创建的,这些问题要么是用CPython无法解决,要么需要开发人员花费巨大的精力。这些问题的实例包括如下几个。

·在嵌入式系统中运行Python代码。

·与运行框架(如Java或.NET)或其他语言做代码集成。

·在Web浏览器中运行Python代码。

本节将简要介绍目前Python开发人员可用的最流行和最新的Python实现。1.6.2 Stackless Python

Stackless Python自称Python增强版。之所以名为Stackless(无栈),是因为它没有依赖C语言的调用栈。它实际上是修改过的CPython代码,还添加了一些新的功能,在创建Stackless Python 时 Python 核心实现中还没有这些功能。其中最重要的功能就是由解释器管理的微线程,用来替代依赖系统内核上下文切换和任务调度的普通线程,既轻量化又节约资源。

Stackless Python最新可用的版本是2.7.9和3.3.5,分别实现的是Python 2.7和3.3。在Stackless Python中,所有的额外功能都是内置stackless模块内的框架。

Stackless Python并不是最有名的Python实现,但很值得一提,因为它引入的思想对编程语言社区有很大的影响。将Stackless Python中的内核切换功能提取出来并作为一个独立包发布,名为greenlet,现在是许多有用的库和框架的基础。此外,它的大部分功能都在PyPy中重新实现,PyPy是另一个Python实现,我们将稍后介绍。1.6.3 Jython

Jython是Python语言的Java实现。它将代码编译为Java字节代码,开发人员在Python模块中可以无缝使用Java类。Jython允许人们在复杂应用系统(例如J2EE)中使用Python作为顶层脚本语言,它还将Java应用引入到Python世界中。Jython的一个很好的例子就是,在Python程序中可以使用Apache Jackrabbit(这是一个基于JCR的文档仓库API。

Jython最新可用的版本是Jython 2.7,对应的是Python 2.7版。它宣称几乎实现了Python所有的核心标准库,并使用相同的回归测试套件。Jython 3.x版正在开发中。

Jython与CPython实现的主要区别如下所示。

·真正的Java垃圾回收,而不是引用计数。

·没有全局解释器锁(Global Interpreter Lock,GIL),在多线程应用中可以充分利用多个内核。

这一语言实现的主要缺点是缺少对C/Python扩展API的支持,因此用C语言编写的Python扩展在Jython中无法运行。这种情况未来可能会发生改变,因为Jython 3.x计划支持C/Python扩展API。

某些Python Web框架(例如Pylons)被认为是促进Jython的开发,使其可用于Java世界。1.6.4 IronPython

IronPython将Python引入.NET框架中。这个项目受到微软的支持,IronPython的主要开发人员都在微软工作。它是推广语言的一种重要实现。除了Java,.NET社区是最大的开发者社区之一。还值得注意的是,微软提供了一套免费开发工具,可以将Visual Studio转换为成熟的Python IDE。这是作为Visual Studio的插件发布的,名为PTVS(Python Tools for Visual Studio,用于Visual Studio的Python工具),在GitHub可以找到其开源代码。

最新的稳定版本是2.7.5,与Python 2.7兼容。与Jython类似,Python 3.x的实现也在开发中,但还没有可用的稳定版本。虽然.NET 主要在微软 Windows 系统上运行,但是IronPython也可以在Mac OS X和Linux系统上运行。这一点要感谢Mono,一个跨平台的开源.NET实现。

与CPython相比,IronPython的主要区别或优点如下。

·与Jython类似,没有全局解释器锁(Global Interpreter Lock,GIL),在多线程应用中可以充分利用多个内核。

·用C#和其他.NET语言编写的代码可以轻松集成到IronPython中,反之亦然。

·通过Silverlight,在所有主流Web浏览器中都可以运行。

说到弱点,IronPython也与Jython非常类似,因为它也不支持C/Python扩展API。对于想要使用主要基于C扩展的Python包(例如NumPy)的开发人员来说,这一点是很重要的。有一个叫作ironclad的项目,其目的是在IronPython中无缝使用这些扩展,虽然它最新支持的版本是2.6,开发似乎也停止了。1.6.5 PyPy

PyPy可能是最令人兴奋的Python实现,因为其目标就是将Python重写为Python。在PyPy中,Python解释器本身是用Python编写的。在Python的CPython实现中,有一个C代码层来实现具体细节。但在PyPy实现中,这个C代码层用Python完全重写。

这样你可以在代码运行期间改变解释器的行为,并实现 CPython 难以实现的代码模式。

目前PyPy的目的是与Python 2.7完全兼容,而PyPy3则与Python 3.2.5版兼容。

以前对PyPy感兴趣主要是理论上的原因,只有喜欢深入钻研语言细节的人才会对它感兴趣。它通常不用于生产环境,但这些年来这种状况已经发生改变。现在许多基准测试给出惊人的结果,PyPy通常比CPython实现要快得多。这个项目有自己的基准测试网站,记录了用数十种不同的基准测试对每一版本性能的测量结果(参见http://speed.pypy.org/)。网站清晰地显示,启用JIT的PyPy至少比CPython要快好几倍。由于PyPy的这一特性以及其他特性,使得越来越多的开发人员决定在生产环境中切换到PyPy。

PyPy与CPython实现的主要区别在于以下几个方面。

·使用垃圾回收,而不是引用计数。

·集成跟踪JIT编译器,可以显著提高性能。

·借鉴了Stackless Python在应用层的无栈特性。

与几乎所有其他的Python实现类似,PyPy也缺乏对C/Python扩展API的完全官方支持。但它至少通过CPyExt子系统为C扩展提供了某种程度的支持,虽然文档不完整,功能也尚未完善。此外,社区正在努力将NumPy迁移到PyPy中,因为这是最需要的功能。1.7 Python开发的现代方法

作为专家,最重要的是要对所选用的编程语言有深刻的理解。对于任何技术来说都是如此。但如果不知道在特定语言社区中的常用工具和实践的话,想开发一款好软件是相当困难的。Python所有的单项功能都可以在其他某种语言中找到。所以,直接比较语法、表现力(expressiveness)或性能的话,总会在一个或多个方面存在更好的解决方案。但Python真正出众的领域在于围绕语言打造的整个生态系统。多年来,Python社区完善了标准实践和标准库,有助于在更短的时间内创建更可靠的软件。

对于上文提到的生态系统,最明显也最重要的一部分就是大量免费的开源包,可以用来解决许多问题。编写新软件总是一个费钱又费时的过程。能够复用现有代码而无需重新造轮子(reinvent the wheel),可以大大降低开发的时间和成本。这也是某些公司的项目在经济上可行的唯一原因。

由于这个原因,Python 开发者花费大量精力来创建工具和标准,方便使用他人创建的开源包。我们首先介绍虚拟隔离环境、改进的交互式 shell 和调试器,然后介绍一些程序,有助于发现、搜索和分析PyPI(Python Package Index,Python包索引)上大量可用的Python包。1.8 应用层Python环境隔离

现在许多操作系统都将 Python 作为标准组件。对于大多数 Linux 发行版和基于 Unix的系统(如FreeBSD、NetBSD、OpenBSD或OS X系统)来说,要么默认安装了Python,要么系统软件包仓库中包含Python。其中很多系统甚至将Python作为核心组件的一部分。有些操作系统的安装程序是用Python编写的,例如Ubuntu系统的Ubiquity、Red Hat Linux和Fedora系统的Anaconda。

基于这一事实,PyPI 上的许多包也可以用系统包管理工具(如 Debian 和 Ubuntu 的apt-get、Red Hat Linux的rpm、Gentoo的emerge)作为本地包来管理。不过应该记住,可用的库非常有限,大部分也比 PyPI 上的版本要旧。因此,PyPA(Python Packaging Authority,Python 包官方小组)推荐始终采用 pip 来获取最新版本的 Python 包。虽然从CPython 2.7.9版和3.4版开始,pip已经成为一个独立的Python包,但每一个新版本都会默认安装pip。安装新Python包的方法就是这么简单,如下所示:

pip install

pip 功能十分强大,可以强制安装特定版本的 Python 包(语法为 pip install package-name==version),或升级到最新可用的版本(使用--upgrade参数)。对于本书中提到的大多数命令行工具来说,在命令后添加-h或--help参数并运行可以轻松获得其完整的用法说明,但下面给出一个示例会话,展示其最常用的选项:

$ pip show pip

---

Metadata-Version: 2.0

Name: pip

Version: 7.1.2

Summary: The PyPA recommended tool for installing Python packages.

Home-page: https://pip.pypa.io/

Author: The pip developers

Author-email: python-virtualenv@groups.google.com

License: MIT

Location: /usr/lib/python2.7/site-packages

Requires:

$ pip install 'pip<7.0.0'

Collecting pip<7.0.0

Downloading pip-6.1.1-py2.py3-none-any.whl (1.1MB)

100% |████████████████████████████████| 1.1MB 242kB/s

Installing collected packages: pip

Found existing installation: pip 7.1.2

Uninstalling pip-7.1.2:

Successfully uninstalled pip-7.1.2

Successfully installed pip-6.1.1

You are using pip version 6.1.1,however version 7.1.2 is available.

You should consider upgrading via the 'pip install --upgrade pip'

command.

$ pip install --upgrade pip

You are using pip version 6.1.1,however version 7.1.2 is available.

You should consider upgrading via the 'pip install --upgrade pip'

command.

Collecting pip

Using cached pip-7.1.2-py2.py3-none-any.whl

Installing collected packages: pip

Found existing installation: pip 6.1.1

Uninstalling pip-6.1.1:

Successfully uninstalled pip-6.1.1

Successfully installed pip-7.1.2

在某些情况下,可能默认pip不可用。从Python 3.4版和2.7.9版开始,总是可以使用ensurepip模块来引导启动pip,具体如下:

$ python -m ensurepip

Ignoring indexes: https://pypi.python.org/simple

Requirement already satisfied (use --upgrade to upgrade): setuptools in /usr/lib/python2.7/site-packages

Collecting pip

Installing collected packages: pip

Successfully installed pip-6.1.1

关于在旧版Python中如何安装pip的方法,访问项目的文档页面可获取最新信息。1.8.1 为什么要隔离

pip可用于安装系统级的Python包。在基于Unix的系统和Linux系统上,这么做需要超级用户权限,所以实际的调用如下所示:

sudo pip install

注意,在 Windows 上并不需要这样做,因为没有默认安装 Python 解释器,Windows上的Python通常由用户手动安装,无需超级用户权限。

无论如何,不推荐直接从PyPI安装系统级的Python包,也应尽量避免这一做法。前面说 PyPA 推荐使用 pip,这似乎与前面的说法相矛盾,但其中是有很重要的原因。如前所述,通过操作系统软件包仓库,Python往往是许多软件包的重要组成部分,也可以提供许多重要服务。系统发行版的维护者投入大量精力选择合适的软件包版本,以匹配各种包依赖。通常来说,系统软件包仓库中的Python包都包含自定义补丁,或者使用较旧的版本,只是为了保证与其他系统组件的兼容。利用pip将这些Python包强制更新至某一版本,打破了向后兼容,也可能会破坏某些关键的系统服务。

即使在本地计算机上,为了方便开发而做这些事情也不是一个好的理由。那样胡乱使用pip几乎总会引起麻烦,最终导致难以调试的问题。并不是说要严格禁止从PyPI全局安装Python包,但这么做时一定要清楚地认识到相关风险。

幸运的是,这个问题有一个简单的解决方案,就是环境隔离。在

试读结束[说明:试读内容隐藏了图片]

下载完整电子书


相关推荐

最新文章


© 2020 txtepub下载