DDR爱好者之家 Design By 杰米

译者按:原文写于2011年末,虽然文中关于Python 3的一些说法可以说已经不成立了,但是作为一篇面向从其他语言转型到Python的程序员来说,本文对Python的生态系统还是做了较为全面的介绍。文中提到了一些第三方库,但是Python社区中强大的第三方库并不止这些,欢迎各位Pytonistas补充。

"http://learnpythonthehardway.org/">《笨办法学Python》,这是本质量很高的免费电子书,看完之后再回头阅读这篇教程吧。

我假设你们使用的是Linux(最好是Ubuntu/Debian)或是类Linux操作系统。为什么?因为这是我最熟悉的系统。我在Windows平台或Mac OS X平台上,没有专业的编程经验,只是测试过不同浏览器的兼容性。如果你用的是这两个平台,那么请参考下面的资料安装Python。

  • Python 101: Setting up Python on Windows
  • Official documentation for Python on Windows
  • Official documentation for Python on Mac OS X

你还可使用搜索引擎,查找你使用的操作系统中安装Python的最好方法。如果你有什么疑问,我强烈建议你去Stack Overflow平台上提问。

该选择哪个版本?

Python 2.x是目前的主流;Python 3是崭新的未来。如果你不关心这个问题,可以直接跳到下面的Python安装部分。(译者注:原文作者写这篇文章时是2011年,当时Python 3才发展没几年。)

刚接触Python的话,安装3.x版本看上去是很自然的第一步,但是这可能并不是你想要的。

目前有两个积极开发中的Python版本——2.7.x与3.x(也被称为Python 3, Py3K和Python 3000)。Python 3是一个不同于Python 2的语言。二者在语义、语法上,既存在细微的区别,又有着截然不同的一面。截至今天,Python2.6/2.7是安装数量和使用度最高的版本。许多主流的Python库、框架、工具都没有做到100%兼容Python 3。

因此,最稳妥的选择就是使用2.x版(更准确的说,即2.7.x)。务必只在你需要或者完全了解情况的前提下,才选择Python 3。

Python 3 Wall of Shame网站记录了Python 3对各种库的兼容情况。在使用Python 3之前,仔细查阅下这个网站的内容。

译者注:现在,主流第三方库和框架对Python 3的支持度已经很高。根据py3readiness网站的统计,360个最受欢迎的Python包中已经有315个支持Python 3。具体的支持情况,可以查看这个网站。一定程度上说,Python 3已经成为新的主流。

使用哪种虚拟机

Python的解释器,又叫做Python虚拟机,它有多种不同的实现。其中,主流实现方式是CPython,装机量也最高,同时也是其他虚拟机的参考实现。

PyPy是利用Python语言实现的Python;Jython则使用Java实现,并运行在Java虚拟机之上;IronPython是用.NET CLR实现的Python。

除非真的有重大理由,否则应该选择CPython版本的实现,避免出现意外情况。

如果这些有关版本和虚拟机的唠叨话让你读了头疼,那你只需要使用CPython 2.7.x即可。

Python安装

大部分Linux/Unix发行版和Mac OS X都预装了Python。如果你没有安装或者已有的版本比较旧,那么你可以通过下面的命令安装2.7.x版:

Ubuntu/Debian及其衍生系统

复制代码 代码如下:
$ sudo apt-get install python2.7

sudo是类Unix系统中的一个程序,可以让用户以其他用户的权限(通常是超级用户或root用户)运行程序。

Fedora/Red Hat及类似系统

sudo yum install python2.7


在RHEL(Red Hat Enterprise Linux的缩写)平台上,你可能需要启用EPEL软件源(repositories),才能正常安装。

在本文后面的示例中,我会使用sudo程序;你应将其替换为自己版本中的相应命令或程序。

理解Python的包(package)

首先你需要了解的是,Python没有默认的包管理工具。事实上,Python语言中包的概念,也是十分松散的。

你可能也知道,Python代码按照模块(module)划分。一个模块,可以是只有一个函数的单个文件,也可以是包含一个或多个子模块的文件夹。包与模块之间的区别非常小,每个模块同时也可以视作一个包。

那么模块与包之间,到底有什么区别?要想解答这个问题,你首先要了解Python是如何查找模块的。

与其他编程环境类似,Python中也有一些函数和类(比如str,len和Exception)是存在于全局作用域(global scope,在Python中被称为builtin scope)的,其他的函数和类则需要通过import语句进行引用。例如:

复制代码 代码如下:
> import os
> from os.path import basename, dirname

这些包就在你的文件系统中的某处,所以能被import语句发现。那么Python是怎么知道这些模块的地址?原来,在你安装Python虚拟机的时候,就自动设置了这些地址。当然平台不同,这些地址也就不一样。

你可以通过sys.path查看系统中的包路径。这是我的笔记本运行该命令之后的输出结果,系统是Ubuntu 11.10 Oneric Ocelot。

> import sys
> print sys.path
['',
 '/usr/lib/python2.7',
 '/usr/lib/python2.7/plat-linux2',
 '/usr/lib/python2.7/lib-tk',
 '/usr/lib/python2.7/lib-old',
 '/usr/lib/python2.7/lib-dynload',
 '/usr/local/lib/python2.7/dist-packages',
 '/usr/lib/python2.7/dist-packages',
 '/usr/lib/python2.7/dist-packages/PIL',
 '/usr/lib/python2.7/dist-packages/gst-0.10',
 '/usr/lib/python2.7/dist-packages/gtk-2.0',
 '/usr/lib/pymodules/python2.7',
 '/usr/lib/python2.7/dist-packages/ubuntu-sso-client',
 '/usr/lib/python2.7/dist-packages/ubuntuone-client',
 '/usr/lib/python2.7/dist-packages/ubuntuone-control-panel',
 '/usr/lib/python2.7/dist-packages/ubuntuone-couch',
 '/usr/lib/python2.7/dist-packages/ubuntuone-installer',
 '/usr/lib/python2.7/dist-packages/ubuntuone-storage-protocol']

这行代码会告诉你Python搜索指定包的所有路径,这个路径就存储在一个Python列表数据类型中。它会先从第一个路径开始,一直往下检索,直到找到匹配的路径名。这意味着,如果两个不同的文件夹中包含了两个同名的包,那么包检索将会返回其遇到的第一个绝对匹配地址,不会再继续检索下去。

你现在可能也猜到了,我们可以轻松地修改(hack)包检索路径,做到你指定的包第一个被发现。你只需要运行下面的代码:

> sys.path.insert(0, '/path/to/my/packages')

尽管这种做法在很多情况下十分有用,但是你必须牢记sys.path很容易被滥用。务必在必要时才使用这种方法,并且不要滥用。

site模块控制着包检索路径设置的方法。每次Python虚拟机初始化时,就会被自动引用。如果你想更详细地了解整个过程,可以查阅官方文档。

PYTHONPATH环境变量

PYTHONPATH是一个可以用来增强默认包检索路径的环境变量。可以把它看作是一个PATH变量,但是一个只针对Python的变量。它只是一些包含有Python模块的文件路径列表(不是sys.path所返回的Python列表),每个路径之间以:分隔。设置方法很简单,如下:

复制代码 代码如下:
export PYTHONPATH=/path/to/some/directory:/path/to/another/directory:/path/to/yet/another/directory

在某些情况下,你不用覆盖已有的PYTHONPATH,只需要在开头或结尾加上新的路径即可。

复制代码 代码如下:
export PYTHONPATH=$PYTHONPATH:/path/to/some/directory    # Append
export PYTHONPATH=/path/to/some/directory:$PYTHONPATH    # Prepend

PYTHONPATH、sys.path.insert`和其他类似的方法,都是hack小技巧,一般情况下最好不要使用。如果它们能够解决本地开发环境出现的问题,可以使用,但是你的生产环境中不应该依赖这些技巧。要取得同样的效果,我们还可以找到更加优雅的方法,稍后我会详细介绍。

现在你明白了Python如何查找已安装的包,我们就可以回到一开始的那个问题了。Python中,模块和包的区别到底是什么?包就是一个或多个模块/子模块的集合,一般都是以经过压缩的tarball文件形式传输,这个文件中包含了:1. 依赖情况(如果有的话);2.将文件复制到标准的包检索路径的说明;3. 编译说明——如果文件中包含了必须要经过编译才能安装的代码。就是这点区别。

第三方包(Third Party packages)

如果想利用Python进行真正的编程工作,你从一开始就需要根据不同的任务安装第三方包。

在Linux系统上,至少有3种安装第三方包的方法。

  1. 使用系统本身自带的包管理器(deb, rpm等)
  2. 通过社区开发的类似pip, easy_install等多种工具
  3. 从源文件安装

这三种方法做的几乎是同一件事情,即安装依赖包,视情况编译代码,然后把包中模块复制到标准包检索路径。

尽管第二种和第三种方法在所有操作系统中的实现都一致,我还是要再次建议你查阅Stack Overflow网站的问答,找到你所使用系统中其他安装第三方包的方法。

去哪找第三方包?

在安装第三方包之前,你得先找到它们。查找包的方法有很多。

  1. 你使用的系统自带的包管理器
  2. Python包索引(也被称为PyPI)
  3. 各种源码托管服务,如Launchpad, Github, Bitbucket等。

通过系统自带的包管理器安装

使用系统自带的包管理器安装,只需要在命令行输入相应命令,或是使用你用来安装其他应用的GUI应用即可。举个例子,要在Ubuntu系统上安装simplejson(一个JSON解析工具),你可以输入下面的命令:

$ sudo apt-get install python-simplejson


通过pip安装

easy_install已经不太受开发者欢迎。本文将重点介绍easy_install的替代者——pip

pip是一个用来安装和管理Python包的工具。它并不是一个Python虚拟机自带的模块,所以我们需要先安装。在Linux系统中,我一般会这样操作:

$ sudo apt-get install python-pip

在安装其他包之前,我总是会把pip升级到PyPI中的最新版本,因为Ubuntu默认源中的版本比PyPI的低。我这样升级pip

$ sudo pip install pip --upgrade

现在,你可以通过运行run pip install package-name,安装任何Python包。所以,要安装simplejson的话,你可以运行以下命令:

$ sudo pip install simplejson

移除包也一样简单。

$ sudo pip uninstall simplejson

pip默认会安装PyPI上最新的稳定版,但是很多时候,你会希望安装指定版本的包,因为你的项目依赖那个特定的版本。要想指定包的版本,你可以这样做:

$ sudo pip install simplejson==2.2.1

你还会经常需要升级、降级或者重装一些包。你可以通过下面的命令实现:

$ sudo pip install simplejson --upgrade   # Upgrade a package to the latest version from PyPI
$ sudo pip install simplejson==2.2.1 --upgrade # Upgrade/downgrade a package to a given version

接下来,假设你想安装某个包的开发版本,但是代码没有放在PyPI上,而是在版本控制仓库中,你该怎么办?pip也可以满足这个需求,但是在此之前,你需要在系统上安装相应的版本控制系统(VCS)。在Ubuntu平台,你可以输入下面的命令:

$ sudo apt-get install git-core mercurial subversion

安装好VCS之后,你可以通过下面的方式从远程仓库中安装一个包:

复制代码 代码如下:
$ sudo pip install git+http://hostname_or_ip/path/to/git-repo#egg=packagename
$ sudo pip install hg+http://hostname_or_ip/path/to/hg-repo#egg=packagename
$ sudo pip install svn+http://hostname_or_ip/path/to/svn-repo#egg=packagename

从本地仓库中安装也同样简单。注意下面文件系统路径部分的三个斜杠(///)。