<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>I am LAZY bones ? &#187; 编程相关</title>
	<atom:link href="http://luy.li/category/programme/feed/" rel="self" type="application/rss+xml" />
	<link>http://luy.li</link>
	<description>all linux</description>
	<lastBuildDate>Sun, 25 Jul 2010 07:24:54 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>为什么python里要 if __name__ == &#8216;__main__&#8217;:</title>
		<link>http://luy.li/2010/05/31/python__name__main__/</link>
		<comments>http://luy.li/2010/05/31/python__name__main__/#comments</comments>
		<pubDate>Mon, 31 May 2010 10:52:14 +0000</pubDate>
		<dc:creator>bones7456</dc:creator>
				<category><![CDATA[编程相关]]></category>

		<guid isPermaLink="false">http://li2z.cn/?p=1581</guid>
		<description><![CDATA[尽管python允许你像shell脚本一样，把大段的代码堆积着写，但是，很多python入门的书，都会建议你把代码写成一个函数，然后在最后面统一调用，例如这样：

def main&#40;&#41;:
    #具体代码
&#160;
if __name__ == '__main__':
    main&#40;&#41;

很多文章都会说这个是由于代码风格之类的原因，但是其实，不这样写，有时候也是会直接导致出错的。
举个例子，打开《A Byte of Python》的类变量那节，可以这里看在线版本，然后把中间的那示例代码复制下来，运行，可以看到，确实能得到预期正确的结果。
但是，现在把那代码里的所有“swaroop”换成“xxx1”，再把所有“kalam”换成“yyy1”，再运行，就会在程序运行的最后时刻，得到这么一个奇怪的错误（Python 2.6.5下实验）：
Exception AttributeError: "'NoneType' object has no attribute 'population'" in  ignored
也就是说，换了个变量名，程序就出错了。。。
究其原因，应该是python在最后析构所有类和对象的时候，并没有处理这些对象之间的依赖关系，而是根据变量名来决定某种顺序操作了。从而导致Person类本身，先于yyy2被干掉了，所以在解构yyy2的时候，执行它的__del__()方法，却发现父类都已经没有了~~
这应该确实算是python解析器的bug，但是，如果那把这个例子里的所有class Person以外的代码，写到一个main()函数里，再通过上述方法调用的话，就不会发生这种错误了。
所以，大家最好还是别太在意多几行代码，养成这个好习惯吧。
要深究此错误的原因，可以看官方文档里的描述，并在这里讨论。
]]></description>
			<content:encoded><![CDATA[<p>尽管python允许你像shell脚本一样，把大段的代码堆积着写，但是，很多python入门的书，都会建议你把代码写成一个函数，然后在最后面统一调用，例如这样：</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> main<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #808080; font-style: italic;">#具体代码</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">if</span> __name__ == <span style="color: #483d8b;">'__main__'</span>:
    main<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>很多文章都会说这个是由于代码风格之类的原因，但是其实，不这样写，有时候也是会直接导致出错的。<br />
举个例子，打开《A Byte of Python》的类变量那节，可以<a href="http://www.ibiblio.org/swaroopch/byteofpython/read/class-and-object-vars.html">这里看在线版本</a>，然后把中间的那示例代码复制下来，运行，可以看到，确实能得到预期正确的结果。<br />
但是，现在把那代码里的所有“swaroop”换成“xxx1”，再把所有“kalam”换成“yyy1”，再运行，就会在程序运行的最后时刻，得到这么一个奇怪的错误（Python 2.6.5下实验）：<br />
<code>Exception AttributeError: "'NoneType' object has no attribute 'population'" in <bound method Person.__del__ of <__main__.Person instance at 0xb689090c>> ignored</code><br />
也就是说，换了个变量名，程序就出错了。。。<br />
究其原因，应该是python在最后析构所有类和对象的时候，并没有处理这些对象之间的依赖关系，而是根据变量名来决定某种顺序操作了。从而导致<code>Person</code>类本身，先于<code>yyy2</code>被干掉了，所以在解构<code>yyy2</code>的时候，执行它的<code>__del__()</code>方法，却发现父类都已经没有了~~<br />
这应该确实算是python解析器的bug，但是，如果那把这个例子里的所有class Person以外的代码，写到一个<code>main()</code>函数里，再通过上述方法调用的话，就不会发生这种错误了。<br />
所以，大家最好还是别太在意多几行代码，养成这个好习惯吧。</p>
<p>要深究此错误的原因，可以看官方文档里的<a href="http://docs.python.org/c-api/init.html#Py_Finalize">描述</a>，并在<a href="http://groups.google.com/group/python-cn/browse_thread/thread/31df4e6076782599">这里</a>讨论。</p>
]]></content:encoded>
			<wfw:commentRss>http://luy.li/2010/05/31/python__name__main__/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>python中的socket代理</title>
		<link>http://luy.li/2010/05/20/python_socks/</link>
		<comments>http://luy.li/2010/05/20/python_socks/#comments</comments>
		<pubDate>Thu, 20 May 2010 11:21:31 +0000</pubDate>
		<dc:creator>bones7456</dc:creator>
				<category><![CDATA[编程相关]]></category>

		<guid isPermaLink="false">http://li2z.cn/?p=1570</guid>
		<description><![CDATA[说socket代理之前，先来说说http代理，python的urllib2是自带http代理功能的，可以用如下代码实现：

proxy_handler = urllib2.ProxyHandler&#40;&#123;'http' : 'http://地址:端口'&#125;&#41;
opener = urllib2.build_opener&#40;proxy_handler, urllib2.HTTPHandler&#41;
urllib2.install_opener&#40;opener&#41;

如此，接下来用urllib2来urlopen的时候，就会自动使用这个代理了。
但是，在我们疯狂的天朝，有时候，http代理并不能满足要求，也许你还想使用更底层的socket代理，于是python里似乎就没有直接的方法了（python3不知道有没有内置，未研究）。这时候，你可能需要这个包：SocksiPy &#8211; A Python SOCKS module，下载解压以后，除了文档也就一个 socks.py 文件，很方便使用，给出示例代码：

import socks, socket
socks.setdefaultproxy&#40;socks.PROXY_TYPE_SOCKS5, &#34;地址&#34;, 端口&#41;
socket.socket = socks.socksocket

接下来，你就可以照常使用socket了，一切都会悄悄地通过代理出去的~
]]></description>
			<content:encoded><![CDATA[<p>说socket代理之前，先来说说http代理，python的urllib2是自带http代理功能的，可以用如下代码实现：</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">proxy_handler = <span style="color: #dc143c;">urllib2</span>.<span style="color: black;">ProxyHandler</span><span style="color: black;">&#40;</span><span style="color: black;">&#123;</span><span style="color: #483d8b;">'http'</span> : <span style="color: #483d8b;">'http://地址:端口'</span><span style="color: black;">&#125;</span><span style="color: black;">&#41;</span>
opener = <span style="color: #dc143c;">urllib2</span>.<span style="color: black;">build_opener</span><span style="color: black;">&#40;</span>proxy_handler, <span style="color: #dc143c;">urllib2</span>.<span style="color: black;">HTTPHandler</span><span style="color: black;">&#41;</span>
<span style="color: #dc143c;">urllib2</span>.<span style="color: black;">install_opener</span><span style="color: black;">&#40;</span>opener<span style="color: black;">&#41;</span></pre></div></div>

<p>如此，接下来用urllib2来urlopen的时候，就会自动使用这个代理了。</p>
<p>但是，在我们疯狂的天朝，有时候，http代理并不能满足要求，也许你还想使用更底层的socket代理，于是python里似乎就没有直接的方法了（python3不知道有没有内置，未研究）。这时候，你可能需要这个包：<a href="http://sourceforge.net/projects/socksipy/">SocksiPy</a> &#8211; A Python SOCKS module，下载解压以后，除了文档也就一个 socks.py 文件，很方便使用，给出示例代码：</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">import</span> socks, <span style="color: #dc143c;">socket</span>
socks.<span style="color: black;">setdefaultproxy</span><span style="color: black;">&#40;</span>socks.<span style="color: black;">PROXY_TYPE_SOCKS5</span>, <span style="color: #483d8b;">&quot;地址&quot;</span>, 端口<span style="color: black;">&#41;</span>
<span style="color: #dc143c;">socket</span>.<span style="color: #dc143c;">socket</span> = socks.<span style="color: black;">socksocket</span></pre></div></div>

<p>接下来，你就可以照常使用socket了，一切都会悄悄地通过代理出去的~</p>
]]></content:encoded>
			<wfw:commentRss>http://luy.li/2010/05/20/python_socks/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>python的正则表达式 re</title>
		<link>http://luy.li/2010/05/12/python-re/</link>
		<comments>http://luy.li/2010/05/12/python-re/#comments</comments>
		<pubDate>Wed, 12 May 2010 06:54:59 +0000</pubDate>
		<dc:creator>bones7456</dc:creator>
				<category><![CDATA[精华]]></category>
		<category><![CDATA[编程相关]]></category>

		<guid isPermaLink="false">http://li2z.cn/?p=1491</guid>
		<description><![CDATA[延伸阅读：python的 内建函数 和 subprocess 。此文是本系列的第三篇文章了，和之前一样，内容出自官方文档，但是会有自己的理解，并非单纯的翻译。所以，如果我理解有误，欢迎指正，谢谢。
本模块提供了和Perl里的正则表达式类似的功能，不关是正则表达式本身还是被搜索的字符串，都可以是Unicode字符，这点不用担心，python会处理地和Ascii字符一样漂亮。
正则表达式使用反斜杆（\）来转义特殊字符，使其可以匹配字符本身，而不是指定其他特殊的含义。这可能会和python字面意义上的字符串转义相冲突，这也许有些令人费解。比如，要匹配一个反斜杆本身，你也许要用'\\\\'来做为正则表达式的字符串，因为正则表达式要是\\，而字符串里，每个反斜杆都要写成\\。
你也可以在字符串前加上 r 这个前缀来避免部分疑惑，因为 r 开头的python字符串是 raw 字符串，所以里面的所有字符都不会被转义，比如r'\n'这个字符串就是一个反斜杆加上一字母n，而'\n'我们知道这是个换行符。因此，上面的'\\\\'你也可以写成r'\\'，这样，应该就好理解很多了。可以看下面这段：

&#62;&#62;&#62; import re
&#62;&#62;&#62; s = '\x5c'  #0x5c就是反斜杆
&#62;&#62;&#62; print s
\
&#62;&#62;&#62; re.match&#40;'\\\\', s&#41;  #这样可以匹配
&#60;_sre.SRE_Match object at 0xb6949e20&#62;
&#62;&#62;&#62; re.match&#40;r'\\', s&#41;  #这样也可以
&#60;_sre.SRE_Match object at 0x80ce2c0&#62;
&#62;&#62;&#62; re.match&#40;'\\', s&#41;  #但是这样不行
Traceback &#40;most recent call last&#41;:
  File &#34;&#60;stdin&#62;&#34;, line 1, in &#60;module&#62;
  File &#34;/usr/lib/python2.6/re.py&#34;, line 137, in [...]]]></description>
			<content:encoded><![CDATA[<p>延伸阅读：python的 <a href="http://luy.li/2009/11/29/python-built-in-functions/">内建函数</a> 和 <a href="http://luy.li/2010/04/14/python_subprocess/">subprocess</a> 。此文是本系列的第三篇文章了，和之前一样，内容出自<a href="http://docs.python.org/library/re.html">官方文档</a>，但是会有自己的理解，并非单纯的翻译。所以，如果我理解有误，欢迎指正，谢谢。</p>
<p>本模块提供了和Perl里的正则表达式类似的功能，不关是正则表达式本身还是被搜索的字符串，都可以是Unicode字符，这点不用担心，python会处理地和Ascii字符一样漂亮。<br />
正则表达式使用反斜杆（<code>\</code>）来转义特殊字符，使其可以匹配字符本身，而不是指定其他特殊的含义。这可能会和python字面意义上的字符串转义相冲突，这也许有些令人费解。比如，要匹配一个反斜杆本身，你也许要用<code>'\\\\'</code>来做为正则表达式的字符串，因为正则表达式要是<code>\\</code>，而字符串里，每个反斜杆都要写成<code>\\</code>。<br />
你也可以在字符串前加上 r 这个前缀来避免部分疑惑，因为 r 开头的python字符串是 raw 字符串，所以里面的所有字符都不会被转义，比如<code>r'\n'</code>这个字符串就是一个反斜杆加上一字母n，而<code>'\n'</code>我们知道这是个换行符。因此，上面的<code>'\\\\'</code>你也可以写成<code>r'\\'</code>，这样，应该就好理解很多了。可以看下面这段：</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">re</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> s = <span style="color: #483d8b;">'<span style="color: #000099; font-weight: bold;">\x</span>5c'</span>  <span style="color: #808080; font-style: italic;">#0x5c就是反斜杆</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">print</span> s
\
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #dc143c;">re</span>.<span style="color: black;">match</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'<span style="color: #000099; font-weight: bold;">\\</span><span style="color: #000099; font-weight: bold;">\\</span>'</span>, s<span style="color: black;">&#41;</span>  <span style="color: #808080; font-style: italic;">#这样可以匹配</span>
<span style="color: #66cc66;">&lt;</span>_sre.<span style="color: black;">SRE_Match</span> <span style="color: #008000;">object</span> at 0xb6949e20<span style="color: #66cc66;">&gt;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #dc143c;">re</span>.<span style="color: black;">match</span><span style="color: black;">&#40;</span>r<span style="color: #483d8b;">'<span style="color: #000099; font-weight: bold;">\\</span>'</span>, s<span style="color: black;">&#41;</span>  <span style="color: #808080; font-style: italic;">#这样也可以</span>
<span style="color: #66cc66;">&lt;</span>_sre.<span style="color: black;">SRE_Match</span> <span style="color: #008000;">object</span> at 0x80ce2c0<span style="color: #66cc66;">&gt;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #dc143c;">re</span>.<span style="color: black;">match</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'<span style="color: #000099; font-weight: bold;">\\</span>'</span>, s<span style="color: black;">&#41;</span>  <span style="color: #808080; font-style: italic;">#但是这样不行</span>
Traceback <span style="color: black;">&#40;</span>most recent call last<span style="color: black;">&#41;</span>:
  File <span style="color: #483d8b;">&quot;&lt;stdin&gt;&quot;</span>, line <span style="color: #ff4500;">1</span>, <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #66cc66;">&lt;</span>module<span style="color: #66cc66;">&gt;</span>
  File <span style="color: #483d8b;">&quot;/usr/lib/python2.6/re.py&quot;</span>, line <span style="color: #ff4500;">137</span>, <span style="color: #ff7700;font-weight:bold;">in</span> match
    <span style="color: #ff7700;font-weight:bold;">return</span> _compile<span style="color: black;">&#40;</span>pattern, flags<span style="color: black;">&#41;</span>.<span style="color: black;">match</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">string</span><span style="color: black;">&#41;</span>
  File <span style="color: #483d8b;">&quot;/usr/lib/python2.6/re.py&quot;</span>, line <span style="color: #ff4500;">245</span>, <span style="color: #ff7700;font-weight:bold;">in</span> _compile
    <span style="color: #ff7700;font-weight:bold;">raise</span> error, v <span style="color: #808080; font-style: italic;"># invalid expression</span>
sre_constants.<span style="color: black;">error</span>: bogus escape <span style="color: black;">&#40;</span>end of line<span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span></pre></div></div>

<p>另外值得一提的是，re模块的方法，大多也就是RegexObject对象的方法，两者的区别在于执行效率。这个在最后再展开吧。</p>
<p><big><strong>正则表达式语法</strong></big></p>
<p>正则表达式（RE）指定一个与之匹配的字符集合；本模块所提供的函数，将可以用来检查所给的字符串是否与指定的正则表达式匹配。<br />
正则表达式可以被连接，从而形成新的正则表达式；例如A和B都是正则表达式，那么AB也是正则表达式。一般地，如果字符串<em>p</em>与A匹配，<em>q</em>与B匹配的话，那么字符串<em>pq</em>也会与AB匹配，但A或者B里含有边界限定条件或者命名组操作的情况除外。也就是说，复杂的正则表达式可以用简单的连接而成。<br />
正则表达式可以包含特殊字符和普通字符，大部分字符比如<code>'A'</code>，<code>'a'</code>和<code>'0'</code>都是普通字符，如果做为正则表达式，它们将匹配它们本身。由于正则表达式可以连接，所以连接多个普通字符而成的正则表达式<code>last</code>也将匹配<code>'last'</code>。（后面将用不带引号的表示正则表达式，带引号的表示字符串）</p>
<p>下面就来介绍正则表达式的特殊字符：</p>
<p><code>'.'</code><br />
点号，在普通模式，它匹配除换行符外的任意一个字符；如果指定了 <strong>DOTALL</strong> 标记，匹配包括换行符以内的任意一个字符。</p>
<p><code>'^'</code><br />
尖尖号，匹配一个字符串的开始，在 <strong>MULTILINE</strong> 模式下，也将匹配任意一个新行的开始。</p>
<p><code>'$'</code><br />
美元符号，匹配一个字符串的结尾或者字符串最后面的换行符，在 <strong>MULTILINE</strong> 模式下，也匹配任意一行的行尾。也就是说，普通模式下，<code>foo.$</code>去搜索<code>'foo1\nfoo2\n'</code>只会找到&#8217;foo2&#8242;，但是在 <strong>MULTILINE</strong> 模式，还能找到 &#8216;foo1&#8242;，而且就用一个 <code>$</code> 去搜索<code>'foo\n'</code>的话，会找到两个空的匹配：一个是最后的换行符，一个是字符串的结尾，演示：</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #dc143c;">re</span>.<span style="color: black;">findall</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'(foo.$)'</span>, <span style="color: #483d8b;">'foo1<span style="color: #000099; font-weight: bold;">\n</span>foo2<span style="color: #000099; font-weight: bold;">\n</span>'</span><span style="color: black;">&#41;</span>
<span style="color: black;">&#91;</span><span style="color: #483d8b;">'foo2'</span><span style="color: black;">&#93;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #dc143c;">re</span>.<span style="color: black;">findall</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'(foo.$)'</span>, <span style="color: #483d8b;">'foo1<span style="color: #000099; font-weight: bold;">\n</span>foo2<span style="color: #000099; font-weight: bold;">\n</span>'</span>, <span style="color: #dc143c;">re</span>.<span style="color: black;">MULTILINE</span><span style="color: black;">&#41;</span>
<span style="color: black;">&#91;</span><span style="color: #483d8b;">'foo1'</span>, <span style="color: #483d8b;">'foo2'</span><span style="color: black;">&#93;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #dc143c;">re</span>.<span style="color: black;">findall</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'($)'</span>, <span style="color: #483d8b;">'foo<span style="color: #000099; font-weight: bold;">\n</span>'</span><span style="color: black;">&#41;</span>
<span style="color: black;">&#91;</span><span style="color: #483d8b;">''</span>, <span style="color: #483d8b;">''</span><span style="color: black;">&#93;</span></pre></div></div>

<p><code>'*'</code><br />
星号，指定将前面的RE重复0次或者任意多次，而且总是试图尽量多次地匹配。</p>
<p><code>'+'</code><br />
加号，指定将前面的RE重复1次或者任意多次，而且总是试图尽量多次地匹配。</p>
<p><code>'?'</code><br />
问号，指定将前面的RE重复0次或者1次，如果有的话，也尽量匹配1次。</p>
<p><code>*?</code>， <code>+?</code>， <code>??</code><br />
从前面的描述可以看到<code>'*'</code>，<code>'+'</code>和<code>'?'</code>都是<em>贪婪的</em>，但这也许并不是我们说要的，所以，可以在后面加个问号，将策略改为<em>非贪婪</em>，只匹配尽量少的RE。示例，体会两者的区别：</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #dc143c;">re</span>.<span style="color: black;">findall</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'&lt;(.*)&gt;'</span>, <span style="color: #483d8b;">'&lt;H1&gt;title&lt;/H1&gt;'</span><span style="color: black;">&#41;</span>
<span style="color: black;">&#91;</span><span style="color: #483d8b;">'H1&gt;title&lt;/H1'</span><span style="color: black;">&#93;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #dc143c;">re</span>.<span style="color: black;">findall</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'&lt;(.*?)&gt;'</span>, <span style="color: #483d8b;">'&lt;H1&gt;title&lt;/H1&gt;'</span><span style="color: black;">&#41;</span>
<span style="color: black;">&#91;</span><span style="color: #483d8b;">'H1'</span>, <span style="color: #483d8b;">'/H1'</span><span style="color: black;">&#93;</span></pre></div></div>

<p><code>{m}</code><br />
m是一个数字，指定将前面的RE重复m次。</p>
<p><code>{m,n}</code><br />
m和n都是数字，指定将前面的RE重复m到n次，例如<code>a{3,5}</code>匹配3到5个连续的a。注意，如果省略m，将匹配0到n个前面的RE；如果省略n，将匹配n到无穷多个前面的RE；当然中间的逗号是不能省略的，不然就变成前面那种形式了。</p>
<p><code>{m,n}?</code><br />
前面说的<code>{m,n}</code>，也是贪婪的，<code>a{3,5}</code>如果有5个以上连续a的话，会匹配5个，这个也可以通过加问号改变。<code>a{3,5}?</code>如果可能的话，将只匹配3个a。</p>
<p><code>'\'</code><br />
反斜杆，转义<code>'*'</code>，<code>'?'</code>等特殊字符，或者指定一个特殊序列（下面会详述）<br />
由于之前所述的原因，强烈建议用raw字符串来表述正则。</p>
<p><code>[]</code><br />
方括号，用于指定一个字符的集合。可以单独列出字符，也可以用<code>'-'</code>连接起止字符以表示一个范围。特殊字符在中括号里将失效，比如<code>[akm$]</code>就表示字符<code>'a'</code>，<code>'k'</code>，<code>'m'</code>，或<code>'$'</code>，在这里$也变身为普通字符了。<code>[a-z]</code>匹配任意一个小写字母，<code>[a-zA-Z0-9]</code>匹配任意一个字母或数字。如果你要匹配<code>']'</code>或<code>'-'</code>本身，你需要加反斜杆转义，或者是将其置于中括号的最前面，比如<code>[]]</code>可以匹配<code>']'</code><br />
你还可以对一个字符集合<em>取反</em>，以匹配任意不在这个字符集合里的字符，<code>取反</code>操作用一个<code>'^'</code>放在集合的最前面表示，放在其他地方的<code>'^'</code>将不会起特殊作用。例如<code>[^5]</code>将匹配任意不是<code>'5'</code>的字符；<code>[^^]</code>将匹配任意不是<code>'^'</code>的字符。<br />
注意：在中括号里，<code>+</code>、<code>*</code>、<code>(</code>、<code>)</code>这类字符将会失去特殊含义，仅作为普通字符。反向引用也不能在中括号内使用。</p>
<p><code>'|'</code><br />
管道符号，A和B是任意的RE，那么<code>A|B</code>就是匹配A或者B的一个新的RE。任意个数的RE都可以像这样用管道符号间隔连接起来。这种形式可以被用于<strong>组</strong>中（后面将详述）。对于目标字符串，被<code>'|'</code>分割的RE将自左至右一一被测试，一旦有一个测试成功，后面的将不再被测试，即使后面的RE可能可以匹配更长的串，换句话说，<code>'|'</code>操作符是非贪婪的。要匹配字面意义上的<code>'|'</code>，可以用反斜杆转义：<code>\|</code>，或是包含在反括号内：<code>[|]</code>。</p>
<p><code>(...)</code><br />
匹配圆括号里的RE匹配的内容，并指定<strong>组</strong>的开始和结束位置。组里面的内容可以被提取，也可以采用<code>\number</code>这样的特殊序列，被用于后续的匹配。要匹配字面意义上的<code>'('</code>和<code>')'</code>，可以用反斜杆转义：<code>\(</code>、<code>\)</code>，或是包含在反括号内：<code>[(]</code>、<code>[)]</code>。</p>
<p><code>(?...)</code><br />
这是一个表达式的扩展符号。<code>'?'</code>后的第一个字母决定了整个表达式的语法和含义，除了<code>(?P<name>...)</code>以外，表达式不会产生一个新的组。下面介绍几个目前已被支持的扩展：</p>
<p><code>(?iLmsux)</code><br />
<code>'i'</code>、<code>'L'</code>、<code>'m'</code>、<code>'s'</code>、<code>'u'</code>、<code>'x'</code>里的一个或多个字母。表达式不匹配任何字符，但是指定相应的标志：<strong>re.I</strong>(忽略大小写)、<strong>re.L</strong>(依赖locale)、<strong>re.M</strong>(多行模式)、<strong>re.S</strong>(.匹配所有字符)、<strong>re.U</strong>(依赖Unicode)、<strong>re.X</strong>(详细模式)。关于各个模式的区别，下面会有专门的一节来介绍的。使用这个语法可以代替在<code>re.compile()</code>的时候或者调用的时候指定<em>flag</em>参数。<br />
例如，上面举过的例子，可以改写成这样（和指定了<code>re.MULTILINE</code>是一样的效果）：</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #dc143c;">re</span>.<span style="color: black;">findall</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'(?m)(foo.$)'</span>, <span style="color: #483d8b;">'foo1<span style="color: #000099; font-weight: bold;">\n</span>foo2<span style="color: #000099; font-weight: bold;">\n</span>'</span><span style="color: black;">&#41;</span>
<span style="color: black;">&#91;</span><span style="color: #483d8b;">'foo1'</span>, <span style="color: #483d8b;">'foo2'</span><span style="color: black;">&#93;</span></pre></div></div>

<p>另外，还要注意<code>(?x)</code>标志如果有的话，要放在最前面。</p>
<p><code>(?:...)</code><br />
匹配内部的RE所匹配的内容，但是不建立<strong>组</strong>。</p>
<p><code>(?P&lt;name&gt;...)</code><br />
和普通的圆括号类似，但是子串匹配到的内容将可以用命名的<em>name</em>参数来提取。组的<em>name</em>必须是有效的python标识符，而且在本表达式内不重名。命名了的组和普通组一样，也用数字来提取，也就是说名字只是个额外的属性。<br />
演示一下：</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> m=<span style="color: #dc143c;">re</span>.<span style="color: black;">match</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'(?P&lt;var&gt;[a-zA-Z_]<span style="color: #000099; font-weight: bold;">\w</span>*)'</span>, <span style="color: #483d8b;">'abc=123'</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> m.<span style="color: black;">group</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'var'</span><span style="color: black;">&#41;</span>
<span style="color: #483d8b;">'abc'</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> m.<span style="color: black;">group</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>
<span style="color: #483d8b;">'abc'</span></pre></div></div>

<p><code>(?P=name)</code><br />
匹配之前以<em>name</em>命名的组里的内容。<br />
演示一下：</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #dc143c;">re</span>.<span style="color: black;">match</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'&lt;(?P&lt;tagname&gt;<span style="color: #000099; font-weight: bold;">\w</span>*)&gt;.*&lt;/(?P=tagname)&gt;'</span>, <span style="color: #483d8b;">'&lt;h1&gt;xxx&lt;/h2&gt;'</span><span style="color: black;">&#41;</span>  <span style="color: #808080; font-style: italic;">#这个不匹配</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #dc143c;">re</span>.<span style="color: black;">match</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'&lt;(?P&lt;tagname&gt;<span style="color: #000099; font-weight: bold;">\w</span>*)&gt;.*&lt;/(?P=tagname)&gt;'</span>, <span style="color: #483d8b;">'&lt;h1&gt;xxx&lt;/h1&gt;'</span><span style="color: black;">&#41;</span>  <span style="color: #808080; font-style: italic;">#这个匹配</span>
<span style="color: #66cc66;">&lt;</span>_sre.<span style="color: black;">SRE_Match</span> <span style="color: #008000;">object</span> at 0xb69588e0<span style="color: #66cc66;">&gt;</span></pre></div></div>

<p><code>(?#...)</code><br />
注释，圆括号里的内容会被忽略。</p>
<p><code>(?=...)</code><br />
如果 <code>...</code> 匹配接下来的字符，才算匹配，但是并不会消耗任何被匹配的字符。例如 <code>Isaac (?=Asimov)</code> 只会匹配后面跟着 <code>'Asimov'</code> 的 <code>'Isaac '</code>，这个叫做“前瞻断言”。</p>
<p><code>(?!...)</code><br />
和上面的相反，只匹配接下来的字符串<strong>不</strong>匹配 <code>...</code> 的串，这叫做“反前瞻断言”。</p>
<p><code>(?<=...)</code><br />
只有当当前位置之前的字符串匹配 <code>...</code> ，整个匹配才有效，这叫“后顾断言”。<code>(?<=abc)def</code>会找到 <code>'abcdef'</code>，因为会后向查找3个字符，看是否为abc。所以内置的子RE，需要是固定长度的，比如可以是<code>abc</code>、<code>a|b</code>，但不能是<code>a*</code>、<code>a{3,4}</code>。注意这种RE永远不会匹配到字符串的开头。举个例子，找到连字符（<code>'-'</code>）后的单词：</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> m = <span style="color: #dc143c;">re</span>.<span style="color: black;">search</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'(?&lt;=-)<span style="color: #000099; font-weight: bold;">\w</span>+'</span>, <span style="color: #483d8b;">'spam-egg'</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> m.<span style="color: black;">group</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span>
<span style="color: #483d8b;">'egg'</span></pre></div></div>

<p><code>(?&lt;!...)</code><br />
同理，这个叫做“反后顾断言”，子RE需要固定长度的，含义是前面的字符串不匹配 <code>...</code> 整个才算匹配。</p>
<p><code>(?(id/name)yes-pattern|no-pattern)</code><br />
如有由<em>id</em>或者<em>name</em>指定的组存在的话，将会匹配<code>yes-pattern</code>，否则将会匹配<code>no-pattern</code>，通常情况下<code>no-pattern</code>也可以省略。例如：<code>(<)?(\w+@\w+(?:\.\w+)+)(?(1)>)</code>可以匹配 <code>'&lt;user@host.com&gt;'</code> 和 <code>'user@host.com'</code>，但是不会匹配 <code>'&lt;user@host.com'</code>。</p>
<p>下面列出以<code>'\'</code>开头的特殊序列。如果某个字符没有在下面列出，那么RE的结果会只匹配那个字母本身，比如，<code>\$</code>只匹配字面意义上的<code>'$'</code>。</p>
<p><code>\number</code><br />
匹配number所指的组相同的字符串。组的序号从1开始。例如：<code>(.+) \1</code>可以匹配<code>'the the'</code>和<code>'55 55'</code>，但不匹配<code>'the end'</code>。这种序列在一个正则表达式里最多可以有99个，如果<em>number</em>以0开头，或是有3位以上的数字，就会被当做八进制表示的字符了。同时，这个也不能用于方括号内。</p>
<p><code>\A</code><br />
只匹配字符串的开始。</p>
<p><code>\b</code><br />
匹配单词边界（包括开始和结束），这里的“单词”，是指连续的字母、数字和下划线组成的字符串。注意，<code>\b</code>的定义是<code>\w</code>和<code>\W</code>的交界，所以精确的定义有赖于<code>UNICODE</code>和<code>LOCALE</code>这两个标志位。</p>
<p><code>\B</code><br />
和<code>\b</code>相反，<code>\B</code>匹配非单词边界。也依赖于<code>UNICODE</code>和<code>LOCALE</code>这两个标志位。</p>
<p><code>\d</code><br />
未指定<code>UNICODE</code>标志时，匹配数字，等效于：<code>[0-9]</code>。指定了<code>UNICODE</code>标志时，还会匹配其他Unicode库里描述为字符串的符号。便于理解，举个例子（好不容易找的例子啊，呵呵）：</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">#\u2076\和u2084分别是上标的6和下标的4，属于unicode的DIGIT</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> unistr = u<span style="color: #483d8b;">'<span style="color: #000099; font-weight: bold;">\u</span>2076<span style="color: #000099; font-weight: bold;">\u</span>2084abc'</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">print</span> unistr
⁶₄abc
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #dc143c;">re</span>.<span style="color: black;">findall</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'<span style="color: #000099; font-weight: bold;">\d</span>+'</span>, unistr, <span style="color: #dc143c;">re</span>.<span style="color: black;">U</span><span style="color: black;">&#41;</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span>
⁶₄</pre></div></div>

<p><code>\D</code><br />
和<code>\d</code>相反，不多说了。</p>
<p><code>\s</code><br />
当未指定<code>UNICODE</code>和<code>LOCALE</code>这两个标志位时，匹配任何空白字符，等效于<code>[ \t\n\r\f\v]</code>。如果指定了<code>LOCALE</code>，则还要加LOCALE相关的空白字符；如果指定了<code>UNICODE</code>，还要加上UNICODE空白字符，如较常见的空宽度连接空格（\uFEFF）、零宽度非连接空格(\u200B)等。</p>
<p><code>\S</code><br />
和<code>\s</code>相反，也不多说。</p>
<p><code>\w</code><br />
当未指定<code>UNICODE</code>和<code>LOCALE</code>这两个标志位时，等效于<code>[a-zA-Z0-9_]</code>。当指定了<code>LOCALE</code>时，为<code>[0-9_]</code>加上当前LOCAL指定的字母。当指定了<code>UNICODE</code>时，为<code>[0-9_]</code>加上UNICODE库里的所有字母。</p>
<p><code>\W</code><br />
和<code>\w</code>相反，不多说。</p>
<p><code>\Z</code><br />
只匹配字符串的结尾。</p>
<p><big><strong>匹配之于搜索</strong></big></p>
<p>python提供了两种基于正则表达式的操作：匹配（match）从字符串的开始检查字符串是否个正则匹配。而搜索（search）检查字符串任意位置是否有匹配的子串（perl默认就是如此）。<br />
注意，即使search的正则以<code>'^'</code>开头，match和search也还是有许多不同的。</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #dc143c;">re</span>.<span style="color: black;">match</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;c&quot;</span>, <span style="color: #483d8b;">&quot;abcdef&quot;</span><span style="color: black;">&#41;</span>  <span style="color: #808080; font-style: italic;"># 不匹配</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #dc143c;">re</span>.<span style="color: black;">search</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;c&quot;</span>, <span style="color: #483d8b;">&quot;abcdef&quot;</span><span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;"># 匹配</span>
<span style="color: #66cc66;">&lt;</span>_sre.<span style="color: black;">SRE_Match</span> <span style="color: #008000;">object</span> at ...<span style="color: #66cc66;">&gt;</span></pre></div></div>

<p><big><strong>模块的属性和方法</strong></big></p>
<p><code>re</code>.<strong>compile</strong>(<em>pattern</em>[, <em>flags</em>])<br />
把一个正则表达式<em>pattern</em>编译成正则对象，以便可以用正则对象的<strong>match</strong>和<strong>search</strong>方法。<br />
得到的正则对象的行为（也就是模式）可以用<em>flags</em>来指定，值可以由几个下面的值OR得到。<br />
以下两段内容在语法上是等效的：</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">prog = <span style="color: #dc143c;">re</span>.<span style="color: #008000;">compile</span><span style="color: black;">&#40;</span>pattern<span style="color: black;">&#41;</span>
result = prog.<span style="color: black;">match</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">string</span><span style="color: black;">&#41;</span></pre></div></div>


<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">result = <span style="color: #dc143c;">re</span>.<span style="color: black;">match</span><span style="color: black;">&#40;</span>pattern, <span style="color: #dc143c;">string</span><span style="color: black;">&#41;</span></pre></div></div>

<p>区别是，用了<strong>re.compile</strong>以后，正则对象会得到保留，这样在需要多次运用这个正则对象的时候，效率会有较大的提升。再用上面用过的例子来演示一下，用相同的正则匹配相同的字符串，执行100万次，就体现出compile的效率了（数据来自我那1.86G CPU的神舟本本）：</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #dc143c;">timeit</span>.<span style="color: #dc143c;">timeit</span><span style="color: black;">&#40;</span>
...     <span style="color: black;">setup</span>=<span style="color: #483d8b;">''</span><span style="color: #483d8b;">'import re; reg = re.compile('</span><span style="color: #66cc66;">&lt;</span><span style="color: black;">&#40;</span><span style="color: #66cc66;">?</span>P<span style="color: #66cc66;">&lt;</span>tagname<span style="color: #66cc66;">&gt;</span>\w<span style="color: #66cc66;">*</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">&gt;</span>.<span style="color: #66cc66;">*&lt;</span>/<span style="color: black;">&#40;</span><span style="color: #66cc66;">?</span>P=tagname<span style="color: black;">&#41;</span><span style="color: #66cc66;">&gt;</span><span style="color: #483d8b;">')'</span><span style="color: #483d8b;">''</span>,
...     <span style="color: black;">stmt</span>=<span style="color: #483d8b;">''</span><span style="color: #483d8b;">'reg.match('</span><span style="color: #66cc66;">&lt;</span>h1<span style="color: #66cc66;">&gt;</span>xxx<span style="color: #66cc66;">&lt;</span>/h1<span style="color: #66cc66;">&gt;</span><span style="color: #483d8b;">')'</span><span style="color: #483d8b;">''</span>,
...     <span style="color: black;">number</span>=<span style="color: #ff4500;">1000000</span><span style="color: black;">&#41;</span>
<span style="color: #ff4500;">1.2062149047851562</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #dc143c;">timeit</span>.<span style="color: #dc143c;">timeit</span><span style="color: black;">&#40;</span>
...     <span style="color: black;">setup</span>=<span style="color: #483d8b;">''</span><span style="color: #483d8b;">'import re'</span><span style="color: #483d8b;">''</span>,
...     <span style="color: black;">stmt</span>=<span style="color: #483d8b;">''</span><span style="color: #483d8b;">'re.match('</span><span style="color: #66cc66;">&lt;</span><span style="color: black;">&#40;</span><span style="color: #66cc66;">?</span>P<span style="color: #66cc66;">&lt;</span>tagname<span style="color: #66cc66;">&gt;</span>\w<span style="color: #66cc66;">*</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">&gt;</span>.<span style="color: #66cc66;">*&lt;</span>/<span style="color: black;">&#40;</span><span style="color: #66cc66;">?</span>P=tagname<span style="color: black;">&#41;</span><span style="color: #66cc66;">&gt;</span><span style="color: #483d8b;">', '</span><span style="color: #66cc66;">&lt;</span>h1<span style="color: #66cc66;">&gt;</span>xxx<span style="color: #66cc66;">&lt;</span>/h1<span style="color: #66cc66;">&gt;</span><span style="color: #483d8b;">')'</span><span style="color: #483d8b;">''</span>,
...     <span style="color: black;">number</span>=<span style="color: #ff4500;">1000000</span><span style="color: black;">&#41;</span>
<span style="color: #ff4500;">4.4380838871002197</span></pre></div></div>

<p><code>re</code>.<strong>I</strong><br />
<code>re</code>.<strong>IGNORECASE</strong><br />
让正则表达式忽略大小写，这样一来，<code>[A-Z]</code>也可以匹配小写字母了。此特性和locale无关。</p>
<p><code>re</code>.<strong>L</strong><br />
<code>re</code>.<strong>LOCALE</strong><br />
让<code>\w</code>、<code>\W</code>、<code>\b</code>、<code>\B</code>、<code>\s</code>和<code>\S</code>依赖当前的locale。</p>
<p><code>re</code>.<strong>M</strong><br />
<code>re</code>.<strong>MULTILINE</strong><br />
影响<code>'^'</code>和<code>'$'</code>的行为，指定了以后，<code>'^'</code>会增加匹配每行的开始（也就是换行符后的位置）；<code>'$'</code>会增加匹配每行的结束（也就是换行符前的位置）。</p>
<p><code>re</code>.<strong>S</strong><br />
<code>re</code>.<strong>DOTALL</strong><br />
影响<code>'.'</code>的行为，平时<code>'.'</code>匹配除换行符以外的所有字符，指定了本标志以后，也可以匹配换行符。</p>
<p><code>re</code>.<strong>U</strong><br />
<code>re</code>.<strong>UNICODE</strong><br />
让<code>\w</code>、<code>\W</code>、<code>\b</code>、<code>\B</code>、<code>\d</code>、<code>\D</code>、<code>\s</code>和<code>\S</code>依赖Unicode库。</p>
<p><code>re</code>.<strong>X</strong><br />
<code>re</code>.<strong>VERBOSE</strong><br />
运用这个标志，你可以写出可读性更好的正则表达式：除了在方括号内的和被反斜杠转义的以外的所有空白字符，都将被忽略，而且每行中，一个正常的井号后的所有字符也被忽略，这样就可以方便地在正则表达式内部写注释了。也就是说，下面两个正则表达式是等效的：</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">a = <span style="color: #dc143c;">re</span>.<span style="color: #008000;">compile</span><span style="color: black;">&#40;</span>r<span style="color: #483d8b;">&quot;&quot;&quot;<span style="color: #000099; font-weight: bold;">\d</span> +  # the integral part
                   <span style="color: #000099; font-weight: bold;">\.</span>    # the decimal point
                   <span style="color: #000099; font-weight: bold;">\d</span> *  # some fractional digits&quot;&quot;&quot;</span>, <span style="color: #dc143c;">re</span>.<span style="color: black;">X</span><span style="color: black;">&#41;</span>
b = <span style="color: #dc143c;">re</span>.<span style="color: #008000;">compile</span><span style="color: black;">&#40;</span>r<span style="color: #483d8b;">&quot;<span style="color: #000099; font-weight: bold;">\d</span>+<span style="color: #000099; font-weight: bold;">\.</span><span style="color: #000099; font-weight: bold;">\d</span>*&quot;</span><span style="color: black;">&#41;</span></pre></div></div>

<p><code>re</code>.<strong>search</strong>(<em>pattern</em>, <em>string</em>[, <em>flags</em>])<br />
扫描<em>string</em>，看是否有个位置可以匹配正则表达式<em>pattern</em>。如果找到了，就返回一个<strong>MatchObject</strong>的实例，否则返回<strong>None</strong>，注意这和找到长度为0的子串含义是不一样的。搜索过程受<em>flags</em>的影响。</p>
<p><code>re</code>.<strong>match</strong>(<em>pattern</em>, <em>string</em>[, <em>flags</em>])<br />
如果字符串<em>string</em>的开头和正则表达式<em>pattern</em>匹配的话，返回一个相应的<strong>MatchObject</strong>的实例，否则返回<strong>None</strong></p>
<blockquote><p>注意：要在字符串的任意位置搜索的话，需要使用上面的<strong>search()</strong>。</p></blockquote>
<p><code>re</code>.<strong>split</strong>(<em>pattern</em>, <em>string</em>[, <em>maxsplit=0</em>])<br />
用匹配<em>pattern</em>的子串来分割<em>string</em>，如果<em>pattern</em>里使用了圆括号，那么被<em>pattern</em>匹配到的串也将作为返回值列表的一部分。如果<em>maxsplit</em>不为0，则最多被分割为<em>maxsplit</em>个子串，剩余部分将整个地被返回。</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #dc143c;">re</span>.<span style="color: black;">split</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'<span style="color: #000099; font-weight: bold;">\W</span>+'</span>, <span style="color: #483d8b;">'Words, words, words.'</span><span style="color: black;">&#41;</span>
<span style="color: black;">&#91;</span><span style="color: #483d8b;">'Words'</span>, <span style="color: #483d8b;">'words'</span>, <span style="color: #483d8b;">'words'</span>, <span style="color: #483d8b;">''</span><span style="color: black;">&#93;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #dc143c;">re</span>.<span style="color: black;">split</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'(<span style="color: #000099; font-weight: bold;">\W</span>+)'</span>, <span style="color: #483d8b;">'Words, words, words.'</span><span style="color: black;">&#41;</span>
<span style="color: black;">&#91;</span><span style="color: #483d8b;">'Words'</span>, <span style="color: #483d8b;">', '</span>, <span style="color: #483d8b;">'words'</span>, <span style="color: #483d8b;">', '</span>, <span style="color: #483d8b;">'words'</span>, <span style="color: #483d8b;">'.'</span>, <span style="color: #483d8b;">''</span><span style="color: black;">&#93;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #dc143c;">re</span>.<span style="color: black;">split</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'<span style="color: #000099; font-weight: bold;">\W</span>+'</span>, <span style="color: #483d8b;">'Words, words, words.'</span>, <span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>
<span style="color: black;">&#91;</span><span style="color: #483d8b;">'Words'</span>, <span style="color: #483d8b;">'words, words.'</span><span style="color: black;">&#93;</span></pre></div></div>

<p>如果正则有圆括号，并且可以匹配到字符串的开始位置的时候，返回值的第一项，会多出一个空字符串。匹配到字符结尾也是同样的道理：</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #dc143c;">re</span>.<span style="color: black;">split</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'(<span style="color: #000099; font-weight: bold;">\W</span>+)'</span>, <span style="color: #483d8b;">'...words, words...'</span><span style="color: black;">&#41;</span>
<span style="color: black;">&#91;</span><span style="color: #483d8b;">''</span>, <span style="color: #483d8b;">'...'</span>, <span style="color: #483d8b;">'words'</span>, <span style="color: #483d8b;">', '</span>, <span style="color: #483d8b;">'words'</span>, <span style="color: #483d8b;">'...'</span>, <span style="color: #483d8b;">''</span><span style="color: black;">&#93;</span></pre></div></div>

<p>注意，<em>split</em>不会被零长度的正则所分割，例如：</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #dc143c;">re</span>.<span style="color: black;">split</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'x*'</span>, <span style="color: #483d8b;">'foo'</span><span style="color: black;">&#41;</span>
<span style="color: black;">&#91;</span><span style="color: #483d8b;">'foo'</span><span style="color: black;">&#93;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #dc143c;">re</span>.<span style="color: black;">split</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;(?m)^$&quot;</span>, <span style="color: #483d8b;">&quot;foo<span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\n</span>bar<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: black;">&#41;</span>
<span style="color: black;">&#91;</span><span style="color: #483d8b;">'foo<span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\n</span>bar<span style="color: #000099; font-weight: bold;">\n</span>'</span><span style="color: black;">&#93;</span></pre></div></div>

<p><code>re</code>.<strong>findall</strong>(<em>pattern</em>, <em>string</em>[, <em>flags</em>])<br />
以列表的形式返回<em>string</em>里匹配<em>pattern</em>的不重叠的子串。<em>string</em>会被从左到右依次扫描，返回的列表也是从左到右一次匹配到的。如果<em>pattern</em>里含有<strong>组</strong>的话，那么会返回匹配到的组的列表；如果<em>pattern</em>里有多个组，那么各组会先组成一个元组，然后返回值将是一个元组的列表。<br />
由于这个函数不会涉及到<strong>MatchObject</strong>之类的概念，所以，对新手来说，应该是最好理解也最容易使用的一个函数了。下面就此来举几个简单的例子：</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">#简单的findall</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #dc143c;">re</span>.<span style="color: black;">findall</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'<span style="color: #000099; font-weight: bold;">\w</span>+'</span>, <span style="color: #483d8b;">'hello, world!'</span><span style="color: black;">&#41;</span>
<span style="color: black;">&#91;</span><span style="color: #483d8b;">'hello'</span>, <span style="color: #483d8b;">'world'</span><span style="color: black;">&#93;</span>
<span style="color: #808080; font-style: italic;">#这个返回的就是元组的列表</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #dc143c;">re</span>.<span style="color: black;">findall</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'(<span style="color: #000099; font-weight: bold;">\d</span>+)<span style="color: #000099; font-weight: bold;">\.</span>(<span style="color: #000099; font-weight: bold;">\d</span>+)<span style="color: #000099; font-weight: bold;">\.</span>(<span style="color: #000099; font-weight: bold;">\d</span>+)<span style="color: #000099; font-weight: bold;">\.</span>(<span style="color: #000099; font-weight: bold;">\d</span>+)'</span>, <span style="color: #483d8b;">'My IP is 192.168.0.2, and your is 192.168.0.3.'</span><span style="color: black;">&#41;</span>
<span style="color: black;">&#91;</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'192'</span>, <span style="color: #483d8b;">'168'</span>, <span style="color: #483d8b;">'0'</span>, <span style="color: #483d8b;">'2'</span><span style="color: black;">&#41;</span>, <span style="color: black;">&#40;</span><span style="color: #483d8b;">'192'</span>, <span style="color: #483d8b;">'168'</span>, <span style="color: #483d8b;">'0'</span>, <span style="color: #483d8b;">'3'</span><span style="color: black;">&#41;</span><span style="color: black;">&#93;</span></pre></div></div>

<p><code>re</code>.<strong> finditer</strong>(<em>pattern</em>, <em>string</em>[, <em>flags</em>])<br />
和上面的<strong>findall()</strong>类似，但返回的是<strong>MatchObject</strong>的实例的迭代器。<br />
还是例子说明问题：<br />
>>> for m in re.finditer('\w+', 'hello, world!'):<br />
...     print m.group()<br />
...<br />
hello<br />
world
</pre>
<p><code>re</code>.<strong>sub</strong>(<em>pattern</em>, <em>repl</em>, <em>string</em>[, <em>count</em>])<br />
替换，将<em>string</em>里，匹配<em>pattern</em>的部分，用<em>repl</em>替换掉，最多替换<em>count</em>次（剩余的匹配将不做处理），然后返回替换后的字符串。如果<em>string</em>里没有可以匹配<em>pattern</em>的串，将被原封不动地返回。<em>repl</em>可以是一个字符串，也可以是一个函数（也可以参考我以前的<a href="http://luy.li/2009/04/01/python_re/">例子</a>）。如果<em>repl</em>是个字符串，则其中的反斜杆会被处理过，比如 <code>\n</code> 会被转成换行符，反斜杆加数字会被替换成相应的组，比如 <code>\6</code> 表示<em>pattern</em>匹配到的第6个组的内容。<br />
例子：</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #dc143c;">re</span>.<span style="color: black;">sub</span><span style="color: black;">&#40;</span>r<span style="color: #483d8b;">'def<span style="color: #000099; font-weight: bold;">\s</span>+([a-zA-Z_][a-zA-Z_0-9]*)<span style="color: #000099; font-weight: bold;">\s</span>*<span style="color: #000099; font-weight: bold;">\(</span><span style="color: #000099; font-weight: bold;">\s</span>*<span style="color: #000099; font-weight: bold;">\)</span>:'</span>,
...        <span style="color: black;">r</span><span style="color: #483d8b;">'static PyObject*<span style="color: #000099; font-weight: bold;">\n</span>py_<span style="color: #000099; font-weight: bold;">\1</span>(void)<span style="color: #000099; font-weight: bold;">\n</span>{'</span>,
...        <span style="color: #483d8b;">'def myfunc():'</span><span style="color: black;">&#41;</span>
<span style="color: #483d8b;">'static PyObject*<span style="color: #000099; font-weight: bold;">\n</span>py_myfunc(void)<span style="color: #000099; font-weight: bold;">\n</span>{'</span></pre></div></div>

<p>如果<em>repl</em>是个函数，每次<em>pattern</em>被匹配到的时候，都会被调用一次，传入一个匹配到的<strong>MatchObject</strong>对象，需要返回一个字符串，在匹配到的位置，就填入返回的字符串。<br />
例子：</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">def</span> dashrepl<span style="color: black;">&#40;</span>matchobj<span style="color: black;">&#41;</span>:
...     <span style="color: #ff7700;font-weight:bold;">if</span> matchobj.<span style="color: black;">group</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span> == <span style="color: #483d8b;">'-'</span>: <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #483d8b;">' '</span>
...     <span style="color: #ff7700;font-weight:bold;">else</span>: <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #483d8b;">'-'</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #dc143c;">re</span>.<span style="color: black;">sub</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'-{1,2}'</span>, dashrepl, <span style="color: #483d8b;">'pro----gram-files'</span><span style="color: black;">&#41;</span>
<span style="color: #483d8b;">'pro--gram files'</span></pre></div></div>

<p>零长度的匹配也会被替换，比如：</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #dc143c;">re</span>.<span style="color: black;">sub</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'x*'</span>, <span style="color: #483d8b;">'-'</span>, <span style="color: #483d8b;">'abcxxd'</span><span style="color: black;">&#41;</span>
<span style="color: #483d8b;">'-a-b-c-d-'</span></pre></div></div>

<p>特殊地，在替换字符串里，如果有<code>\g<name></code>这样的写法，将匹配正则的命名组（前面介绍过的，<code>(?P<name>...)</code>这样定义出来的东西）。<code>\g<number></code>这样的写法，也是数字的组，也就是说，<code>\g<2></code>一般和<code>\2</code>是等效的，但是万一你要在<code>\2</code>后面紧接着写上字面意义的0，你就不能写成<code>\20</code>了（因为这代表第20个组），这时候必须写成<code>\g<2>0</code>，另外，<code>\g<0></code>代表匹配到的整个子串。<br />
例子：</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #dc143c;">re</span>.<span style="color: black;">sub</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'-(<span style="color: #000099; font-weight: bold;">\d</span>+)-'</span>, <span style="color: #483d8b;">'-<span style="color: #000099; font-weight: bold;">\g</span>&lt;1&gt;0<span style="color: #000099; font-weight: bold;">\g</span>&lt;0&gt;'</span>, <span style="color: #483d8b;">'a-11-b-22-c'</span><span style="color: black;">&#41;</span>
<span style="color: #483d8b;">'a-110-11-b-220-22-c'</span></pre></div></div>

<p><code>re</code>.<strong>subn</strong>(<em>pattern</em>, <em>repl</em>, <em>string</em>[, <em>count</em>])<br />
跟上面的<code>sub()</code>函数一样，只是它返回的是一个元组 <code>(新字符串, 匹配到的次数)</code><br />
，还是用例子说话：</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #dc143c;">re</span>.<span style="color: black;">subn</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'-(<span style="color: #000099; font-weight: bold;">\d</span>+)-'</span>, <span style="color: #483d8b;">'-<span style="color: #000099; font-weight: bold;">\g</span>&lt;1&gt;0<span style="color: #000099; font-weight: bold;">\g</span>&lt;0&gt;'</span>, <span style="color: #483d8b;">'a-11-b-22-c'</span><span style="color: black;">&#41;</span>
<span style="color: black;">&#40;</span><span style="color: #483d8b;">'a-110-11-b-220-22-c'</span>, <span style="color: #ff4500;">2</span><span style="color: black;">&#41;</span></pre></div></div>

<p><code>re</code>.<strong>escape</strong>(<em>string</em>)<br />
把<em>string</em>中，除了字母和数字以外的字符，都加上反斜杆。</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #dc143c;">re</span>.<span style="color: black;">escape</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'abc123_@#$'</span><span style="color: black;">&#41;</span>
abc123\_\@\<span style="color: #808080; font-style: italic;">#\$</span></pre></div></div>

<p><em>exception</em> <code>re</code>.<strong>error</strong><br />
如果字符串不能被成功编译成正则表达式或者正则表达式在匹配过程中出错了，都会抛出此异常。但是如果正则表达式没有匹配到任何文本，是不会抛出这个异常的。</p>
<p><big><strong>正则对象</strong></big></p>
<p>正则对象由<code>re</code>.<strong>compile()</strong>返回。它有如下的属性和方法。</p>
<p><strong>match</strong>(<em>string</em>[, <em>pos</em>[, <em>endpos</em>]])<br />
作用和模块的<strong>match()</strong>函数类似，区别就是后面两个参数。<br />
<em>pos</em>是开始搜索的位置，默认为0。<em>endpos</em>是搜索的结束位置，如果<em>endpos</em>比<em>pos</em>还小的话，结果肯定是空的。也就是说只有<em>pos</em> 到 <em>endpos</em>-1 位置的字符串将会被搜索。<br />
例子：</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> pattern = <span style="color: #dc143c;">re</span>.<span style="color: #008000;">compile</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;o&quot;</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> pattern.<span style="color: black;">match</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;dog&quot;</span><span style="color: black;">&#41;</span>      <span style="color: #808080; font-style: italic;"># 开始位置不是o，所以不匹配</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> pattern.<span style="color: black;">match</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;dog&quot;</span>, <span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>   <span style="color: #808080; font-style: italic;"># 第二个字符是o，所以匹配</span>
<span style="color: #66cc66;">&lt;</span>_sre.<span style="color: black;">SRE_Match</span> <span style="color: #008000;">object</span> at ...<span style="color: #66cc66;">&gt;</span></pre></div></div>

<p><strong>search</strong>(<em>string</em>[, <em>pos</em>[, <em>endpos</em>]])<br />
作用和模块的<strong>search()</strong>函数类似，<em>pos</em>和<em>endpos</em>参数和上面的<strong>match()</strong>函数类似。</p>
<p><strong>split</strong>(<em>string</em>[, <em>maxsplit</em>=0])<br />
<strong>findall</strong>(<em>string</em>[, <em>pos</em>[, <em>endpos</em>]])<br />
<strong>finditer</strong>(<em>string</em>[, <em>pos</em>[, <em>endpos</em>]])<br />
<strong>sub</strong>(<em>repl</em>, <em>string</em>[, <em>count=0</em>])<br />
<strong>subn</strong>(<em>repl</em>, <em>string</em>[, <em>count=0</em>])<br />
这几个函数，都和模块的相应函数一致。</p>
<p><strong>flags</strong><br />
编译本RE时，指定的标志位，如果未指定任何标志位，则为0。</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> pattern = <span style="color: #dc143c;">re</span>.<span style="color: #008000;">compile</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;o&quot;</span>, <span style="color: #dc143c;">re</span>.<span style="color: black;">S</span>|re.<span style="color: black;">U</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> pattern.<span style="color: black;">flags</span>
<span style="color: #ff4500;">48</span></pre></div></div>

<p><strong>groups</strong><br />
RE所含有的组的个数。</p>
<p><strong>groupindex</strong><br />
一个字典，定义了命名组的名字和序号之间的关系。<br />
例子：</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">这个正则有<span style="color: #ff4500;">3</span>个组，如果匹配到，第一个叫区号，最后一个叫分机号，中间的那个未命名
<span style="color: #66cc66;">&gt;&gt;&gt;</span> pattern = <span style="color: #dc143c;">re</span>.<span style="color: #008000;">compile</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;(?P&lt;quhao&gt;<span style="color: #000099; font-weight: bold;">\d</span>+)-(<span style="color: #000099; font-weight: bold;">\d</span>+)-(?P&lt;fenjihao&gt;<span style="color: #000099; font-weight: bold;">\d</span>+)&quot;</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> pattern.<span style="color: black;">groups</span>
<span style="color: #ff4500;">3</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> pattern.<span style="color: black;">groupindex</span>
<span style="color: black;">&#123;</span><span style="color: #483d8b;">'fenjihao'</span>: <span style="color: #ff4500;">3</span>, <span style="color: #483d8b;">'quhao'</span>: <span style="color: #ff4500;">1</span><span style="color: black;">&#125;</span></pre></div></div>

<p><strong>pattern</strong><br />
建立本RE的原始字符串，相当于源代码了，呵呵。<br />
还是上面这个正则，可以看到，会原样返回：</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">print</span> pattern.<span style="color: black;">pattern</span>
<span style="color: black;">&#40;</span><span style="color: #66cc66;">?</span>P<span style="color: #66cc66;">&lt;</span>quhao<span style="color: #66cc66;">&gt;</span>\d+<span style="color: black;">&#41;</span>-<span style="color: black;">&#40;</span>\d+<span style="color: black;">&#41;</span>-<span style="color: black;">&#40;</span><span style="color: #66cc66;">?</span>P<span style="color: #66cc66;">&lt;</span>fenjihao<span style="color: #66cc66;">&gt;</span>\d+<span style="color: black;">&#41;</span></pre></div></div>

<p><big><strong>Match对象</strong></big></p>
<p><code>re</code>.<strong>MatchObject</strong>被用于布尔判断的时候，始终返回True，所以你用 if 语句来判断某个 <strong>match()</strong> 是否成功是安全的。<br />
它有以下方法和属性：</p>
<p><strong>expand</strong>(<em>template</em>)<br />
用<em>template</em>做为模板，将<strong>MatchObject</strong>展开，就像<strong>sub()</strong>里的行为一样，看例子：</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> m = <span style="color: #dc143c;">re</span>.<span style="color: black;">match</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'a=(<span style="color: #000099; font-weight: bold;">\d</span>+)'</span>, <span style="color: #483d8b;">'a=100'</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> m.<span style="color: black;">expand</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'above a is <span style="color: #000099; font-weight: bold;">\g</span>&lt;1&gt;'</span><span style="color: black;">&#41;</span>
<span style="color: #483d8b;">'above a is 100'</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> m.<span style="color: black;">expand</span><span style="color: black;">&#40;</span>r<span style="color: #483d8b;">'above a is <span style="color: #000099; font-weight: bold;">\1</span>'</span><span style="color: black;">&#41;</span>
<span style="color: #483d8b;">'above a is 100'</span></pre></div></div>

<p><strong>group</strong>([<em>group1</em>, <em>...</em>])<br />
返回一个或多个子组。如果参数为一个，就返回一个子串；如果参数有多个，就返回多个子串注册的元组。如果不传任何参数，效果和传入一个0一样，将返回整个匹配。如果某个<em>groupN</em>未匹配到，相应位置会返回<strong>None</strong>。如果某个<em>groupN</em>是负数或者大于group的总数，则会抛出<strong>IndexError</strong>异常。</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> m = <span style="color: #dc143c;">re</span>.<span style="color: black;">match</span><span style="color: black;">&#40;</span>r<span style="color: #483d8b;">&quot;(<span style="color: #000099; font-weight: bold;">\w</span>+) (<span style="color: #000099; font-weight: bold;">\w</span>+)&quot;</span>, <span style="color: #483d8b;">&quot;Isaac Newton, physicist&quot;</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> m.<span style="color: black;">group</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span>       <span style="color: #808080; font-style: italic;"># 整个匹配</span>
<span style="color: #483d8b;">'Isaac Newton'</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> m.<span style="color: black;">group</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>       <span style="color: #808080; font-style: italic;"># 第一个子串</span>
<span style="color: #483d8b;">'Isaac'</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> m.<span style="color: black;">group</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">2</span><span style="color: black;">&#41;</span>       <span style="color: #808080; font-style: italic;"># 第二个子串</span>
<span style="color: #483d8b;">'Newton'</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> m.<span style="color: black;">group</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span>, <span style="color: #ff4500;">2</span><span style="color: black;">&#41;</span>    <span style="color: #808080; font-style: italic;"># 多个子串组成的元组</span>
<span style="color: black;">&#40;</span><span style="color: #483d8b;">'Isaac'</span>, <span style="color: #483d8b;">'Newton'</span><span style="color: black;">&#41;</span></pre></div></div>

<p>如果有其中有用<code>(?P<name>...)</code>这种语法命名过的子串的话，相应的<em>groupN</em>也可以是名字字符串。例如：</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> m = <span style="color: #dc143c;">re</span>.<span style="color: black;">match</span><span style="color: black;">&#40;</span>r<span style="color: #483d8b;">&quot;(?P&lt;first_name&gt;<span style="color: #000099; font-weight: bold;">\w</span>+) (?P&lt;last_name&gt;<span style="color: #000099; font-weight: bold;">\w</span>+)&quot;</span>, <span style="color: #483d8b;">&quot;Malcolm Reynolds&quot;</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> m.<span style="color: black;">group</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'first_name'</span><span style="color: black;">&#41;</span>
<span style="color: #483d8b;">'Malcolm'</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> m.<span style="color: black;">group</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'last_name'</span><span style="color: black;">&#41;</span>
<span style="color: #483d8b;">'Reynolds'</span></pre></div></div>

<p>如果某个组被匹配到多次，那么只有最后一次的数据，可以被提取到：</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> m = <span style="color: #dc143c;">re</span>.<span style="color: black;">match</span><span style="color: black;">&#40;</span>r<span style="color: #483d8b;">&quot;(..)+&quot;</span>, <span style="color: #483d8b;">&quot;a1b2c3&quot;</span><span style="color: black;">&#41;</span>  <span style="color: #808080; font-style: italic;"># 匹配到3次</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> m.<span style="color: black;">group</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>                        <span style="color: #808080; font-style: italic;"># 返回的是最后一次</span>
<span style="color: #483d8b;">'c3'</span></pre></div></div>

<p><strong>groups</strong>([<em>default</em>])<br />
返回一个由所有匹配到的子串组成的元组。<em>default</em>参数，用于给那些没有匹配到的组做默认值，它的默认值是<strong>None</strong><br />
例如：</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> m = <span style="color: #dc143c;">re</span>.<span style="color: black;">match</span><span style="color: black;">&#40;</span>r<span style="color: #483d8b;">&quot;(<span style="color: #000099; font-weight: bold;">\d</span>+)<span style="color: #000099; font-weight: bold;">\.</span>(<span style="color: #000099; font-weight: bold;">\d</span>+)&quot;</span>, <span style="color: #483d8b;">&quot;24.1632&quot;</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> m.<span style="color: black;">groups</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: black;">&#40;</span><span style="color: #483d8b;">'24'</span>, <span style="color: #483d8b;">'1632'</span><span style="color: black;">&#41;</span></pre></div></div>

<p><em>default</em>的作用：</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> m = <span style="color: #dc143c;">re</span>.<span style="color: black;">match</span><span style="color: black;">&#40;</span>r<span style="color: #483d8b;">&quot;(<span style="color: #000099; font-weight: bold;">\d</span>+)<span style="color: #000099; font-weight: bold;">\.</span>?(<span style="color: #000099; font-weight: bold;">\d</span>+)?&quot;</span>, <span style="color: #483d8b;">&quot;24&quot;</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> m.<span style="color: black;">groups</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>      <span style="color: #808080; font-style: italic;"># 第二个默认是None</span>
<span style="color: black;">&#40;</span><span style="color: #483d8b;">'24'</span>, <span style="color: #008000;">None</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> m.<span style="color: black;">groups</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'0'</span><span style="color: black;">&#41;</span>   <span style="color: #808080; font-style: italic;"># 现在默认是0了</span>
<span style="color: black;">&#40;</span><span style="color: #483d8b;">'24'</span>, <span style="color: #483d8b;">'0'</span><span style="color: black;">&#41;</span></pre></div></div>

<p><strong>groupdict</strong>([<em>default</em>])<br />
返回一个包含所有命名组的名字和子串的字典，<em>default</em>参数，用于给那些没有匹配到的组做默认值，它的默认值是<strong>None</strong>，例如：</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> m = <span style="color: #dc143c;">re</span>.<span style="color: black;">match</span><span style="color: black;">&#40;</span>r<span style="color: #483d8b;">&quot;(?P&lt;first_name&gt;<span style="color: #000099; font-weight: bold;">\w</span>+) (?P&lt;last_name&gt;<span style="color: #000099; font-weight: bold;">\w</span>+)&quot;</span>, <span style="color: #483d8b;">&quot;Malcolm Reynolds&quot;</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> m.<span style="color: black;">groupdict</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: black;">&#123;</span><span style="color: #483d8b;">'first_name'</span>: <span style="color: #483d8b;">'Malcolm'</span>, <span style="color: #483d8b;">'last_name'</span>: <span style="color: #483d8b;">'Reynolds'</span><span style="color: black;">&#125;</span></pre></div></div>

<p><strong>start</strong>([<strong>group</strong>])<br />
<strong>end</strong>([<em>group</em>])<br />
返回的是：被组<em>group</em>匹配到的子串在原字符串中的位置。如果不指定<em>group</em>或<em>group</em>指定为0，则代表整个匹配。如果<em>group</em>未匹配到，则返回 <code>-1</code>。<br />
对于指定的m和g，<code>m.group(g)</code>和<code>m.string[m.start(g):m.end(g)]</code>等效。<br />
注意：如果<em>group</em>匹配到空字符串，<em>m.start(group)</em>和<em>m.end(group)</em>将相等。<br />
例如：</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> m = <span style="color: #dc143c;">re</span>.<span style="color: black;">search</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'b(c?)'</span>, <span style="color: #483d8b;">'cba'</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> m.<span style="color: black;">start</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span>
<span style="color: #ff4500;">1</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> m.<span style="color: black;">end</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span>
<span style="color: #ff4500;">2</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> m.<span style="color: black;">start</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>
<span style="color: #ff4500;">2</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> m.<span style="color: black;">end</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>
<span style="color: #ff4500;">2</span></pre></div></div>

<p>下面是一个把email地址里的“remove_this”去掉的例子：</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #dc143c;">email</span> = <span style="color: #483d8b;">&quot;tony@tiremove_thisger.net&quot;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> m = <span style="color: #dc143c;">re</span>.<span style="color: black;">search</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;remove_this&quot;</span>, <span style="color: #dc143c;">email</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #dc143c;">email</span><span style="color: black;">&#91;</span>:m.<span style="color: black;">start</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#93;</span> + <span style="color: #dc143c;">email</span><span style="color: black;">&#91;</span>m.<span style="color: black;">end</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:<span style="color: black;">&#93;</span>
<span style="color: #483d8b;">'tony@tiger.net'</span></pre></div></div>

<p><strong>span</strong>([<em>group</em>])<br />
返回一个元组： <code>(m.start(group), m.end(group))</code></p>
<p><strong>pos</strong><br />
就是传给RE对象的<strong>search()</strong>或<strong>match()</strong>方法的参数<em>pos</em>，代表RE开始搜索字符串的位置。</p>
<p><strong>endpos</strong><br />
就是传给RE对象的<strong>search()</strong>或<strong>match()</strong>方法的参数<em>endpos</em>，代表RE搜索字符串的结束位置。</p>
<p><strong>lastindex</strong><br />
最后一次匹配到的组的数字序号，如果没有匹配到，将得到<strong>None</strong>。<br />
例如：<code>(a)b</code>、<code>((a)(b))</code>和<code>((ab))</code>正则去匹配<code>'ab'</code>的话，得到的<strong>lastindex</strong>为1。而用<code>(a)(b)</code>去匹配<code>'ab'</code>的话，得到的<strong>lastindex</strong>为2。</p>
<p><strong>lastgroup</strong><br />
最后一次匹配到的组的名字，如果没有匹配到或者最后的组没有名字，将得到<strong>None</strong>。</p>
<p><strong>re</strong><br />
得到本Match对象的正则表达式对象，也就是执行<strong>search()</strong>或<strong>match()</strong>的对象。</p>
<p><strong>string</strong><br />
传给<strong>search()</strong>或<strong>match()</strong>的字符串。</p>
<p><br/></p>
<p>后面的例子就略了吧，文中已经加了很多我自己的例子了，需要更多例子的话，参照英文原文吧。<br />
最后，感谢我的老婆辛苦地帮我校对，哈哈。</p>
]]></content:encoded>
			<wfw:commentRss>http://luy.li/2010/05/12/python-re/feed/</wfw:commentRss>
		<slash:comments>15</slash:comments>
		</item>
		<item>
		<title>python程序，在windows下调用子进程，不产生cmd窗口的办法</title>
		<link>http://luy.li/2010/04/24/python_windows_no_cmd/</link>
		<comments>http://luy.li/2010/04/24/python_windows_no_cmd/#comments</comments>
		<pubDate>Sat, 24 Apr 2010 12:16:47 +0000</pubDate>
		<dc:creator>bones7456</dc:creator>
				<category><![CDATA[编程相关]]></category>

		<guid isPermaLink="false">http://li2z.cn/?p=1479</guid>
		<description><![CDATA[python写的GTK程序，会有这样一个怪现象，本来在cmd下用 python xxx.py 启动，还好好的，但是用py2exe编译以后，再用subprocess调用命令行程序的时候，就发现一个黑乎乎的cmd窗口跳出来了，特别难看，要消除它其实也还比较容易，但是要使用startupinfo这个windows only的参数，以下代码是linux和windows通用的例子：

if os.name == 'nt':
    startupinfo = subprocess.STARTUPINFO&#40;&#41;
    startupinfo.dwFlags &#124;= subprocess.STARTF_USESHOWWINDOW
    startupinfo.wShowWindow = subprocess.SW_HIDE
else:
    startupinfo = None
subprocess.Popen&#40;要运行的命令, startupinfo=startupinfo&#41;

经过今天的修改，gmbox 0.2.4 beta 已经基本能在win下运行了，哈哈。
PS：贴一个ultraedit的python语法高亮文件，偶尔在win下改改代码可能会用到，在这里。
]]></description>
			<content:encoded><![CDATA[<p>python写的GTK程序，会有这样一个怪现象，本来在cmd下用 python xxx.py 启动，还好好的，但是用<a href="http://luy.li/2009/06/20/py2exe/">py2exe编译</a>以后，再用<a href="http://luy.li/2010/04/14/python_subprocess/">subprocess</a>调用命令行程序的时候，就发现一个黑乎乎的cmd窗口跳出来了，特别难看，要消除它其实也还比较容易，但是要使用startupinfo这个windows only的参数，以下代码是linux和windows通用的例子：</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #dc143c;">os</span>.<span style="color: black;">name</span> == <span style="color: #483d8b;">'nt'</span>:
    startupinfo = <span style="color: #dc143c;">subprocess</span>.<span style="color: black;">STARTUPINFO</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    startupinfo.<span style="color: black;">dwFlags</span> |= <span style="color: #dc143c;">subprocess</span>.<span style="color: black;">STARTF_USESHOWWINDOW</span>
    startupinfo.<span style="color: black;">wShowWindow</span> = <span style="color: #dc143c;">subprocess</span>.<span style="color: black;">SW_HIDE</span>
<span style="color: #ff7700;font-weight:bold;">else</span>:
    startupinfo = <span style="color: #008000;">None</span>
<span style="color: #dc143c;">subprocess</span>.<span style="color: black;">Popen</span><span style="color: black;">&#40;</span>要运行的命令, startupinfo=startupinfo<span style="color: black;">&#41;</span></pre></div></div>

<p>经过今天的修改，gmbox 0.2.4 beta 已经基本能在win下运行了，哈哈。</p>
<p>PS：贴一个ultraedit的python语法高亮文件，偶尔在win下改改代码可能会用到，在<a href="http://www.ultraedit.com/forums/download/file.php?id=184&#038;sid=ed28286fa6063f3f0c9dbee486a361e3">这里</a>。</p>
]]></content:encoded>
			<wfw:commentRss>http://luy.li/2010/04/24/python_windows_no_cmd/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>python中的子进程 subprocess</title>
		<link>http://luy.li/2010/04/14/python_subprocess/</link>
		<comments>http://luy.li/2010/04/14/python_subprocess/#comments</comments>
		<pubDate>Wed, 14 Apr 2010 09:19:48 +0000</pubDate>
		<dc:creator>bones7456</dc:creator>
				<category><![CDATA[编程相关]]></category>

		<guid isPermaLink="false">http://li2z.cn/?p=1448</guid>
		<description><![CDATA[此文和python 内建函数一样，内容全部出自python官方文档，但是会有自己的理解，并非单纯的翻译。所以，如果我理解有误，欢迎指正，谢谢。
从python2.4版本开始，你就可以用可以用subprocess这个模块来产生子进程，并连接到子进程的标准输入/输出/错误中去，还可以得到子进程的返回值。subprocess意在替代其他几个老的模块或者函数，比如：
os.system
os.spawn*
os.popen*
popen2.*
commands.*
下面将一一介绍如何用subprocess来替代这些函数或者模块。
使用subprocess模块
本模块定义了一个类： Popen
class subprocess.Popen(args, bufsize=0, executable=None, stdin=None, stdout=None, stderr=None, preexec_fn=None, close_fds=False, shell=False, cwd=None, env=None, universal_newlines=False, startupinfo=None, creationflags=0)
各参数含义如下：
args需要是一个字符串，或者包含程序参数的列表。要执行的程序一般就是这个列表的第一项，或者是字符串本身。但是也可以用executable参数来明确指出。当executable参数不为空时，args里的第一项仍被认为是程序的“命令名”，不同于真正的可执行文件的文件名，这个“命令名”是一个用来显示的名称，例如执行*nix下的 ps 命令，显示出来的就是这个“命令名”。
在*nix下，当shell=False（默认）时，Popen使用os.execvp()来执行子程序。args一般要是一个列表。如果args是个字符串的话，会被当做是可执行文件的路径，这样就不能传入任何参数了。
注意：
shlex.split()可以被用于序列化复杂的命令参数，比如：

&#62;&#62;&#62; import shlex, subprocess
&#62;&#62;&#62; command_line = raw_input&#40;&#41;
/bin/vikings -input eggs.txt -output &#34;spam spam.txt&#34; -cmd &#34;echo '$MONEY'&#34;
&#62;&#62;&#62; args = shlex.split&#40;command_line&#41;
&#62;&#62;&#62; print args
&#91;'/bin/vikings', '-input', 'eggs.txt', '-output', 'spam spam.txt', '-cmd', &#34;echo '$MONEY'&#34;&#93;
&#62;&#62;&#62; p = subprocess.Popen&#40;args&#41; # 成功执行!

可以看到，空格分隔的选项（如-input）和参数（如eggs.txt）会被分割为列表里独立的项，但引号里的或者转义过的空格不在此列。这也有点像大多数shell的行为。

在*nix下，当shell=True时，如果args是个字符串，就使用shell来解释执行这个字符串。如果args是个列表，则第一项被视为命令，其余的都视为是给shell本身的参数。也就是说，等效于：

Popen&#40;&#91;'/bin/sh', '-c', args&#91;0&#93;, args&#91;1&#93;, ...&#93;&#41;

在windows下，Popen使用接受字符串参数的CreateProcess()来执行子程序。如果args是个列表，它会被先用list2cmdline()转换成字符串。
如果指定了bufsize参数，作用就和内建函数open()一样：0表示不缓冲，1表示行缓冲，其他正数表示近似的缓冲区字节数，负数表示使用系统默认值。默认是0。
executable参数指定要执行的程序。它很少会被用到：一般程序可以由args参数指定。如果shell=True，executable可以用于指定用哪个shell来执行（比如bash、csh、zsh等）。*nix下，默认是 [...]]]></description>
			<content:encoded><![CDATA[<p>此文和<a href="http://luy.li/2009/11/29/python-built-in-functions/">python 内建函数</a>一样，内容全部出自<a href="http://docs.python.org/library/subprocess.html">python官方文档</a>，但是会有自己的理解，并非单纯的翻译。所以，如果我理解有误，欢迎指正，谢谢。</p>
<p>从python2.4版本开始，你就可以用可以用<code>subprocess</code>这个模块来产生子进程，并连接到子进程的标准输入/输出/错误中去，还可以得到子进程的返回值。<code>subprocess</code>意在替代其他几个老的模块或者函数，比如：</p>
<blockquote><p>os.system<br />
os.spawn*<br />
os.popen*<br />
popen2.*<br />
commands.*</p></blockquote>
<p>下面将一一介绍如何用<code>subprocess</code>来替代这些函数或者模块。</p>
<p><big><strong>使用subprocess模块</strong></big></p>
<p>本模块定义了一个类： Popen</p>
<p><em>class</em> <code>subprocess</code>.<strong>Popen</strong>(<em>args</em>, <em>bufsize=0</em>, <em>executable=None</em>, <em>stdin=None</em>, <em>stdout=None</em>, <em>stderr=None</em>, <em>preexec_fn=None</em>, <em>close_fds=False</em>, <em>shell=False</em>, <em>cwd=None</em>, <em>env=None</em>, <em>universal_newlines=False</em>, <em>startupinfo=None</em>, <em>creationflags=0</em>)</p>
<p>各参数含义如下：</p>
<p><em>args</em>需要是一个字符串，或者包含程序参数的列表。要执行的程序一般就是这个列表的第一项，或者是字符串本身。但是也可以用<em>executable</em>参数来明确指出。当<em>executable</em>参数不为空时，<em>args</em>里的第一项仍被认为是程序的“命令名”，不同于真正的可执行文件的文件名，这个“命令名”是一个用来显示的名称，例如执行*nix下的 ps 命令，显示出来的就是这个“命令名”。</p>
<p>在*nix下，当<em>shell=False</em>（默认）时，Popen使用<a href="http://docs.python.org/library/os.html#os.execvp">os.execvp()</a>来执行子程序。<em>args</em>一般要是一个列表。如果<em>args</em>是个字符串的话，会被当做是可执行文件的路径，这样就不能传入任何参数了。</p>
<blockquote><p><strong>注意：</strong><br />
<a href="http://docs.python.org/library/shlex.html#shlex.split">shlex.split()</a>可以被用于序列化复杂的命令参数，比如：</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">shlex</span>, <span style="color: #dc143c;">subprocess</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> command_line = <span style="color: #008000;">raw_input</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
/bin/vikings -<span style="color: #008000;">input</span> eggs.<span style="color: black;">txt</span> -output <span style="color: #483d8b;">&quot;spam spam.txt&quot;</span> -<span style="color: #dc143c;">cmd</span> <span style="color: #483d8b;">&quot;echo '$MONEY'&quot;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> args = <span style="color: #dc143c;">shlex</span>.<span style="color: black;">split</span><span style="color: black;">&#40;</span>command_line<span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">print</span> args
<span style="color: black;">&#91;</span><span style="color: #483d8b;">'/bin/vikings'</span>, <span style="color: #483d8b;">'-input'</span>, <span style="color: #483d8b;">'eggs.txt'</span>, <span style="color: #483d8b;">'-output'</span>, <span style="color: #483d8b;">'spam spam.txt'</span>, <span style="color: #483d8b;">'-cmd'</span>, <span style="color: #483d8b;">&quot;echo '$MONEY'&quot;</span><span style="color: black;">&#93;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> p = <span style="color: #dc143c;">subprocess</span>.<span style="color: black;">Popen</span><span style="color: black;">&#40;</span>args<span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;"># 成功执行!</span></pre></div></div>

<p>可以看到，空格分隔的选项（如-input）和参数（如eggs.txt）会被分割为列表里独立的项，但引号里的或者转义过的空格不在此列。这也有点像大多数shell的行为。
</p></blockquote>
<p>在*nix下，当<em>shell=True</em>时，如果<em>args</em>是个字符串，就使用shell来解释执行这个字符串。如果<em>args</em>是个列表，则第一项被视为命令，其余的都视为是给shell本身的参数。也就是说，等效于：</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">Popen<span style="color: black;">&#40;</span><span style="color: black;">&#91;</span><span style="color: #483d8b;">'/bin/sh'</span>, <span style="color: #483d8b;">'-c'</span>, args<span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span>, args<span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span>, ...<span style="color: black;">&#93;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>在windows下，Popen使用接受字符串参数的CreateProcess()来执行子程序。如果<em>args</em>是个列表，它会被先用<strong>list2cmdline()</strong>转换成字符串。</p>
<p>如果指定了<em>bufsize</em>参数，作用就和内建函数open()一样：0表示不缓冲，1表示行缓冲，其他正数表示近似的缓冲区字节数，负数表示使用系统默认值。默认是0。</p>
<p><em>executable</em>参数指定要执行的程序。它很少会被用到：一般程序可以由<em>args</em>参数指定。如果<code>shell=True</code>，<em>executable</em>可以用于指定用哪个shell来执行（比如bash、csh、zsh等）。*nix下，默认是 /bin/sh ，windows下，就是环境变量 <strong>COMSPEC</strong> 的值。windows下，只有当你要执行的命令确实是shell内建命令（比如<code>dir</code>，<code>copy</code>等）时，你才需要指定<code>shell=True</code>，而当你要执行一个基于命令行的批处理脚本的时候，不需要指定此项。</p>
<p><em>stdin</em>、<em>stdout</em>和<em>stderr</em>分别表示子程序的标准输入、标准输出和标准错误。可选的值有<a href="http://docs.python.org/library/subprocess.html#subprocess.PIPE">PIPE</a>（见下面的描述）或者一个有效的文件描述符（其实是个正整数）或者一个文件对象，还有None。如果是PIPE，则表示需要创建一个新的管道，如果是None，不会做任何重定向工作，子进程的文件描述符会继承父进程的。另外，<em>stderr</em>的值还可以是<a href="http://docs.python.org/library/subprocess.html#subprocess.STDOUT">STDOUT</a>（见下），表示子进程的标准错误也输出到标准输出。</p>
<p>如果把<em>preexec_fn</em>设置为一个可调用的对象（比如函数），就会在子进程被执行前被调用。（仅限*nix）</p>
<p>如果把<em>close_fds</em>设置成True，*nix下会在开子进程前把除了0、1、2以外的文件描述符都先关闭。在Windows下也不会继承其他文件描述符。</p>
<p>如果把<em>shell</em>设置成True，指定的命令会在shell里解释执行，这个前面已经说得比较详细了。</p>
<p>如果<em>cwd</em>不是None，则会把<em>cwd</em>做为子程序的当前目录。注意，并不会把该目录做为可执行文件的搜索目录，所以不要把程序文件所在目录设置为<em>cwd</em>。</p>
<p>如果<em>env</em>不是None，则子程序的环境变量由<em>env</em>的值来设置，而不是默认那样继承父进程的环境变量。注意，即使你只在env里定义了某一个环境变量的值，也会阻止子程序得到其他的父进程的环境变量（也就是说，如果env里只有1项，那么子进程的环境变量就只有1个了）。例如：</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #dc143c;">subprocess</span>.<span style="color: black;">Popen</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'env'</span>, env=<span style="color: black;">&#123;</span><span style="color: #483d8b;">'xxx'</span>:<span style="color: #483d8b;">'123'</span>, <span style="color: #483d8b;">'yyy'</span>:<span style="color: #483d8b;">'zzz'</span><span style="color: black;">&#125;</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&lt;</span>subprocess.<span style="color: black;">Popen</span> <span style="color: #008000;">object</span> at 0xb694112c<span style="color: #66cc66;">&gt;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> xxx=<span style="color: #ff4500;">123</span>
yyy=zzz</pre></div></div>

<p>如果把<em>universal_newlines</em>设置成True，则子进程的stdout和stderr被视为文本对象，并且不管是*nix的行结束符（<code>'\n'</code>），还是老mac格式的行结束符（<code>'\r'</code>），还是windows格式的行结束符（<code>'\r\n'</code>）都将被视为 <code>'\n'</code> 。</p>
<p>如果指定了<em>startupinfo</em>和<em>creationflags</em>，将会被传递给后面的<code>CreateProcess()</code>函数，用于指定子程序的各种其他属性，比如主窗口样式或者是子进程的优先级等。（仅限Windows）</p>
<p>介绍完Popen的各参数，再来看下两个小东西：</p>
<p><code>subprocess</code>.<strong>PIPE</strong><br />
一个可以被用于Popen的<em>stdin</em>、<em>stdout</em>和<em>stderr</em>3个参数的特输值，表示需要创建一个新的管道。</p>
<p><code>subprocess</code>.<strong>STDOUT</strong><br />
一个可以被用于Popen的<em>stderr</em>参数的特输值，表示子程序的标准错误汇合到标准输出。</p>
<p><big>方便的函数</big></p>
<p><code>subprocess</code>.<strong>call</strong>(<em>*popenargs</em>, <em>**kwargs</em>)<br />
执行命令，并等待命令结束，再返回子进程的返回值。参数同Popen，因为打开 /usr/lib/python2.6/subprocess.py 你就知道，去掉文档，其实是这样的：</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> call<span style="color: black;">&#40;</span><span style="color: #66cc66;">*</span>popenargs, <span style="color: #66cc66;">**</span>kwargs<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">return</span> Popen<span style="color: black;">&#40;</span><span style="color: #66cc66;">*</span>popenargs, <span style="color: #66cc66;">**</span>kwargs<span style="color: black;">&#41;</span>.<span style="color: black;">wait</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></div></div>

<p><code>subprocess</code>.<strong>check_call</strong>(<em>*popenargs</em>, <em>**kwargs</em>)<br />
执行上面的call命令，并检查返回值，如果子进程返回非0，则会抛出<strong>CalledProcessError</strong>异常，这个异常会有个<strong>returncode</strong>属性，记录子进程的返回值。</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #dc143c;">subprocess</span>.<span style="color: black;">check_call</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'false'</span><span style="color: black;">&#41;</span>
Traceback <span style="color: black;">&#40;</span>most recent call last<span style="color: black;">&#41;</span>:
  File <span style="color: #483d8b;">&quot;&lt;stdin&gt;&quot;</span>, line <span style="color: #ff4500;">1</span>, <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #66cc66;">&lt;</span>module<span style="color: #66cc66;">&gt;</span>
  File <span style="color: #483d8b;">&quot;/usr/lib/python2.6/subprocess.py&quot;</span>, line <span style="color: #ff4500;">498</span>, <span style="color: #ff7700;font-weight:bold;">in</span> check_call
    <span style="color: #ff7700;font-weight:bold;">raise</span> CalledProcessError<span style="color: black;">&#40;</span>retcode, <span style="color: #dc143c;">cmd</span><span style="color: black;">&#41;</span>
<span style="color: #dc143c;">subprocess</span>.<span style="color: black;">CalledProcessError</span>: Command <span style="color: #483d8b;">'false'</span> returned non-zero exit status <span style="color: #ff4500;">1</span></pre></div></div>

<p><big>异常</big></p>
<p>子进程里抛出的异常，会在父进程中再次抛出。并且，异常会有个叫<strong>child_traceback</strong>的额外属性，这是个包含子进程错误traceback信息的字符串。</p>
<p>遇到最多的错误回是 OSError，比如执行了一个并不存在的子程序就会产生OSError。</p>
<p>另外，如果使用错误的参数调用Popen，会抛出ValueError。</p>
<p>当子程序返回非0时，check_call()还会产生<strong>CalledProcessError</strong>异常。</p>
<p><big>安全性</big></p>
<p>不像其他的popen函数，本模块不会偷偷地调用/bin/sh来解释命令，也就是说，命令中的每一个字符都会被安全地传递到子进程里。</p>
<p><big><strong>Popen对象</strong></big></p>
<p>Popen对象有以下方法：</p>
<p><code>Popen</code>.<strong>poll()</strong><br />
检查子进程是否已结束，设置并返回 <strong>returncode</strong> 属性。</p>
<p><code>Popen</code>.<strong>wait()</strong><br />
等待子进程结束，设置并返回 <strong>returncode</strong> 属性。</p>
<blockquote><p><strong>注意：</strong>如果子进程输出了大量数据到stdout或者stderr的管道，并达到了系统pipe的缓存大小的话，子进程会等待父进程读取管道，而父进程此时正wait着的话，将会产生传说中的死锁，后果是非常严重滴。建议使用<strong>communicate()</strong>来避免这种情况的发生。</p></blockquote>
<p><code>Popen</code>.<strong>communicate</strong>(<em>input</em>=<em>None</em>)<br />
和子进程交互：发送数据到stdin，并从stdout和stderr读数据，直到收到EOF。等待子进程结束。可选的<em>input</em>如有有的话，要为字符串类型。<br />
此函数返回一个元组： (<code>stdoutdata</code>, <code>stderrdata</code>) 。<br />
注意，要给子进程的stdin发送数据，则Popen的时候，stdin要为PIPE；同理，要可以收数据的话，stdout或者stderr也要为PIPE。</p>
<blockquote><p>注意：读到的数据会被缓存在内存里，所以数据量非常大的时候要小心了。</p></blockquote>
<p><code>Popen</code>.<strong>send_signal</strong>(<em>signal</em>)<br />
给子进程发送<em>signal</em>信号量。</p>
<blockquote><p>注意：windows下目前只支持发送SIGTERM，等效于下面的<strong>terminate()</strong>。</p></blockquote>
<p><code>Popen</code>.<strong>terminate()</strong><br />
停止子进程。Posix下是发送SIGTERM信号。windows下是调用<strong>TerminateProcess()</strong>这个API。</p>
<p><code>Popen</code>.<strong>kill()</strong><br />
杀死子进程。Posix下是发送SIGKILL信号。windows下和<strong>terminate()</strong>无异。</p>
<p><code>Popen</code>.<strong>stdin</strong><br />
如果<em>stdin</em>参数是PIPE，此属性就是一个文件对象，否则为<strong>None</strong>。</p>
<p><code>Popen</code>.<strong>stdout</strong><br />
如果<em>stdout</em>参数是PIPE，此属性就是一个文件对象，否则为<strong>None</strong>。</p>
<p><code>Popen</code>.<strong>stderr</strong><br />
如果<em>stderr</em>参数是PIPE，此属性就是一个文件对象，否则为<strong>None</strong>。</p>
<p><code>Popen</code>.<strong>pid</strong><br />
子进程的进程号。注意，如果<em>shell</em>参数为True，这属性指的是子shell的进程号。</p>
<p><code>Popen</code>.<strong>returncode</strong><br />
子程序的返回值，由poll()或者wait()设置，间接地也由communicate()设置。<br />
如果为None，表示子进程还没终止。<br />
如果为负数-N的话，表示子进程被N号信号终止。（仅限*nux）</p>
<p><big><strong>用subprocess来代替其他函数</strong></big></p>
<p>在这节里，举一些常用的例子，都可以用subprocess来完成，我们假定是用 “from subprocess import *” 来导入模块的：</p>
<p><big>代替shell命令：</big></p>
<blockquote><p>output=`mycmd myarg`<br />
等效于<br />
output = Popen(["mycmd", "myarg"], stdout=PIPE).communicate()[0]</p></blockquote>
<p><big>代替shell管道：</big></p>
<blockquote><p>output=`dmesg | grep hda`<br />
等效于<br />
p1 = Popen(["dmesg"], stdout=PIPE)<br />
p2 = Popen(["grep", "hda"], stdin=p1.stdout, stdout=PIPE)<br />
output = p2.communicate()[0]</p></blockquote>
<p><big>代替<strong>os.system()</strong></big></p>
<blockquote><p>sts = os.system(&#8220;mycmd&#8221; + &#8221; myarg&#8221;)<br />
等效于<br />
p = Popen(&#8220;mycmd&#8221; + &#8221; myarg&#8221;, shell=True)<br />
sts = os.waitpid(p.pid, 0)[1]</p></blockquote>
<p>注意：</p>
<ul>
<li>通常并不需要用shell来调用程序。</li>
<li>用subprocess可以更方便地得到子程序的返回值。</li>
</ul>
<p>其实，更真实的替换是：</p>
<blockquote><p>try:<br />
    retcode = call(&#8220;mycmd&#8221; + &#8221; myarg&#8221;, shell=True)<br />
    if retcode < 0:<br />
        print >>sys.stderr, &#8220;Child was terminated by signal&#8221;, -retcode<br />
    else:<br />
        print >>sys.stderr, &#8220;Child returned&#8221;, retcode<br />
except OSError, e:<br />
    print >>sys.stderr, &#8220;Execution failed:&#8221;, e</p></blockquote>
<p><big>代替os.spawn系列</big><br />
P_NOWAIT的例子</p>
<blockquote><p>pid = os.spawnlp(os.P_NOWAIT, &#8220;/bin/mycmd&#8221;, &#8220;mycmd&#8221;, &#8220;myarg&#8221;)<br />
等效于<br />
pid = Popen(["/bin/mycmd", "myarg"]).pid</p></blockquote>
<p>P_WAIT的例子</p>
<blockquote><p>retcode = os.spawnlp(os.P_WAIT, &#8220;/bin/mycmd&#8221;, &#8220;mycmd&#8221;, &#8220;myarg&#8221;)<br />
等效于<br />
retcode = call(["/bin/mycmd", "myarg"])</p></blockquote>
<p>Vector的例子</p>
<blockquote><p>os.spawnvp(os.P_NOWAIT, path, args)<br />
等效于<br />
Popen([path] + args[1:])</p></blockquote>
<p>关于环境变量的例子</p>
<blockquote><p>os.spawnlpe(os.P_NOWAIT, &#8220;/bin/mycmd&#8221;, &#8220;mycmd&#8221;, &#8220;myarg&#8221;, env)<br />
等效于<br />
Popen(["/bin/mycmd", "myarg"], env={&#8220;PATH&#8221;: &#8220;/usr/bin&#8221;})</p></blockquote>
<p><big>代替<strong>os.popen()</strong>, <strong>os.popen2()</strong>, <strong>os.popen3()</strong>：</big></p>
<blockquote><p>pipe = os.popen(&#8220;cmd&#8221;, &#8216;r&#8217;, bufsize)<br />
等效于<br />
pipe = Popen(&#8220;cmd&#8221;, shell=True, bufsize=bufsize, stdout=PIPE).stdout</p></blockquote>
<blockquote><p>pipe = os.popen(&#8220;cmd&#8221;, &#8216;w&#8217;, bufsize)<br />
等效于<br />
pipe = Popen(&#8220;cmd&#8221;, shell=True, bufsize=bufsize, stdin=PIPE).stdin</p></blockquote>
<blockquote><p>(child_stdin, child_stdout) = os.popen2(&#8220;cmd&#8221;, mode, bufsize)<br />
等效于<br />
p = Popen(&#8220;cmd&#8221;, shell=True, bufsize=bufsize, stdin=PIPE, stdout=PIPE, close_fds=True)<br />
(child_stdin, child_stdout) = (p.stdin, p.stdout)</p></blockquote>
<blockquote><p>(child_stdin, child_stdout, child_stderr) = os.popen3(&#8220;cmd&#8221;, mode, bufsize)<br />
等效于<br />
p = Popen(&#8220;cmd&#8221;, shell=True, bufsize=bufsize, stdin=PIPE, stdout=PIPE, stderr=PIPE, close_fds=True)<br />
(child_stdin, child_stdout, child_stderr) = (p.stdin, p.stdout, p.stderr)</p></blockquote>
<blockquote><p>(child_stdin, child_stdout_and_stderr) = os.popen4(&#8220;cmd&#8221;, mode, bufsize)<br />
等效于<br />
p = Popen(&#8220;cmd&#8221;, shell=True, bufsize=bufsize, stdin=PIPE, stdout=PIPE, stderr=STDOUT, close_fds=True)<br />
(child_stdin, child_stdout_and_stderr) = (p.stdin, p.stdout)</p></blockquote>
<p>*nix下，os.popen2， os.popen3， os.popen4 也可以接受一个列表做为执行的命令，这时参数会被直接传给程序，而不经过shell的解释转换。如下：</p>
<blockquote><p>(child_stdin, child_stdout) = os.popen2(["/bin/ls", "-l"], mode, bufsize)<br />
等效于<br />
p = Popen(["/bin/ls", "-l"], bufsize=bufsize, stdin=PIPE, stdout=PIPE)<br />
(child_stdin, child_stdout) = (p.stdin, p.stdout)</p></blockquote>
<p>返回值处理：</p>
<blockquote><p>pipe = os.popen(&#8220;cmd&#8221;, &#8216;w&#8217;)<br />
&#8230;<br />
rc = pipe.close()<br />
if rc != None and rc % 256:<br />
    print &#8220;There were some errors&#8221;<br />
等效于<br />
process = Popen(&#8220;cmd&#8221;, &#8216;w&#8217;, shell=True, stdin=PIPE)<br />
&#8230;<br />
process.stdin.close()<br />
if process.wait() != 0:<br />
    print &#8220;There were some errors&#8221;</p></blockquote>
<p><big>代替<strong>popen2</strong>模块里的函数：</big></p>
<blockquote><p>(child_stdout, child_stdin) = popen2.popen2(&#8220;somestring&#8221;, bufsize, mode)<br />
等效于<br />
p = Popen(["somestring"], shell=True, bufsize=bufsize, stdin=PIPE, stdout=PIPE, close_fds=True)<br />
(child_stdout, child_stdin) = (p.stdout, p.stdin)</p></blockquote>
<p>*nix下，popen2 也可以接受一个列表做为执行的命令，这时参数会被直接传给程序，而不经过shell的解释转换。如下：</p>
<blockquote><p>(child_stdout, child_stdin) = popen2.popen2(["mycmd", "myarg"], bufsize, mode)<br />
等效于<br />
p = Popen(["mycmd", "myarg"], bufsize=bufsize, stdin=PIPE, stdout=PIPE, close_fds=True)<br />
(child_stdout, child_stdin) = (p.stdout, p.stdin)</p></blockquote>
<p><a href="http://docs.python.org/library/popen2.html#popen2.Popen3">popen2.Popen3</a> and <a href="http://docs.python.org/library/popen2.html#popen2.Popen4">popen2.Popen4</a> 基本上也能用 subprocess.Popen 代替，除了以下几点要注意：</p>
<ul>
<li>执行失败的时候Popen会抛出异常</li>
<li><em>capturestderr</em>参数用<em>stderr</em>代替</li>
<li><code>stdin=PIPE</code> 和 <code>stdout=PIPE</code> 必须要指定</li>
<li>popen2默认会关掉所有文件描述符，而Popen要指定<code>close_fds=True</code></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://luy.li/2010/04/14/python_subprocess/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
	</channel>
</rss>
