专栏名称: Python开发者
人生苦短,我用 Python。伯乐在线旗下账号「Python开发者」分享 Python 相关的技术文章、工具资源、精选课程、热点资讯等。
目录
相关文章推荐
Python爱好者社区  ·  刚刚!微信 DeepSeek ... ·  昨天  
Python爱好者社区  ·  模仿一下领导说话的样子 ·  16 小时前  
Python爱好者社区  ·  35个爬虫实例 ·  3 天前  
Python爱好者社区  ·  机器学习全书 ·  3 天前  
Python爱好者社区  ·  梁文锋导师项志宇引关注,个人主页满满都是对团 ... ·  3 天前  
51好读  ›  专栏  ›  Python开发者

PyPy 简介

Python开发者  · 公众号  · Python  · 2016-11-28 22:11

正文

(点击 上方公众号 ,可快速关注)


来源:Uche Ogbuji

链接:www.ibm.com/developerworks/cn/opensource/os-pypy-intro/


概述


Python 编程语言于 1994 年问世,自新千年以来,这种语言获得了极大的成功。衡量一种语言成功与否的标准之一就是其实现的数量。最知名也是最常用的 Python 实现称为 CPython。此外还有其他一些成功的项目,例如 Jython(在 Java ™ 运行时中工作的 Python 语言)和 IronPython(在 .NET 平台上工作的 Python 语言)。所有这些项目都是开放源码的,而 Python 在开放源码软件世界中始终有着极大的影响力。


Python 实现的一个由来已久的目标就是支持纯语言设计,通过以自己的方式指定相关语言来 “引导” Python 的定义,而不是按照 C 和 Java 等其他语言的方式做出规定。PyPy 项目正是应此需求而出现的一种 Python 实现。PyPy 表示 “用 Python 实现的 Python”,但实际上它是使用一个称为 RPython 的 Python 子集实现的。更准确地来说,PyPy 自身就是一种运行时,您可以在其中插入任何语言。


PyPy 整洁的语言设计使之非常适合嵌入低级优化器,提供诸多优化优势。具体来说,PyPy 集成了一种即时 (JIT) 编译器。这与能够以革命性的方式改变 Java 性能的知名技术 HotSpot 属于同一种技术的不同形式,Sun Microsystems 于 21 世纪初期从 Animorphic 手中收购了 HotSpot,并整合到了自己的 Java 实现之中,使这种语言适用于大多数用途。Python 原本已经适用于多种用途,但性能是最常被人们抱怨的问题。PyPy 的跟踪 JIT 编译器已经展现了它革新 Python 程序性能的能力,尽管我认为这个项目仍然处于后续测试阶段,但它已经是 Python 程序员的一种重要工具,是开发人员工具箱的有用补充。


在这篇文章中,我将介绍 PyPy,而且假设读者并不具备丰富的 Python 背景知识。


入门


首先,请不要将 PyPy 与 PyPI 混淆。这是两个截然不同的项目。PyPI 即 Python Package Index,是获得第三方 Python 软件包以补充标准库的一个站点及系统。在您进入正确的 PyPy 站点之后(请参见 参考资料 部分),您会看到开发人员已经使大多数用户能够轻松开始尝试使用 PyPy。如果您在最新的硬件上使用 Linux®、Mac 或 Windows®(不含 Windows 64,目前尚不支持 Windows 64),那么就应该能够直接下载并执行一个二进制软件包。


PyPY 的最新版本是 1.8,它充分实现了 Python 2.7.2,也就是说能够兼容这个版本的 CPython 的语言特性和行为。然而,在许多基准使用当中,它的速度已经远远超过了 CPython 2.7.2,这是它引起我们注意的真正因素。下面的会话展示了我在 Ubuntu 11.04 机器上安装 PyPy 的过程。这段会话来自旧版本的 PyPy,但 PyPy 1.8 也会提供类似的结果。


$ cd Downloads /

$ wget https : //bitbucket.org/pypy/pypy/downloads/pypy-1.6-linux.tar.bz2

$ cd .. / . local

$ tar jxvf ~/ Downloads / pypy - 1.6 - linux . tar . bz2

$ ln - s ~/ . local / pypy - 1.6 / bin / pypy ~/ . local / bin /


现在,您需要更新 $PATH,以包含 ~/.local/bin/。安装 PyPy 之后,建议您同样安装 Distribute 和 Pip,以便简化额外软件包的安装。(尽管本文中未提及,但您也可能需要使用 Virtualenv,这是保持独立、整洁的 Python 环境的一种方法。)以下会话展示了 Distribute 和 Pip 的设置。


$ wget http : //python-distribute.org/distribute_setup.py

$ wget https : //raw.github.com/pypa/pip/master/contrib/get-pip.py

$ pypy distribute_setup . py

$ pypy get - pip . py


您应发现,库文件安装在 ~/.local/pypy-1.8/site-packages/ 目录之中,可执行文件位于 ~/.local/pypy-1.8/bin 目录之中,因此您可能希望将后者添加到 $PATH。此外,务必确保使用了之前安装的 pip,而不是系统级的 pip。随后,您就可以安装本文稍后要用到的第三方软件包。


$ pip install html5lib $ pip install pyparsing


清单 1 展示了调用 Python 的 “彩蛋” import this 之后,PyPy 解释器的输出结果。


清单 1. 示例 PyPy 输出


uche @ malatesta :~ $ pypy

Python 2.7.1 ( d8ac7d23d3ec , Aug 17 2011 , 11 : 51 : 18 )

[ PyPy 1.6.0 with GCC 4.4.3 ] on linux2

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

And now for something completely different : `` __xxx__ and __rxxx__ vs operation

slots : particle quantum superposition kind of fun ''

>>>> import this

The Zen of Python , by Tim Peters

Beautiful is better than ugly .

Explicit is better than implicit .

Simple is better than complex .

Complex is better than complicated .

Flat is better than nested .

Sparse is better than dense .

Readability counts .

Special cases aren 't special enough to break the rules.

Although practicality beats purity.

Errors should never pass silently.

Unless explicitly silenced.

In the face of ambiguity, refuse the temptation to guess.

There should be one-- and preferably only one --obvious way to do it.

Although that way may not be obvious at first unless you' re Dutch .

Now is better than never .

Although never is often better than *right* now .

If the implementation is hard to explain , it 's a bad idea.

If the implementation is easy to explain, it may be a good idea.

Namespaces are one honking great idea -- let' s do more of those !

>>>>


链接统计


作为 PyPy 的一个简单实例,我将展示一个解析网页并打印出网页中表示的链接列表的程序。这正是网络蜘蛛 (spidering) 软件的基本理念,即出于某些目的跟踪页面间的链接网络。


在解析方面,我选择了 html5lib,这是一种纯 Python 解析库,设计用于实现定义了 HTML5 规范的 WHAT-WG 组织的解析算法。HTML5 针对向后兼容性而设计,即便可以兼容损坏的网页。因此 html5lib 同时也是一种出色的通用 HTML 解析工具包。这种工具在 CPython 和 PyPy 上执行了基准测试,在 PyPy 上的速度明显要更快。


清单 2 解析了一个特定的网页,逐行打印了该页面中的链接。您在命令行中指定目标页面 URL,例如: pypy listing1.py http://www.ibm.com/developerworks/opensource/。


清单 2. 列出一个页面中的链接


#!/usr/bin/env pypy

#Import the needed libraries for use

import sys

import urllib2

import html5lib

#List of tuples, each an element/attribute pair to check for links

link_attrs = [

( 'a' , 'href' ),

( 'link' , 'href' ),

]

#This function is a generator, a Python construct that can be used as a sequence.

def list_links ( url ) :

'''

Given a URL parse the HTML and yield a sequence of link strings

as they are found on the page.

'''

#Open the URL and get back a stream of the content

stream = urllib2 . urlopen ( url )

#Parse the HTML content according to html5lib conventions

tree_builder = html5lib . treebuilders . getTreeBuilder ( 'dom' )

parser = html5lib . html5parser . HTMLParser ( tree = tree_builder )

doc = parser . parse ( stream )

#In the outer loop, go over each element/attribute set

for elemname , attr in link_attrs :

#In the inner loop, go over the matches of the current element name

for elem in doc . getElementsByTagName ( elemname ) :

#If the corresponding attribute is found, yield it in sequence

attrvalue = elem . getAttribute ( attr )

if attrvalue :

yield attrvalue

return

#Read the URL to parse from the first command line argument

#Note: Python lists start at index 0, but as in UNIX convention the 0th

#Command line argument is the program name itself

input_url = sys . argv [ 1 ]

#Set up the generator by calling it with the URL argument, then iterate

#Over the yielded link strings, printing each

for link in list_links ( input_url ) :

print link


我在代码中作了非常详尽的注释,因为我并未假设读者拥有深厚的 Python 知识,但您应该了解一些基本知识,例如,如何使用缩排格式来表示控制流。相关的 Python 教程请参见 参考资料 部分。


为简单起见,我避免了此类程序的一些惯例,但确实使用了一项我认为即便对入门级的程序员也非常有用的高级特性。函数 list_links 称为生成器。它是一个像序列一样操作的函数,可依次计算并提供项目。yield 语句是这里的关键,它提供了值序列。


更为复杂的屏幕屏幕抓取


大多数网页解析任务都不仅仅是发现和显示链接那样简单,有一些库可以帮助处理典型的 “网络抓取” 任务。Pyparsing 是一种通用的纯 Python 解析工具包,包含一些支持 HTML 解析的工具。


在下一个示例中,我将展示如何从 IBM developerWorks 索引页面中抓取文章列表。图 1 展示了目标页面的屏幕快照。清单 3 是 HTML 形式的示例记录。


图 1. 需要处理的 IBM developerWorks 网页



清单 3. 待处理的 HTML 示例记录


href = "http://www.ibm.com/developerworks/opensource/library/os-wc3jam/index.html" >

Join the social business revolution

Social media has become social business and everyone from

business leadership to software developers need to understand

the tools and techniques that will be required.

The World Wide Web Consortium (W3C) will be conducting a

social media event to discuss relevant standards and requirement

for the near and far future.

Articles

class = "dw-nowrap" > 03 Nov 2011


清单 4 给出了解析这个页面的代码。同样,我仍然在这里给出了大量注释,但在给出清单后,我还要说明几个重要新概念。


清单 4.  从网页中提取文章列表


#Import the needed built-in libraries for use

import sys

import urllib2

from greenlet import greenlet

#Import what we need from pyparsing

from pyparsing import makeHTMLTags , SkipTo

def collapse_space ( s ) :

'''

Strip leading and trailing space from a string, and replace any run of whitespace

within with a single space

'''

#Split the string according to whitespace and then join back with single spaces

#Then strip leadig and trailing spaces. These are all standard Python library tools

return ' ' . join ( s . split ()). strip ()

def handler () :

'''

Simple coroutine to print the result of a matched portion from the page

'''

#This will be run the first time the code switches to this greenlet function

print 'A list of recent IBM developerWorks Open Source Zone articles:'

#Then we get into the main loop

while True :

next_tok = green_handler . parent . switch ()

print ' *' , collapse_space ( data . title ), '(' , data . date , ')' , data . link . href

#Turn a regular function into a greenlet by wrapping it

green_handler = greenlet ( handler )

#Switch to the handler greenlet the first time to prime it

green_handler . switch ()

#Read the search starting page

START_URL = "http://www.ibm.com/developerworks/opensource/library/"

stream = urllib2 . urlopen ( START_URL )

html = stream . read ()

stream . close ()

#Set up some tokens for HTML start and end tags

div_start , div_end = makeHTMLTags ( "div" )

tbody_start , tbody_end = makeHTMLTags ( "tbody" )

strong_start , strong_end = makeHTMLTags ( "strong" )

article_tr , tr_end = makeHTMLTags ( "tr" )

td_start







请到「今天看啥」查看全文