772 lines
82 KiB
HTML
772 lines
82 KiB
HTML
|
||
<!DOCTYPE html>
|
||
|
||
<html xmlns="http://www.w3.org/1999/xhtml" lang="zh_CN">
|
||
<head>
|
||
<meta charset="utf-8" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
|
||
|
||
<title>代码库和插件 FAQ — Python 3.8.20 文档</title><meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
|
||
<link rel="stylesheet" href="../_static/pydoctheme.css" type="text/css" />
|
||
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
|
||
|
||
<script id="documentation_options" data-url_root="../" src="../_static/documentation_options.js"></script>
|
||
<script src="../_static/jquery.js"></script>
|
||
<script src="../_static/underscore.js"></script>
|
||
<script src="../_static/doctools.js"></script>
|
||
<script src="../_static/language_data.js"></script>
|
||
<script src="../_static/translations.js"></script>
|
||
|
||
<script src="../_static/sidebar.js"></script>
|
||
|
||
<link rel="search" type="application/opensearchdescription+xml"
|
||
title="在 Python 3.8.20 文档 中搜索"
|
||
href="../_static/opensearch.xml"/>
|
||
<link rel="author" title="关于这些文档" href="../about.html" />
|
||
<link rel="index" title="索引" href="../genindex.html" />
|
||
<link rel="search" title="搜索" href="../search.html" />
|
||
<link rel="copyright" title="版权所有" href="../copyright.html" />
|
||
<link rel="next" title="扩展/嵌入常见问题" href="extending.html" />
|
||
<link rel="prev" title="设计和历史常见问题" href="design.html" />
|
||
<link rel="canonical" href="https://docs.python.org/3/faq/library.html" />
|
||
|
||
|
||
|
||
|
||
|
||
<style>
|
||
@media only screen {
|
||
table.full-width-table {
|
||
width: 100%;
|
||
}
|
||
}
|
||
</style>
|
||
<link rel="shortcut icon" type="image/png" href="../_static/py.svg" />
|
||
<script type="text/javascript" src="../_static/copybutton.js"></script>
|
||
<script type="text/javascript" src="../_static/menu.js"></script>
|
||
|
||
</head>
|
||
<body>
|
||
<div class="mobile-nav">
|
||
<input type="checkbox" id="menuToggler" class="toggler__input" aria-controls="navigation"
|
||
aria-pressed="false" aria-expanded="false" role="button" aria-label="Menu" />
|
||
<label for="menuToggler" class="toggler__label">
|
||
<span></span>
|
||
</label>
|
||
<nav class="nav-content" role="navigation">
|
||
<a href="https://www.python.org/" class="nav-logo">
|
||
<img src="../_static/py.svg" alt="Logo"/>
|
||
</a>
|
||
<div class="version_switcher_placeholder"></div>
|
||
<form role="search" class="search" action="../search.html" method="get">
|
||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" class="search-icon">
|
||
<path fill-rule="nonzero"
|
||
d="M15.5 14h-.79l-.28-.27a6.5 6.5 0 001.48-5.34c-.47-2.78-2.79-5-5.59-5.34a6.505 6.505 0 00-7.27 7.27c.34 2.8 2.56 5.12 5.34 5.59a6.5 6.5 0 005.34-1.48l.27.28v.79l4.25 4.25c.41.41 1.08.41 1.49 0 .41-.41.41-1.08 0-1.49L15.5 14zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z" fill="#444"></path>
|
||
</svg>
|
||
<input type="text" name="q" aria-label="快速搜索"/>
|
||
<input type="submit" value="转向"/>
|
||
</form>
|
||
</nav>
|
||
<div class="menu-wrapper">
|
||
<nav class="menu" role="navigation" aria-label="main navigation">
|
||
<div class="language_switcher_placeholder"></div>
|
||
<h3><a href="../contents.html">目录</a></h3>
|
||
<ul>
|
||
<li><a class="reference internal" href="#">代码库和插件 FAQ</a><ul>
|
||
<li><a class="reference internal" href="#general-library-questions">通用的代码库问题</a></li>
|
||
<li><a class="reference internal" href="#common-tasks">通用任务</a></li>
|
||
<li><a class="reference internal" href="#threads">线程相关</a></li>
|
||
<li><a class="reference internal" href="#input-and-output">输入输出</a></li>
|
||
<li><a class="reference internal" href="#network-internet-programming">网络 / Internet 编程</a></li>
|
||
<li><a class="reference internal" href="#databases">数据库</a></li>
|
||
<li><a class="reference internal" href="#mathematics-and-numerics">数学和数字</a></li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
|
||
<h4>上一个主题</h4>
|
||
<p class="topless"><a href="design.html"
|
||
title="上一章">设计和历史常见问题</a></p>
|
||
<h4>下一个主题</h4>
|
||
<p class="topless"><a href="extending.html"
|
||
title="下一章">扩展/嵌入常见问题</a></p>
|
||
<div role="note" aria-label="source link">
|
||
<h3>本页</h3>
|
||
<ul class="this-page-menu">
|
||
<li><a href="../bugs.html">报告 Bug</a></li>
|
||
<li>
|
||
<a href="https://github.com/python/cpython/blob/3.8/Doc/faq/library.rst"
|
||
rel="nofollow">显示源代码
|
||
</a>
|
||
</li>
|
||
</ul>
|
||
</div>
|
||
</nav>
|
||
</div>
|
||
</div>
|
||
|
||
<div id="outdated-warning" style="padding: .5em; text-align: center; background-color: #FFBABA; color: #6A0E0E;">
|
||
这个文档所针对的是一个已不再受支持的 Python 旧版本。
|
||
你应当升级版本,并阅读
|
||
<a href="/3/faq/library.html"> Python 当前稳定版本的文档</a>.
|
||
</div>
|
||
|
||
<div class="related" role="navigation" aria-label="related navigation">
|
||
<h3>导航</h3>
|
||
<ul>
|
||
<li class="right" style="margin-right: 10px">
|
||
<a href="../genindex.html" title="总目录"
|
||
accesskey="I">索引</a></li>
|
||
<li class="right" >
|
||
<a href="../py-modindex.html" title="Python 模块索引"
|
||
>模块</a> |</li>
|
||
<li class="right" >
|
||
<a href="extending.html" title="扩展/嵌入常见问题"
|
||
accesskey="N">下一页</a> |</li>
|
||
<li class="right" >
|
||
<a href="design.html" title="设计和历史常见问题"
|
||
accesskey="P">上一页</a> |</li>
|
||
|
||
<li><img src="../_static/py.svg" alt="python logo" style="vertical-align: middle; margin-top: -1px"/></li>
|
||
<li><a href="https://www.python.org/">Python</a> »</li>
|
||
<li class="switchers">
|
||
<div class="language_switcher_placeholder"></div>
|
||
<div class="version_switcher_placeholder"></div>
|
||
</li>
|
||
<li>
|
||
|
||
</li>
|
||
<li id="cpython-language-and-version">
|
||
<a href="../index.html">3.8.20 Documentation</a> »
|
||
</li>
|
||
|
||
<li class="nav-item nav-item-1"><a href="index.html" accesskey="U">Python 常见问题</a> »</li>
|
||
<li class="right">
|
||
|
||
|
||
<div class="inline-search" role="search">
|
||
<form class="inline-search" action="../search.html" method="get">
|
||
<input placeholder="快速搜索" aria-label="快速搜索" type="text" name="q" />
|
||
<input type="submit" value="转向" />
|
||
<input type="hidden" name="check_keywords" value="yes" />
|
||
<input type="hidden" name="area" value="default" />
|
||
</form>
|
||
</div>
|
||
|
|
||
</li>
|
||
|
||
</ul>
|
||
</div>
|
||
|
||
<div class="document">
|
||
<div class="documentwrapper">
|
||
<div class="bodywrapper">
|
||
<div class="body" role="main">
|
||
|
||
<section id="library-and-extension-faq">
|
||
<h1><a class="toc-backref" href="#id2">代码库和插件 FAQ</a><a class="headerlink" href="#library-and-extension-faq" title="永久链接至标题">¶</a></h1>
|
||
<div class="contents topic" id="id1">
|
||
<p class="topic-title">目录</p>
|
||
<ul class="simple">
|
||
<li><p><a class="reference internal" href="#library-and-extension-faq" id="id2">代码库和插件 FAQ</a></p>
|
||
<ul>
|
||
<li><p><a class="reference internal" href="#general-library-questions" id="id3">通用的代码库问题</a></p>
|
||
<ul>
|
||
<li><p><a class="reference internal" href="#how-do-i-find-a-module-or-application-to-perform-task-x" id="id4">如何找到可以用来做 XXX 的模块或应用?</a></p></li>
|
||
<li><p><a class="reference internal" href="#where-is-the-math-py-socket-py-regex-py-etc-source-file" id="id5">math.py(socket.py,regex.py 等)的源文件在哪?</a></p></li>
|
||
<li><p><a class="reference internal" href="#how-do-i-make-a-python-script-executable-on-unix" id="id6">在 Unix 中怎样让 Python 脚本可执行?</a></p></li>
|
||
<li><p><a class="reference internal" href="#is-there-a-curses-termcap-package-for-python" id="id7">Python 中有 curses/termcap 包吗?</a></p></li>
|
||
<li><p><a class="reference internal" href="#is-there-an-equivalent-to-c-s-onexit-in-python" id="id8">Python 中存在类似 C 的 onexit() 函数的东西吗?</a></p></li>
|
||
<li><p><a class="reference internal" href="#why-don-t-my-signal-handlers-work" id="id9">为什么我的信号处理函数不能工作?</a></p></li>
|
||
</ul>
|
||
</li>
|
||
<li><p><a class="reference internal" href="#common-tasks" id="id10">通用任务</a></p>
|
||
<ul>
|
||
<li><p><a class="reference internal" href="#how-do-i-test-a-python-program-or-component" id="id11">怎样测试 Python 程序或组件?</a></p></li>
|
||
<li><p><a class="reference internal" href="#how-do-i-create-documentation-from-doc-strings" id="id12">怎样用 docstring 创建文档?</a></p></li>
|
||
<li><p><a class="reference internal" href="#how-do-i-get-a-single-keypress-at-a-time" id="id13">怎样一次只获取一个按键?</a></p></li>
|
||
</ul>
|
||
</li>
|
||
<li><p><a class="reference internal" href="#threads" id="id14">线程相关</a></p>
|
||
<ul>
|
||
<li><p><a class="reference internal" href="#how-do-i-program-using-threads" id="id15">程序中怎样使用线程?</a></p></li>
|
||
<li><p><a class="reference internal" href="#none-of-my-threads-seem-to-run-why" id="id16">我的线程都没有运行,为什么?</a></p></li>
|
||
<li><p><a class="reference internal" href="#how-do-i-parcel-out-work-among-a-bunch-of-worker-threads" id="id17">如何将任务分配给多个工作线程?</a></p></li>
|
||
<li><p><a class="reference internal" href="#what-kinds-of-global-value-mutation-are-thread-safe" id="id18">怎样修改全局变量是线程安全的?</a></p></li>
|
||
<li><p><a class="reference internal" href="#can-t-we-get-rid-of-the-global-interpreter-lock" id="id19">不能删除全局解释器锁吗?</a></p></li>
|
||
</ul>
|
||
</li>
|
||
<li><p><a class="reference internal" href="#input-and-output" id="id20">输入输出</a></p>
|
||
<ul>
|
||
<li><p><a class="reference internal" href="#how-do-i-delete-a-file-and-other-file-questions" id="id21">怎样删除文件?(以及其他文件相关的问题……)</a></p></li>
|
||
<li><p><a class="reference internal" href="#how-do-i-copy-a-file" id="id22">怎样复制文件?</a></p></li>
|
||
<li><p><a class="reference internal" href="#how-do-i-read-or-write-binary-data" id="id23">怎样读取(或写入)二进制数据?</a></p></li>
|
||
<li><p><a class="reference internal" href="#i-can-t-seem-to-use-os-read-on-a-pipe-created-with-os-popen-why" id="id24">似乎 os.popen() 创建的管道不能使用 os.read(),这是为什么?</a></p></li>
|
||
<li><p><a class="reference internal" href="#how-do-i-access-the-serial-rs232-port" id="id25">怎样访问(RS232)串口?</a></p></li>
|
||
<li><p><a class="reference internal" href="#why-doesn-t-closing-sys-stdout-stdin-stderr-really-close-it" id="id26">为什么关闭 sys.stdout(stdin,stderr)并不会真正关掉它?</a></p></li>
|
||
</ul>
|
||
</li>
|
||
<li><p><a class="reference internal" href="#network-internet-programming" id="id27">网络 / Internet 编程</a></p>
|
||
<ul>
|
||
<li><p><a class="reference internal" href="#what-www-tools-are-there-for-python" id="id28">Python 中的 WWW 工具是什么?</a></p></li>
|
||
<li><p><a class="reference internal" href="#how-can-i-mimic-cgi-form-submission-method-post" id="id29">怎样模拟发送 CGI 表单(METHOD=POST)?</a></p></li>
|
||
<li><p><a class="reference internal" href="#what-module-should-i-use-to-help-with-generating-html" id="id30">生成 HTML 需要使用什么模块?</a></p></li>
|
||
<li><p><a class="reference internal" href="#how-do-i-send-mail-from-a-python-script" id="id31">怎样使用 Python 脚本发送邮件?</a></p></li>
|
||
<li><p><a class="reference internal" href="#how-do-i-avoid-blocking-in-the-connect-method-of-a-socket" id="id32">socket 的 connect() 方法怎样避免阻塞?</a></p></li>
|
||
</ul>
|
||
</li>
|
||
<li><p><a class="reference internal" href="#databases" id="id33">数据库</a></p>
|
||
<ul>
|
||
<li><p><a class="reference internal" href="#are-there-any-interfaces-to-database-packages-in-python" id="id34">Python 中有数据库包的接口吗?</a></p></li>
|
||
<li><p><a class="reference internal" href="#how-do-you-implement-persistent-objects-in-python" id="id35">在 Python 中如何实现持久化对象?</a></p></li>
|
||
</ul>
|
||
</li>
|
||
<li><p><a class="reference internal" href="#mathematics-and-numerics" id="id36">数学和数字</a></p>
|
||
<ul>
|
||
<li><p><a class="reference internal" href="#how-do-i-generate-random-numbers-in-python" id="id37">Python 中怎样生成随机数?</a></p></li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
</div>
|
||
<section id="general-library-questions">
|
||
<h2><a class="toc-backref" href="#id3">通用的代码库问题</a><a class="headerlink" href="#general-library-questions" title="永久链接至标题">¶</a></h2>
|
||
<section id="how-do-i-find-a-module-or-application-to-perform-task-x">
|
||
<h3><a class="toc-backref" href="#id4">如何找到可以用来做 XXX 的模块或应用?</a><a class="headerlink" href="#how-do-i-find-a-module-or-application-to-perform-task-x" title="永久链接至标题">¶</a></h3>
|
||
<p>在 <a class="reference internal" href="../library/index.html#library-index"><span class="std std-ref">代码库参考</span></a> 中查找是否有适合的标准库模块。(如果你已经了解标准库的内容,可以跳过这一步)</p>
|
||
<p>对于第三方软件包,请搜索 <a class="reference external" href="https://pypi.org">Python Package Index</a> 或是 <a class="reference external" href="https://www.google.com">Google</a> 等其他搜索引擎。用“Python”加上一两个你需要的关键字通常会找到有用的东西。</p>
|
||
</section>
|
||
<section id="where-is-the-math-py-socket-py-regex-py-etc-source-file">
|
||
<h3><a class="toc-backref" href="#id5">math.py(socket.py,regex.py 等)的源文件在哪?</a><a class="headerlink" href="#where-is-the-math-py-socket-py-regex-py-etc-source-file" title="永久链接至标题">¶</a></h3>
|
||
<p>如果找不到模块的源文件,可能它是一个内建的模块,或是使用 C,C++ 或其他编译型语言实现的动态加载模块。这种情况下可能是没有源码文件的,类似 <code class="file docutils literal notranslate"><span class="pre">mathmodule.c</span></code> 这样的文件会存放在 C 代码目录中(但不在 Python 目录中)。</p>
|
||
<p>Python 中(至少)有三类模块:</p>
|
||
<ol class="arabic">
|
||
<li><p>使用 Python 编写的模块(.py);</p></li>
|
||
<li><p>使用 C 编写的动态加载模块(.dll,.pyd,.so,.sl 等);</p></li>
|
||
<li><p>使用 C 编写并链接到解释器的模块,要获取此列表,输入:</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">sys</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">builtin_module_names</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
</li>
|
||
</ol>
|
||
</section>
|
||
<section id="how-do-i-make-a-python-script-executable-on-unix">
|
||
<h3><a class="toc-backref" href="#id6">在 Unix 中怎样让 Python 脚本可执行?</a><a class="headerlink" href="#how-do-i-make-a-python-script-executable-on-unix" title="永久链接至标题">¶</a></h3>
|
||
<p>你需要做两件事:文件必须是可执行的,并且第一行需要以 <code class="docutils literal notranslate"><span class="pre">#!</span></code> 开头,后面跟上 Python 解释器的路径。</p>
|
||
<p>第一点可以用执行 <code class="docutils literal notranslate"><span class="pre">chmod</span> <span class="pre">+x</span> <span class="pre">scriptfile</span></code> 或是 <code class="docutils literal notranslate"><span class="pre">chmod</span> <span class="pre">755</span> <span class="pre">scriptfile</span></code> 做到。</p>
|
||
<p>第二点有很多种做法,最直接的方式是:</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="ch">#!/usr/local/bin/python</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>在文件第一行,使用你所在平台上的 Python 解释器的路径。</p>
|
||
<p>如果你希望脚本不依赖 Python 解释器的具体路径,你也可以使用 <strong class="program">env</strong> 程序。假设你的 Python 解释器所在目录已经添加到了 <span class="target" id="index-4"></span><code class="xref std std-envvar docutils literal notranslate"><span class="pre">PATH</span></code> 环境变量中,几乎所有的类 Unix 系统都支持下面的写法:</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="ch">#!/usr/bin/env python</span>
|
||
</pre></div>
|
||
</div>
|
||
<p><em>不要</em> 在 CGI 脚本中这样做。CGI 脚本的 <span class="target" id="index-5"></span><code class="xref std std-envvar docutils literal notranslate"><span class="pre">PATH</span></code> 环境变量通常会非常精简,所以你必须使用解释器的完整绝对路径。</p>
|
||
<p>有时候,用户的环境变量如果太长,可能会导致 <strong class="program">/usr/bin/env</strong> 执行失败;又或者甚至根本就不存在 env 程序。在这种情况下,你可以尝试使用下面的 hack 方法(来自 Alex Rezinsky):</p>
|
||
<div class="highlight-sh notranslate"><div class="highlight"><pre><span></span><span class="ch">#! /bin/sh</span>
|
||
<span class="s2">""":"</span>
|
||
<span class="nb">exec</span><span class="w"> </span>python<span class="w"> </span><span class="nv">$0</span><span class="w"> </span><span class="si">${</span><span class="nv">1</span><span class="p">+</span><span class="s2">"</span><span class="nv">$@</span><span class="s2">"</span><span class="si">}</span>
|
||
<span class="s2">"""</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>这样做有一个小小的缺点,它会定义脚本的 __doc__ 字符串。不过可以这样修复:</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="vm">__doc__</span> <span class="o">=</span> <span class="s2">"""...Whatever..."""</span>
|
||
</pre></div>
|
||
</div>
|
||
</section>
|
||
<section id="is-there-a-curses-termcap-package-for-python">
|
||
<h3><a class="toc-backref" href="#id7">Python 中有 curses/termcap 包吗?</a><a class="headerlink" href="#is-there-a-curses-termcap-package-for-python" title="永久链接至标题">¶</a></h3>
|
||
<p>对于类 Unix 系统:标准 Python 源码发行版会在 <a class="reference external" href="https://github.com/python/cpython/tree/3.8/Modules">Modules</a> 子目录中附带 curses 模块,但默认并不会编译。(注意:在 Windows 平台下不可用 —— Windows 中没有 curses 模块。)</p>
|
||
<p><a class="reference internal" href="../library/curses.html#module-curses" title="curses: An interface to the curses library, providing portable terminal handling. (Unix)"><code class="xref py py-mod docutils literal notranslate"><span class="pre">curses</span></code></a> 模块支持基本的 curses 特性,同时也支持 ncurses 和 SYSV curses 中的很多额外功能,比如颜色、不同的字符集支持、填充和鼠标支持。这意味着这个模块不兼容只有 BSD curses 模块的操作系统,但是目前仍在维护的系统应该都不会存在这种情况。</p>
|
||
<p>对于 Windows 平台:使用 <a class="reference external" href="http://effbot.org/zone/console-index.htm">consolelib 模块</a>.</p>
|
||
</section>
|
||
<section id="is-there-an-equivalent-to-c-s-onexit-in-python">
|
||
<h3><a class="toc-backref" href="#id8">Python 中存在类似 C 的 onexit() 函数的东西吗?</a><a class="headerlink" href="#is-there-an-equivalent-to-c-s-onexit-in-python" title="永久链接至标题">¶</a></h3>
|
||
<p><a class="reference internal" href="../library/atexit.html#module-atexit" title="atexit: Register and execute cleanup functions."><code class="xref py py-mod docutils literal notranslate"><span class="pre">atexit</span></code></a> 模块提供了一个与 C 的 <code class="xref c c-func docutils literal notranslate"><span class="pre">onexit()</span></code> 函数类似的注册函数。</p>
|
||
</section>
|
||
<section id="why-don-t-my-signal-handlers-work">
|
||
<h3><a class="toc-backref" href="#id9">为什么我的信号处理函数不能工作?</a><a class="headerlink" href="#why-don-t-my-signal-handlers-work" title="永久链接至标题">¶</a></h3>
|
||
<p>最常见的问题是信号处理函数没有正确定义参数列表。它会被这样调用:</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">handler</span><span class="p">(</span><span class="n">signum</span><span class="p">,</span> <span class="n">frame</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>因此函数应该定义两个参数:</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">handler</span><span class="p">(</span><span class="n">signum</span><span class="p">,</span> <span class="n">frame</span><span class="p">):</span>
|
||
<span class="o">...</span>
|
||
</pre></div>
|
||
</div>
|
||
</section>
|
||
</section>
|
||
<section id="common-tasks">
|
||
<h2><a class="toc-backref" href="#id10">通用任务</a><a class="headerlink" href="#common-tasks" title="永久链接至标题">¶</a></h2>
|
||
<section id="how-do-i-test-a-python-program-or-component">
|
||
<h3><a class="toc-backref" href="#id11">怎样测试 Python 程序或组件?</a><a class="headerlink" href="#how-do-i-test-a-python-program-or-component" title="永久链接至标题">¶</a></h3>
|
||
<p>Python 带有两个测试框架。<a class="reference internal" href="../library/doctest.html#module-doctest" title="doctest: Test pieces of code within docstrings."><code class="xref py py-mod docutils literal notranslate"><span class="pre">doctest</span></code></a> 模块从模块的 docstring 中寻找示例并执行,对比输出是否与 docstring 中给出的是否一致。</p>
|
||
<p><a class="reference internal" href="../library/unittest.html#module-unittest" title="unittest: Unit testing framework for Python."><code class="xref py py-mod docutils literal notranslate"><span class="pre">unittest</span></code></a> 模块是一个模仿 Java 和 Smalltalk 测试框架的更棒的测试框架。</p>
|
||
<p>为了使测试更容易,你应该在程序中使用良好的模块化设计。程序中的绝大多数功能都应该用函数或类方法封装 —— 有时这样做会有额外惊喜,程序会运行得更快(因为局部变量比全局变量访问要快)。除此之外,程序应该避免依赖可变的局部变量,这会使得测试困难许多。</p>
|
||
<p>程序的“全局主逻辑”应该尽量简单:</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s2">"__main__"</span><span class="p">:</span>
|
||
<span class="n">main_logic</span><span class="p">()</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>并放置在程序主模块的最后面。</p>
|
||
<p>一旦你的程序已经用函数和类完善地组织起来,你就应该编写测试函数来测试其行为。可以使用自动执行一系列测试函数的测试集与每个模块进行关联。听起来似乎需要大量的工作,但是因为 Python 非常简洁和灵活,所以实际上会相当简单。在编写“生产代码”的同时别忘了也要编写测试函数,你会发现编程会变得更愉快、更有趣,因为这样会使得发现 bug 和设计缺陷更加容易。</p>
|
||
<p>程序主模块之外的其他“辅助模块”中可以增加自测试的入口。</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s2">"__main__"</span><span class="p">:</span>
|
||
<span class="n">self_test</span><span class="p">()</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>通过使用 Python 实现的“假”接口,即使是需要与复杂的外部接口交互的程序也可以在外部接口不可用时进行测试。</p>
|
||
</section>
|
||
<section id="how-do-i-create-documentation-from-doc-strings">
|
||
<h3><a class="toc-backref" href="#id12">怎样用 docstring 创建文档?</a><a class="headerlink" href="#how-do-i-create-documentation-from-doc-strings" title="永久链接至标题">¶</a></h3>
|
||
<p><a class="reference internal" href="../library/pydoc.html#module-pydoc" title="pydoc: Documentation generator and online help system."><code class="xref py py-mod docutils literal notranslate"><span class="pre">pydoc</span></code></a> 模块可以用 Python 源码中的 docstring 创建 HTML 文件。也可以使用 <a class="reference external" href="http://epydoc.sourceforge.net/">epydoc</a> 来只通过 docstring 创建 API 文档。<a class="reference external" href="http://sphinx-doc.org">Sphinx</a> 也可以引入 docstring 的内容。</p>
|
||
</section>
|
||
<section id="how-do-i-get-a-single-keypress-at-a-time">
|
||
<h3><a class="toc-backref" href="#id13">怎样一次只获取一个按键?</a><a class="headerlink" href="#how-do-i-get-a-single-keypress-at-a-time" title="永久链接至标题">¶</a></h3>
|
||
<p>在类 Unix 系统中有多种方案。最直接的方法是使用 curses,但是 curses 模块太大了,难以学习。</p>
|
||
</section>
|
||
</section>
|
||
<section id="threads">
|
||
<h2><a class="toc-backref" href="#id14">线程相关</a><a class="headerlink" href="#threads" title="永久链接至标题">¶</a></h2>
|
||
<section id="how-do-i-program-using-threads">
|
||
<h3><a class="toc-backref" href="#id15">程序中怎样使用线程?</a><a class="headerlink" href="#how-do-i-program-using-threads" title="永久链接至标题">¶</a></h3>
|
||
<p>一定要使用 <a class="reference internal" href="../library/threading.html#module-threading" title="threading: Thread-based parallelism."><code class="xref py py-mod docutils literal notranslate"><span class="pre">threading</span></code></a> 模块,不要使用 <a class="reference internal" href="../library/_thread.html#module-_thread" title="_thread: Low-level threading API."><code class="xref py py-mod docutils literal notranslate"><span class="pre">_thread</span></code></a> 模块。<a class="reference internal" href="../library/threading.html#module-threading" title="threading: Thread-based parallelism."><code class="xref py py-mod docutils literal notranslate"><span class="pre">threading</span></code></a> 模块对 <a class="reference internal" href="../library/_thread.html#module-_thread" title="_thread: Low-level threading API."><code class="xref py py-mod docutils literal notranslate"><span class="pre">_thread</span></code></a> 模块提供的底层线程原语做了更易用的抽象。</p>
|
||
<p>Aahz 的非常实用的 threading 教程中有一些幻灯片;可以参阅 <a class="reference external" href="http://www.pythoncraft.com/OSCON2001/">http://www.pythoncraft.com/OSCON2001/</a> 。</p>
|
||
</section>
|
||
<section id="none-of-my-threads-seem-to-run-why">
|
||
<h3><a class="toc-backref" href="#id16">我的线程都没有运行,为什么?</a><a class="headerlink" href="#none-of-my-threads-seem-to-run-why" title="永久链接至标题">¶</a></h3>
|
||
<p>一旦主线程退出,所有的子线程都会被杀掉。你的主线程运行得太快了,子线程还没来得及工作。</p>
|
||
<p>简单的解决方法是在程序中加一个时间足够长的 sleep,让子线程能够完成运行。</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">threading</span><span class="o">,</span> <span class="nn">time</span>
|
||
|
||
<span class="k">def</span> <span class="nf">thread_task</span><span class="p">(</span><span class="n">name</span><span class="p">,</span> <span class="n">n</span><span class="p">):</span>
|
||
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">n</span><span class="p">):</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="n">name</span><span class="p">,</span> <span class="n">i</span><span class="p">)</span>
|
||
|
||
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">10</span><span class="p">):</span>
|
||
<span class="n">T</span> <span class="o">=</span> <span class="n">threading</span><span class="o">.</span><span class="n">Thread</span><span class="p">(</span><span class="n">target</span><span class="o">=</span><span class="n">thread_task</span><span class="p">,</span> <span class="n">args</span><span class="o">=</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">i</span><span class="p">),</span> <span class="n">i</span><span class="p">))</span>
|
||
<span class="n">T</span><span class="o">.</span><span class="n">start</span><span class="p">()</span>
|
||
|
||
<span class="n">time</span><span class="o">.</span><span class="n">sleep</span><span class="p">(</span><span class="mi">10</span><span class="p">)</span> <span class="c1"># <---------------------------!</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>但目前(在许多平台上)线程不是并行运行的,而是按顺序依次执行!原因是系统线程调度器在前一个线程阻塞之前不会启动新线程。</p>
|
||
<p>简单的解决方法是在运行函数的开始处加一个时间很短的 sleep。</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">thread_task</span><span class="p">(</span><span class="n">name</span><span class="p">,</span> <span class="n">n</span><span class="p">):</span>
|
||
<span class="n">time</span><span class="o">.</span><span class="n">sleep</span><span class="p">(</span><span class="mf">0.001</span><span class="p">)</span> <span class="c1"># <--------------------!</span>
|
||
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">n</span><span class="p">):</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="n">name</span><span class="p">,</span> <span class="n">i</span><span class="p">)</span>
|
||
|
||
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">10</span><span class="p">):</span>
|
||
<span class="n">T</span> <span class="o">=</span> <span class="n">threading</span><span class="o">.</span><span class="n">Thread</span><span class="p">(</span><span class="n">target</span><span class="o">=</span><span class="n">thread_task</span><span class="p">,</span> <span class="n">args</span><span class="o">=</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">i</span><span class="p">),</span> <span class="n">i</span><span class="p">))</span>
|
||
<span class="n">T</span><span class="o">.</span><span class="n">start</span><span class="p">()</span>
|
||
|
||
<span class="n">time</span><span class="o">.</span><span class="n">sleep</span><span class="p">(</span><span class="mi">10</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>比起用 <a class="reference internal" href="../library/time.html#time.sleep" title="time.sleep"><code class="xref py py-func docutils literal notranslate"><span class="pre">time.sleep()</span></code></a> 猜一个合适的等待时间,使用信号量机制会更好些。有一个办法是使用 <a class="reference internal" href="../library/queue.html#module-queue" title="queue: A synchronized queue class."><code class="xref py py-mod docutils literal notranslate"><span class="pre">queue</span></code></a> 模块创建一个 queue 对象,让每一个线程在运行结束时 append 一个令牌到 queue 对象中,主线程中从 queue 对象中读取与线程数量一致的令牌数量即可。</p>
|
||
</section>
|
||
<section id="how-do-i-parcel-out-work-among-a-bunch-of-worker-threads">
|
||
<h3><a class="toc-backref" href="#id17">如何将任务分配给多个工作线程?</a><a class="headerlink" href="#how-do-i-parcel-out-work-among-a-bunch-of-worker-threads" title="永久链接至标题">¶</a></h3>
|
||
<p>最简单的方法是使用新的 <a class="reference internal" href="../library/concurrent.futures.html#module-concurrent.futures" title="concurrent.futures: Execute computations concurrently using threads or processes."><code class="xref py py-mod docutils literal notranslate"><span class="pre">concurrent.futures</span></code></a> 模块,尤其是其中的 <a class="reference internal" href="../library/concurrent.futures.html#concurrent.futures.ThreadPoolExecutor" title="concurrent.futures.ThreadPoolExecutor"><code class="xref py py-mod docutils literal notranslate"><span class="pre">ThreadPoolExecutor</span></code></a> 类。</p>
|
||
<p>或者,如果你想更好地控制分发算法,你也可以自己写逻辑实现。使用 <a class="reference internal" href="../library/queue.html#module-queue" title="queue: A synchronized queue class."><code class="xref py py-mod docutils literal notranslate"><span class="pre">queue</span></code></a> 模块来创建任务列表队列。<a class="reference internal" href="../library/queue.html#queue.Queue" title="queue.Queue"><code class="xref py py-class docutils literal notranslate"><span class="pre">Queue</span></code></a> 类维护一个了一个存有对象的列表,提供了 <code class="docutils literal notranslate"><span class="pre">.put(obj)</span></code> 方法添加元素,并且可以用 <code class="docutils literal notranslate"><span class="pre">.get()</span></code> 方法获取元素。这个类会使用必要的加锁操作,以此确保每个任务只会执行一次。</p>
|
||
<p>这是一个简单的例子:</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">threading</span><span class="o">,</span> <span class="nn">queue</span><span class="o">,</span> <span class="nn">time</span>
|
||
|
||
<span class="c1"># The worker thread gets jobs off the queue. When the queue is empty, it</span>
|
||
<span class="c1"># assumes there will be no more work and exits.</span>
|
||
<span class="c1"># (Realistically workers will run until terminated.)</span>
|
||
<span class="k">def</span> <span class="nf">worker</span><span class="p">():</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="s1">'Running worker'</span><span class="p">)</span>
|
||
<span class="n">time</span><span class="o">.</span><span class="n">sleep</span><span class="p">(</span><span class="mf">0.1</span><span class="p">)</span>
|
||
<span class="k">while</span> <span class="kc">True</span><span class="p">:</span>
|
||
<span class="k">try</span><span class="p">:</span>
|
||
<span class="n">arg</span> <span class="o">=</span> <span class="n">q</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">block</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span>
|
||
<span class="k">except</span> <span class="n">queue</span><span class="o">.</span><span class="n">Empty</span><span class="p">:</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="s1">'Worker'</span><span class="p">,</span> <span class="n">threading</span><span class="o">.</span><span class="n">currentThread</span><span class="p">(),</span> <span class="n">end</span><span class="o">=</span><span class="s1">' '</span><span class="p">)</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="s1">'queue empty'</span><span class="p">)</span>
|
||
<span class="k">break</span>
|
||
<span class="k">else</span><span class="p">:</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="s1">'Worker'</span><span class="p">,</span> <span class="n">threading</span><span class="o">.</span><span class="n">currentThread</span><span class="p">(),</span> <span class="n">end</span><span class="o">=</span><span class="s1">' '</span><span class="p">)</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="s1">'running with argument'</span><span class="p">,</span> <span class="n">arg</span><span class="p">)</span>
|
||
<span class="n">time</span><span class="o">.</span><span class="n">sleep</span><span class="p">(</span><span class="mf">0.5</span><span class="p">)</span>
|
||
|
||
<span class="c1"># Create queue</span>
|
||
<span class="n">q</span> <span class="o">=</span> <span class="n">queue</span><span class="o">.</span><span class="n">Queue</span><span class="p">()</span>
|
||
|
||
<span class="c1"># Start a pool of 5 workers</span>
|
||
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">5</span><span class="p">):</span>
|
||
<span class="n">t</span> <span class="o">=</span> <span class="n">threading</span><span class="o">.</span><span class="n">Thread</span><span class="p">(</span><span class="n">target</span><span class="o">=</span><span class="n">worker</span><span class="p">,</span> <span class="n">name</span><span class="o">=</span><span class="s1">'worker </span><span class="si">%i</span><span class="s1">'</span> <span class="o">%</span> <span class="p">(</span><span class="n">i</span><span class="o">+</span><span class="mi">1</span><span class="p">))</span>
|
||
<span class="n">t</span><span class="o">.</span><span class="n">start</span><span class="p">()</span>
|
||
|
||
<span class="c1"># Begin adding work to the queue</span>
|
||
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">50</span><span class="p">):</span>
|
||
<span class="n">q</span><span class="o">.</span><span class="n">put</span><span class="p">(</span><span class="n">i</span><span class="p">)</span>
|
||
|
||
<span class="c1"># Give threads time to run</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="s1">'Main thread sleeping'</span><span class="p">)</span>
|
||
<span class="n">time</span><span class="o">.</span><span class="n">sleep</span><span class="p">(</span><span class="mi">5</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>运行时会产生如下输出:</p>
|
||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>Running worker
|
||
Running worker
|
||
Running worker
|
||
Running worker
|
||
Running worker
|
||
Main thread sleeping
|
||
Worker <Thread(worker 1, started 130283832797456)> running with argument 0
|
||
Worker <Thread(worker 2, started 130283824404752)> running with argument 1
|
||
Worker <Thread(worker 3, started 130283816012048)> running with argument 2
|
||
Worker <Thread(worker 4, started 130283807619344)> running with argument 3
|
||
Worker <Thread(worker 5, started 130283799226640)> running with argument 4
|
||
Worker <Thread(worker 1, started 130283832797456)> running with argument 5
|
||
...
|
||
</pre></div>
|
||
</div>
|
||
<p>查看模块的文档以获取更多信息;<a class="reference internal" href="../library/queue.html#queue.Queue" title="queue.Queue"><code class="xref py py-class docutils literal notranslate"><span class="pre">Queue</span></code></a> 类提供了多种接口。</p>
|
||
</section>
|
||
<section id="what-kinds-of-global-value-mutation-are-thread-safe">
|
||
<h3><a class="toc-backref" href="#id18">怎样修改全局变量是线程安全的?</a><a class="headerlink" href="#what-kinds-of-global-value-mutation-are-thread-safe" title="永久链接至标题">¶</a></h3>
|
||
<p>Python VM 内部会使用 <a class="reference internal" href="../glossary.html#term-global-interpreter-lock"><span class="xref std std-term">global interpreter lock</span></a> (GIL)来确保同一时间只有一个线程运行。通常 Python 只会在字节码指令之间切换线程;切换的频率可以通过设置 <a class="reference internal" href="../library/sys.html#sys.setswitchinterval" title="sys.setswitchinterval"><code class="xref py py-func docutils literal notranslate"><span class="pre">sys.setswitchinterval()</span></code></a> 指定。从 Python 程序的角度来看,每一条字节码指令以及每一条指令对应的 C 代码实现都是原子的。</p>
|
||
<p>理论上说,具体的结果要看具体的 PVM 字节码实现对指令的解释。而实际上,对内建类型(int,list,dict 等)的共享变量的“类原子”操作都是原子的。</p>
|
||
<p>举例来说,下面的操作是原子的(L、L1、L2 是列表,D、D1、D2 是字典,x、y 是对象,i,j 是 int 变量):</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">L</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">x</span><span class="p">)</span>
|
||
<span class="n">L1</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">L2</span><span class="p">)</span>
|
||
<span class="n">x</span> <span class="o">=</span> <span class="n">L</span><span class="p">[</span><span class="n">i</span><span class="p">]</span>
|
||
<span class="n">x</span> <span class="o">=</span> <span class="n">L</span><span class="o">.</span><span class="n">pop</span><span class="p">()</span>
|
||
<span class="n">L1</span><span class="p">[</span><span class="n">i</span><span class="p">:</span><span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="n">L2</span>
|
||
<span class="n">L</span><span class="o">.</span><span class="n">sort</span><span class="p">()</span>
|
||
<span class="n">x</span> <span class="o">=</span> <span class="n">y</span>
|
||
<span class="n">x</span><span class="o">.</span><span class="n">field</span> <span class="o">=</span> <span class="n">y</span>
|
||
<span class="n">D</span><span class="p">[</span><span class="n">x</span><span class="p">]</span> <span class="o">=</span> <span class="n">y</span>
|
||
<span class="n">D1</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="n">D2</span><span class="p">)</span>
|
||
<span class="n">D</span><span class="o">.</span><span class="n">keys</span><span class="p">()</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>这些不是原子的:</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">i</span> <span class="o">=</span> <span class="n">i</span><span class="o">+</span><span class="mi">1</span>
|
||
<span class="n">L</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">L</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">])</span>
|
||
<span class="n">L</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">L</span><span class="p">[</span><span class="n">j</span><span class="p">]</span>
|
||
<span class="n">D</span><span class="p">[</span><span class="n">x</span><span class="p">]</span> <span class="o">=</span> <span class="n">D</span><span class="p">[</span><span class="n">x</span><span class="p">]</span> <span class="o">+</span> <span class="mi">1</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>覆盖其他对象的操作会在其他对象的引用计数变成 0 时触发其 <a class="reference internal" href="../reference/datamodel.html#object.__del__" title="object.__del__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__del__()</span></code></a> 方法,这可能会产生一些影响。对字典和列表进行大量操作时尤其如此。如果有疑问的话,使用互斥锁!</p>
|
||
</section>
|
||
<section id="can-t-we-get-rid-of-the-global-interpreter-lock">
|
||
<h3><a class="toc-backref" href="#id19">不能删除全局解释器锁吗?</a><a class="headerlink" href="#can-t-we-get-rid-of-the-global-interpreter-lock" title="永久链接至标题">¶</a></h3>
|
||
<p><a class="reference internal" href="../glossary.html#term-global-interpreter-lock"><span class="xref std std-term">global interpreter lock</span></a> (GIL)通常被视为 Python 在高端多核服务器上开发时的阻力,因为(几乎)所有 Python 代码只有在获取到 GIL 时才能运行,所以多线程的 Python 程序只能有效地使用一个 CPU。</p>
|
||
<p>在 Python 1.5 时代,Greg Stein 开发了一个完整的补丁包(“free threadings” 补丁),移除了 GIL,并用粒度更合适的锁来代替。Adam Olsen 最近也在他的 <a class="reference external" href="https://code.google.com/archive/p/python-safethread">python-safethread</a> 项目里做了类似的实验。不幸的是,由于为了移除 GIL 而使用了大量细粒度的锁,这两个实验在单线程测试中的性能都有明显的下降(至少慢 30%)。</p>
|
||
<p>但这并意味着你不能在多核机器上很好地使用 Python!你只需将任务划分为多*进程*,而不是多*线程*。新的 <a class="reference internal" href="../library/concurrent.futures.html#module-concurrent.futures" title="concurrent.futures: Execute computations concurrently using threads or processes."><code class="xref py py-mod docutils literal notranslate"><span class="pre">concurrent.futures</span></code></a> 模块中的 <a class="reference internal" href="../library/concurrent.futures.html#concurrent.futures.ProcessPoolExecutor" title="concurrent.futures.ProcessPoolExecutor"><code class="xref py py-class docutils literal notranslate"><span class="pre">ProcessPoolExecutor</span></code></a> 类提供了一个简单的方法;如果你想对任务分发做更多控制,可以使用 <a class="reference internal" href="../library/multiprocessing.html#module-multiprocessing" title="multiprocessing: Process-based parallelism."><code class="xref py py-mod docutils literal notranslate"><span class="pre">multiprocessing</span></code></a> 模块提供的底层 API。</p>
|
||
<p>恰当地使用 C 拓展也很有用;使用 C 拓展处理耗时较久的任务时,拓展可以在线程执行 C 代码时释放 GIL,让其他线程执行。<a class="reference internal" href="../library/zlib.html#module-zlib" title="zlib: Low-level interface to compression and decompression routines compatible with gzip."><code class="xref py py-mod docutils literal notranslate"><span class="pre">zlib</span></code></a> 和 <a class="reference internal" href="../library/hashlib.html#module-hashlib" title="hashlib: Secure hash and message digest algorithms."><code class="xref py py-mod docutils literal notranslate"><span class="pre">hashlib</span></code></a> 等标准库模块已经这样做了。</p>
|
||
<p>也有建议说 GIL 应该是解释器状态锁,而不是完全的全局锁;解释器不应该共享对象。不幸的是,这也不可能发生。由于目前许多对象的实现都有全局的状态,因此这是一个艰巨的工作。举例来说,小整型数和短字符串会缓存起来,这些缓存将不得不移动到解释器状态中。其他对象类型都有自己的自由变量列表,这些自由变量列表也必须移动到解释器状态中。等等。</p>
|
||
<p>我甚至怀疑这些工作是否可能在有限的时间内完成,因为同样的问题在第三方拓展中也会存在。第三方拓展编写的速度可比你将它们转换为把全局状态存入解释器状态中的速度快得多。</p>
|
||
<p>最后,假设多个解释器不共享任何状态,那么这样做比每个进程一个解释器好在哪里呢?</p>
|
||
</section>
|
||
</section>
|
||
<section id="input-and-output">
|
||
<h2><a class="toc-backref" href="#id20">输入输出</a><a class="headerlink" href="#input-and-output" title="永久链接至标题">¶</a></h2>
|
||
<section id="how-do-i-delete-a-file-and-other-file-questions">
|
||
<h3><a class="toc-backref" href="#id21">怎样删除文件?(以及其他文件相关的问题……)</a><a class="headerlink" href="#how-do-i-delete-a-file-and-other-file-questions" title="永久链接至标题">¶</a></h3>
|
||
<p>使用 <code class="docutils literal notranslate"><span class="pre">os.remove(filename)</span></code> 或 <code class="docutils literal notranslate"><span class="pre">os.unlink(filename)</span></code>。查看 <a class="reference internal" href="../library/os.html#module-os" title="os: Miscellaneous operating system interfaces."><code class="xref py py-mod docutils literal notranslate"><span class="pre">os</span></code></a> 模块以获取更多文档。这两个函数是一样的,<a class="reference internal" href="../library/os.html#os.unlink" title="os.unlink"><code class="xref py py-func docutils literal notranslate"><span class="pre">unlink()</span></code></a> 是这个函数在 Unix 系统调用中的名字。</p>
|
||
<p>如果要删除目录,应该使用 <a class="reference internal" href="../library/os.html#os.rmdir" title="os.rmdir"><code class="xref py py-func docutils literal notranslate"><span class="pre">os.rmdir()</span></code></a>;使用 <a class="reference internal" href="../library/os.html#os.mkdir" title="os.mkdir"><code class="xref py py-func docutils literal notranslate"><span class="pre">os.mkdir()</span></code></a> 创建目录。<code class="docutils literal notranslate"><span class="pre">os.makedirs(path)</span></code> 会创建 <code class="docutils literal notranslate"><span class="pre">path</span></code> 中任何不存在的目录。<code class="docutils literal notranslate"><span class="pre">os.removedirs(path)</span></code> 则会删除其中的目录,只要它们都是空的;如果你想删除整个目录以及其中的内容,可以使用 <a class="reference internal" href="../library/shutil.html#shutil.rmtree" title="shutil.rmtree"><code class="xref py py-func docutils literal notranslate"><span class="pre">shutil.rmtree()</span></code></a>。</p>
|
||
<p>重命名文件可以使用 <code class="docutils literal notranslate"><span class="pre">os.rename(old_path,</span> <span class="pre">new_path)</span></code>。</p>
|
||
<p>如果需要截断文件,使用 <code class="docutils literal notranslate"><span class="pre">f</span> <span class="pre">=</span> <span class="pre">open(filename,</span> <span class="pre">"rb+")</span></code> 打开文件,然后使用 <code class="docutils literal notranslate"><span class="pre">f.truncate(offset)</span></code>;offset 默认是当前的搜索位置。也可以对使用 <a class="reference internal" href="../library/os.html#os.open" title="os.open"><code class="xref py py-func docutils literal notranslate"><span class="pre">os.open()</span></code></a> 打开的文件使用 <code class="docutils literal notranslate"><span class="pre">os.ftruncate(fd,</span> <span class="pre">offset)</span></code>,其中 <em>fd</em> 是文件描述符(一个小的整型数)。</p>
|
||
<p><a class="reference internal" href="../library/shutil.html#module-shutil" title="shutil: High-level file operations, including copying."><code class="xref py py-mod docutils literal notranslate"><span class="pre">shutil</span></code></a> 模块也包含了一些处理文件的函数,包括 <a class="reference internal" href="../library/shutil.html#shutil.copyfile" title="shutil.copyfile"><code class="xref py py-func docutils literal notranslate"><span class="pre">copyfile()</span></code></a>,<a class="reference internal" href="../library/shutil.html#shutil.copytree" title="shutil.copytree"><code class="xref py py-func docutils literal notranslate"><span class="pre">copytree()</span></code></a> 和 <a class="reference internal" href="../library/shutil.html#shutil.rmtree" title="shutil.rmtree"><code class="xref py py-func docutils literal notranslate"><span class="pre">rmtree()</span></code></a>。</p>
|
||
</section>
|
||
<section id="how-do-i-copy-a-file">
|
||
<h3><a class="toc-backref" href="#id22">怎样复制文件?</a><a class="headerlink" href="#how-do-i-copy-a-file" title="永久链接至标题">¶</a></h3>
|
||
<p><a class="reference internal" href="../library/shutil.html#module-shutil" title="shutil: High-level file operations, including copying."><code class="xref py py-mod docutils literal notranslate"><span class="pre">shutil</span></code></a> 模块有一个 <a class="reference internal" href="../library/shutil.html#shutil.copyfile" title="shutil.copyfile"><code class="xref py py-func docutils literal notranslate"><span class="pre">copyfile()</span></code></a> 函数。注意在 MacOS 9 中不会复制 resource fork 和 Finder info。</p>
|
||
</section>
|
||
<section id="how-do-i-read-or-write-binary-data">
|
||
<h3><a class="toc-backref" href="#id23">怎样读取(或写入)二进制数据?</a><a class="headerlink" href="#how-do-i-read-or-write-binary-data" title="永久链接至标题">¶</a></h3>
|
||
<p>要读写复杂的二进制数据格式,最好使用 <a class="reference internal" href="../library/struct.html#module-struct" title="struct: Interpret bytes as packed binary data."><code class="xref py py-mod docutils literal notranslate"><span class="pre">struct</span></code></a> 模块。该模块可以读取包含二进制数据(通常是数字)的字符串并转换为 Python 对象,反之亦然。</p>
|
||
<p>举例来说,下面的代码会从文件中以大端序格式读取一个 2 字节的整型和一个 4 字节的整型:</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">struct</span>
|
||
|
||
<span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">filename</span><span class="p">,</span> <span class="s2">"rb"</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
|
||
<span class="n">s</span> <span class="o">=</span> <span class="n">f</span><span class="o">.</span><span class="n">read</span><span class="p">(</span><span class="mi">8</span><span class="p">)</span>
|
||
<span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="n">z</span> <span class="o">=</span> <span class="n">struct</span><span class="o">.</span><span class="n">unpack</span><span class="p">(</span><span class="s2">">hhl"</span><span class="p">,</span> <span class="n">s</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>格式字符串中的 ‘>’ 强制以大端序读取数据;字母 ‘h’ 从字符串中读取一个“短整型”(2 字节),字母 ‘l’ 读取一个“长整型”(4 字节)。</p>
|
||
<p>对于更常规的数据(例如整型或浮点类型的列表),你也可以使用 <a class="reference internal" href="../library/array.html#module-array" title="array: Space efficient arrays of uniformly typed numeric values."><code class="xref py py-mod docutils literal notranslate"><span class="pre">array</span></code></a> 模块。</p>
|
||
<div class="admonition note">
|
||
<p class="admonition-title">注解</p>
|
||
<p>要读写二进制数据的话,需要强制以二进制模式打开文件(这里为 <a class="reference internal" href="../library/functions.html#open" title="open"><code class="xref py py-func docutils literal notranslate"><span class="pre">open()</span></code></a> 函数传入 <code class="docutils literal notranslate"><span class="pre">"rb"</span></code>)。如果(默认)传入 <code class="docutils literal notranslate"><span class="pre">"r"</span></code> 的话,文件会以文本模式打开,<code class="docutils literal notranslate"><span class="pre">f.read()</span></code> 会返回 <a class="reference internal" href="../library/stdtypes.html#str" title="str"><code class="xref py py-class docutils literal notranslate"><span class="pre">str</span></code></a> 对象,而不是 <a class="reference internal" href="../library/stdtypes.html#bytes" title="bytes"><code class="xref py py-class docutils literal notranslate"><span class="pre">bytes</span></code></a> 对象。</p>
|
||
</div>
|
||
</section>
|
||
<section id="i-can-t-seem-to-use-os-read-on-a-pipe-created-with-os-popen-why">
|
||
<h3><a class="toc-backref" href="#id24">似乎 os.popen() 创建的管道不能使用 os.read(),这是为什么?</a><a class="headerlink" href="#i-can-t-seem-to-use-os-read-on-a-pipe-created-with-os-popen-why" title="永久链接至标题">¶</a></h3>
|
||
<p><a class="reference internal" href="../library/os.html#os.read" title="os.read"><code class="xref py py-func docutils literal notranslate"><span class="pre">os.read()</span></code></a> 是一个底层函数,它接收的是文件描述符 —— 用小整型数表示的打开的文件。<a class="reference internal" href="../library/os.html#os.popen" title="os.popen"><code class="xref py py-func docutils literal notranslate"><span class="pre">os.popen()</span></code></a> 创建的是一个高级文件对象,和内建的 <a class="reference internal" href="../library/functions.html#open" title="open"><code class="xref py py-func docutils literal notranslate"><span class="pre">open()</span></code></a> 方法返回的类型一样。因此,如果要从 <a class="reference internal" href="../library/os.html#os.popen" title="os.popen"><code class="xref py py-func docutils literal notranslate"><span class="pre">os.popen()</span></code></a> 创建的管道 <em>p</em> 中读取 <em>n</em> 个字节的话,你应该使用 <code class="docutils literal notranslate"><span class="pre">p.read(n)</span></code>。</p>
|
||
</section>
|
||
<section id="how-do-i-access-the-serial-rs232-port">
|
||
<h3><a class="toc-backref" href="#id25">怎样访问(RS232)串口?</a><a class="headerlink" href="#how-do-i-access-the-serial-rs232-port" title="永久链接至标题">¶</a></h3>
|
||
<p>对于 Win32,POSIX(Linux,BSD 等),Jython:</p>
|
||
<blockquote>
|
||
<div><p><a class="reference external" href="http://pyserial.sourceforge.net">http://pyserial.sourceforge.net</a></p>
|
||
</div></blockquote>
|
||
<p>对于 Unix,查看 Mitch Chapman 发布的帖子:</p>
|
||
<blockquote>
|
||
<div><p><a class="reference external" href="https://groups.google.com/groups?selm=34A04430.CF9@ohioee.com">https://groups.google.com/groups?selm=34A04430.CF9@ohioee.com</a></p>
|
||
</div></blockquote>
|
||
</section>
|
||
<section id="why-doesn-t-closing-sys-stdout-stdin-stderr-really-close-it">
|
||
<h3><a class="toc-backref" href="#id26">为什么关闭 sys.stdout(stdin,stderr)并不会真正关掉它?</a><a class="headerlink" href="#why-doesn-t-closing-sys-stdout-stdin-stderr-really-close-it" title="永久链接至标题">¶</a></h3>
|
||
<p>Python <a class="reference internal" href="../glossary.html#term-file-object"><span class="xref std std-term">文件对象</span></a> 是一个对底层 C 文件描述符的高层抽象。</p>
|
||
<p>对于在 Python 中通过内建的 <a class="reference internal" href="../library/functions.html#open" title="open"><code class="xref py py-func docutils literal notranslate"><span class="pre">open()</span></code></a> 函数创建的多数文件对象来说,<code class="docutils literal notranslate"><span class="pre">f.close()</span></code> 从 Python 的角度将其标记为已关闭,并且会关闭底层的 C 文件描述符。在 <code class="docutils literal notranslate"><span class="pre">f</span></code> 被垃圾回收的时候,析构函数中也会自动处理。</p>
|
||
<p>但由于 stdin,stdout 和 stderr 在 C 中的特殊地位,在 Python 中也会对它们做特殊处理。运行 <code class="docutils literal notranslate"><span class="pre">sys.stdout.close()</span></code> 会将 Python 的文件对象标记为已关闭,但是*不会*关闭与之关联的文件描述符。</p>
|
||
<p>要关闭这三者的 C 文件描述符的话,首先你应该确认确实需要关闭它(比如,这可能会影响到处理 I/O 的拓展)。如果确实需要这么做的话,使用 <a class="reference internal" href="../library/os.html#os.close" title="os.close"><code class="xref py py-func docutils literal notranslate"><span class="pre">os.close()</span></code></a>:</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">os</span><span class="o">.</span><span class="n">close</span><span class="p">(</span><span class="n">stdin</span><span class="o">.</span><span class="n">fileno</span><span class="p">())</span>
|
||
<span class="n">os</span><span class="o">.</span><span class="n">close</span><span class="p">(</span><span class="n">stdout</span><span class="o">.</span><span class="n">fileno</span><span class="p">())</span>
|
||
<span class="n">os</span><span class="o">.</span><span class="n">close</span><span class="p">(</span><span class="n">stderr</span><span class="o">.</span><span class="n">fileno</span><span class="p">())</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>或者也可以使用常量 0,1,2 代替。</p>
|
||
</section>
|
||
</section>
|
||
<section id="network-internet-programming">
|
||
<h2><a class="toc-backref" href="#id27">网络 / Internet 编程</a><a class="headerlink" href="#network-internet-programming" title="永久链接至标题">¶</a></h2>
|
||
<section id="what-www-tools-are-there-for-python">
|
||
<h3><a class="toc-backref" href="#id28">Python 中的 WWW 工具是什么?</a><a class="headerlink" href="#what-www-tools-are-there-for-python" title="永久链接至标题">¶</a></h3>
|
||
<p>参阅代码库参考手册中 <a class="reference internal" href="../library/internet.html#internet"><span class="std std-ref">互联网协议和支持</span></a> 和 <a class="reference internal" href="../library/netdata.html#netdata"><span class="std std-ref">互联网数据处理</span></a> 这两章的内容。Python 有大量模块来帮助你构建服务端和客户端 web 系统。</p>
|
||
<p>Paul Boddie 维护了一份可用框架的概览,见 <a class="reference external" href="https://wiki.python.org/moin/WebProgramming">https://wiki.python.org/moin/WebProgramming</a> 。</p>
|
||
<p>Cameron Laird 维护了一份关于 Python web 技术的实用网页的集合,见 <a class="reference external" href="http://phaseit.net/claird/comp.lang.python/web_python">http://phaseit.net/claird/comp.lang.python/web_python</a> 。</p>
|
||
</section>
|
||
<section id="how-can-i-mimic-cgi-form-submission-method-post">
|
||
<h3><a class="toc-backref" href="#id29">怎样模拟发送 CGI 表单(METHOD=POST)?</a><a class="headerlink" href="#how-can-i-mimic-cgi-form-submission-method-post" title="永久链接至标题">¶</a></h3>
|
||
<p>我需要通过 POST 表单获取网页,有什么代码能简单做到吗?</p>
|
||
<p>是的,这里有一个使用 urllib.request 的简单例子:</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="ch">#!/usr/local/bin/python</span>
|
||
|
||
<span class="kn">import</span> <span class="nn">urllib.request</span>
|
||
|
||
<span class="c1"># build the query string</span>
|
||
<span class="n">qs</span> <span class="o">=</span> <span class="s2">"First=Josephine&MI=Q&Last=Public"</span>
|
||
|
||
<span class="c1"># connect and send the server a path</span>
|
||
<span class="n">req</span> <span class="o">=</span> <span class="n">urllib</span><span class="o">.</span><span class="n">request</span><span class="o">.</span><span class="n">urlopen</span><span class="p">(</span><span class="s1">'http://www.some-server.out-there'</span>
|
||
<span class="s1">'/cgi-bin/some-cgi-script'</span><span class="p">,</span> <span class="n">data</span><span class="o">=</span><span class="n">qs</span><span class="p">)</span>
|
||
<span class="k">with</span> <span class="n">req</span><span class="p">:</span>
|
||
<span class="n">msg</span><span class="p">,</span> <span class="n">hdrs</span> <span class="o">=</span> <span class="n">req</span><span class="o">.</span><span class="n">read</span><span class="p">(),</span> <span class="n">req</span><span class="o">.</span><span class="n">info</span><span class="p">()</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>注意,通常在百分号编码的 POST 操作中,查询字符串必须使用 <a class="reference internal" href="../library/urllib.parse.html#urllib.parse.urlencode" title="urllib.parse.urlencode"><code class="xref py py-func docutils literal notranslate"><span class="pre">urllib.parse.urlencode()</span></code></a> 处理一下。举个例子,如果要发送 <code class="docutils literal notranslate"><span class="pre">name=Guy</span> <span class="pre">Steele,</span> <span class="pre">Jr.</span></code> 的话:</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="kn">import</span> <span class="nn">urllib.parse</span>
|
||
<span class="gp">>>> </span><span class="n">urllib</span><span class="o">.</span><span class="n">parse</span><span class="o">.</span><span class="n">urlencode</span><span class="p">({</span><span class="s1">'name'</span><span class="p">:</span> <span class="s1">'Guy Steele, Jr.'</span><span class="p">})</span>
|
||
<span class="go">'name=Guy+Steele%2C+Jr.'</span>
|
||
</pre></div>
|
||
</div>
|
||
<div class="admonition seealso">
|
||
<p class="admonition-title">参见</p>
|
||
<p>查看 <a class="reference internal" href="../howto/urllib2.html#urllib-howto"><span class="std std-ref">如何利用 urllib 包获取网络资源</span></a> 获取更多示例。</p>
|
||
</div>
|
||
</section>
|
||
<section id="what-module-should-i-use-to-help-with-generating-html">
|
||
<h3><a class="toc-backref" href="#id30">生成 HTML 需要使用什么模块?</a><a class="headerlink" href="#what-module-should-i-use-to-help-with-generating-html" title="永久链接至标题">¶</a></h3>
|
||
<p>你可以在 <a class="reference external" href="https://wiki.python.org/moin/WebProgramming">Web 编程 wiki 页面</a> 找到许多有用的链接。</p>
|
||
</section>
|
||
<section id="how-do-i-send-mail-from-a-python-script">
|
||
<h3><a class="toc-backref" href="#id31">怎样使用 Python 脚本发送邮件?</a><a class="headerlink" href="#how-do-i-send-mail-from-a-python-script" title="永久链接至标题">¶</a></h3>
|
||
<p>使用 <a class="reference internal" href="../library/smtplib.html#module-smtplib" title="smtplib: SMTP protocol client (requires sockets)."><code class="xref py py-mod docutils literal notranslate"><span class="pre">smtplib</span></code></a> 标准库模块。</p>
|
||
<p>下面是一个很简单的交互式发送邮件的代码。这个方法适用于任何支持 SMTP 协议的主机。</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">sys</span><span class="o">,</span> <span class="nn">smtplib</span>
|
||
|
||
<span class="n">fromaddr</span> <span class="o">=</span> <span class="nb">input</span><span class="p">(</span><span class="s2">"From: "</span><span class="p">)</span>
|
||
<span class="n">toaddrs</span> <span class="o">=</span> <span class="nb">input</span><span class="p">(</span><span class="s2">"To: "</span><span class="p">)</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s1">','</span><span class="p">)</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="s2">"Enter message, end with ^D:"</span><span class="p">)</span>
|
||
<span class="n">msg</span> <span class="o">=</span> <span class="s1">''</span>
|
||
<span class="k">while</span> <span class="kc">True</span><span class="p">:</span>
|
||
<span class="n">line</span> <span class="o">=</span> <span class="n">sys</span><span class="o">.</span><span class="n">stdin</span><span class="o">.</span><span class="n">readline</span><span class="p">()</span>
|
||
<span class="k">if</span> <span class="ow">not</span> <span class="n">line</span><span class="p">:</span>
|
||
<span class="k">break</span>
|
||
<span class="n">msg</span> <span class="o">+=</span> <span class="n">line</span>
|
||
|
||
<span class="c1"># The actual mail send</span>
|
||
<span class="n">server</span> <span class="o">=</span> <span class="n">smtplib</span><span class="o">.</span><span class="n">SMTP</span><span class="p">(</span><span class="s1">'localhost'</span><span class="p">)</span>
|
||
<span class="n">server</span><span class="o">.</span><span class="n">sendmail</span><span class="p">(</span><span class="n">fromaddr</span><span class="p">,</span> <span class="n">toaddrs</span><span class="p">,</span> <span class="n">msg</span><span class="p">)</span>
|
||
<span class="n">server</span><span class="o">.</span><span class="n">quit</span><span class="p">()</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>在 Unix 系统中还可以使用 sendmail。sendmail 程序的位置在不同系统中不一样,有时是在 <code class="docutils literal notranslate"><span class="pre">/usr/lib/sendmail</span></code>,有时是在 <code class="docutils literal notranslate"><span class="pre">/usr/sbin/sendmail</span></code>。sendmail 手册页面会对你有所帮助。以下是示例代码:</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">os</span>
|
||
|
||
<span class="n">SENDMAIL</span> <span class="o">=</span> <span class="s2">"/usr/sbin/sendmail"</span> <span class="c1"># sendmail location</span>
|
||
<span class="n">p</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">popen</span><span class="p">(</span><span class="s2">"</span><span class="si">%s</span><span class="s2"> -t -i"</span> <span class="o">%</span> <span class="n">SENDMAIL</span><span class="p">,</span> <span class="s2">"w"</span><span class="p">)</span>
|
||
<span class="n">p</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s2">"To: receiver@example.com</span><span class="se">\n</span><span class="s2">"</span><span class="p">)</span>
|
||
<span class="n">p</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s2">"Subject: test</span><span class="se">\n</span><span class="s2">"</span><span class="p">)</span>
|
||
<span class="n">p</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s2">"</span><span class="se">\n</span><span class="s2">"</span><span class="p">)</span> <span class="c1"># blank line separating headers from body</span>
|
||
<span class="n">p</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s2">"Some text</span><span class="se">\n</span><span class="s2">"</span><span class="p">)</span>
|
||
<span class="n">p</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s2">"some more text</span><span class="se">\n</span><span class="s2">"</span><span class="p">)</span>
|
||
<span class="n">sts</span> <span class="o">=</span> <span class="n">p</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
|
||
<span class="k">if</span> <span class="n">sts</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">:</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="s2">"Sendmail exit status"</span><span class="p">,</span> <span class="n">sts</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
</section>
|
||
<section id="how-do-i-avoid-blocking-in-the-connect-method-of-a-socket">
|
||
<h3><a class="toc-backref" href="#id32">socket 的 connect() 方法怎样避免阻塞?</a><a class="headerlink" href="#how-do-i-avoid-blocking-in-the-connect-method-of-a-socket" title="永久链接至标题">¶</a></h3>
|
||
<p>通常会用 <a class="reference internal" href="../library/select.html#module-select" title="select: Wait for I/O completion on multiple streams."><code class="xref py py-mod docutils literal notranslate"><span class="pre">select</span></code></a> 模块处理 socket 异步 I/O。</p>
|
||
<p>要避免 TCP 连接阻塞,你可以设置将 socket 设置为非阻塞模式。此时当调用 <code class="docutils literal notranslate"><span class="pre">connect()</span></code> 时,要么连接会立刻建立好(几乎不可能),要么会收到一个包含了错误码 <code class="docutils literal notranslate"><span class="pre">.error</span></code> 的异常。<code class="docutils literal notranslate"><span class="pre">errno.EINPROGRESS</span></code> 表示连接正在进行,但还没有完成。不同的系统会返回不同的值,所以你需要确认你使用的系统会返回什么。</p>
|
||
<p>你可以使用 <code class="docutils literal notranslate"><span class="pre">connect_ex()</span></code> 方法来避免产生异常。这个方法只会返回错误码。如果需要轮询的话,你可以再次调用 <code class="docutils literal notranslate"><span class="pre">connect_ex()</span></code> —— <code class="docutils literal notranslate"><span class="pre">0</span></code> 或 <code class="docutils literal notranslate"><span class="pre">errno.EISCONN</span></code> 表示连接已建立,或者你也可以用 select 检查这个 socket 是否可写。</p>
|
||
<div class="admonition note">
|
||
<p class="admonition-title">注解</p>
|
||
<p><a class="reference internal" href="../library/asyncore.html#module-asyncore" title="asyncore: A base class for developing asynchronous socket handling services."><code class="xref py py-mod docutils literal notranslate"><span class="pre">asyncore</span></code></a> 模块提供了编写非阻塞网络代码框架性的方法。第三方的 <a class="reference external" href="https://twistedmatrix.com/trac/">Twisted</a> 库也很常用且功能强大。</p>
|
||
</div>
|
||
</section>
|
||
</section>
|
||
<section id="databases">
|
||
<h2><a class="toc-backref" href="#id33">数据库</a><a class="headerlink" href="#databases" title="永久链接至标题">¶</a></h2>
|
||
<section id="are-there-any-interfaces-to-database-packages-in-python">
|
||
<h3><a class="toc-backref" href="#id34">Python 中有数据库包的接口吗?</a><a class="headerlink" href="#are-there-any-interfaces-to-database-packages-in-python" title="永久链接至标题">¶</a></h3>
|
||
<p>有的。</p>
|
||
<p>标准 Python 还包含了基于磁盘的哈希接口例如 <a class="reference internal" href="../library/dbm.html#module-dbm.ndbm" title="dbm.ndbm: The standard "database" interface, based on ndbm. (Unix)"><code class="xref py py-mod docutils literal notranslate"><span class="pre">DBM</span></code></a> 和 <a class="reference internal" href="../library/dbm.html#module-dbm.gnu" title="dbm.gnu: GNU's reinterpretation of dbm. (Unix)"><code class="xref py py-mod docutils literal notranslate"><span class="pre">GDBM</span></code></a> 。除此之外还有 <a class="reference internal" href="../library/sqlite3.html#module-sqlite3" title="sqlite3: A DB-API 2.0 implementation using SQLite 3.x."><code class="xref py py-mod docutils literal notranslate"><span class="pre">sqlite3</span></code></a> 模块,该模块提供了一个轻量级的基于磁盘的关系型数据库。</p>
|
||
<p>大多数关系型数据库都已经支持。查看 <a class="reference external" href="https://wiki.python.org/moin/DatabaseProgramming">数据库编程 wiki 页面</a> 获取更多信息。</p>
|
||
</section>
|
||
<section id="how-do-you-implement-persistent-objects-in-python">
|
||
<h3><a class="toc-backref" href="#id35">在 Python 中如何实现持久化对象?</a><a class="headerlink" href="#how-do-you-implement-persistent-objects-in-python" title="永久链接至标题">¶</a></h3>
|
||
<p><a class="reference internal" href="../library/pickle.html#module-pickle" title="pickle: Convert Python objects to streams of bytes and back."><code class="xref py py-mod docutils literal notranslate"><span class="pre">pickle</span></code></a> 库模块以一种非常通用的方式解决了这个问题(虽然你依然不能用它保存打开的文件、套接字或窗口之类的东西),此外 <a class="reference internal" href="../library/shelve.html#module-shelve" title="shelve: Python object persistence."><code class="xref py py-mod docutils literal notranslate"><span class="pre">shelve</span></code></a> 库模块可使用 pickle 和 (g)dbm 来创建包含任意 Python 对象的持久化映射。</p>
|
||
</section>
|
||
</section>
|
||
<section id="mathematics-and-numerics">
|
||
<h2><a class="toc-backref" href="#id36">数学和数字</a><a class="headerlink" href="#mathematics-and-numerics" title="永久链接至标题">¶</a></h2>
|
||
<section id="how-do-i-generate-random-numbers-in-python">
|
||
<h3><a class="toc-backref" href="#id37">Python 中怎样生成随机数?</a><a class="headerlink" href="#how-do-i-generate-random-numbers-in-python" title="永久链接至标题">¶</a></h3>
|
||
<p><a class="reference internal" href="../library/random.html#module-random" title="random: Generate pseudo-random numbers with various common distributions."><code class="xref py py-mod docutils literal notranslate"><span class="pre">random</span></code></a> 标准库模块实现了随机数生成器,使用起来非常简单:</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">random</span>
|
||
<span class="n">random</span><span class="o">.</span><span class="n">random</span><span class="p">()</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>这个函数会返回 [0, 1) 之间的随机浮点数。</p>
|
||
<p>该模块中还有许多其他的专门的生成器,例如:</p>
|
||
<ul class="simple">
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">randrange(a,</span> <span class="pre">b)</span></code> 返回 [a, b) 区间内的一个整型数。</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">uniform(a,</span> <span class="pre">b)</span></code> 返回 [a, b) 区间之间的浮点数。</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">normalvariate(mean,</span> <span class="pre">sdev)</span></code> 使用正态(高斯)分布采样。</p></li>
|
||
</ul>
|
||
<p>还有一些高级函数直接对序列进行操作,例如:</p>
|
||
<ul class="simple">
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">choice(S)</span></code> 从给定的序列中随机选择一个元素。</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">shuffle(L)</span></code> 对列表进行原地重排,也就是说随机打乱。</p></li>
|
||
</ul>
|
||
<p>还有 <code class="docutils literal notranslate"><span class="pre">Random</span></code> 类,你可以将其实例化,用来创建多个独立的随机数生成器。</p>
|
||
</section>
|
||
</section>
|
||
</section>
|
||
|
||
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
|
||
<div class="sphinxsidebarwrapper">
|
||
<h3><a href="../contents.html">目录</a></h3>
|
||
<ul>
|
||
<li><a class="reference internal" href="#">代码库和插件 FAQ</a><ul>
|
||
<li><a class="reference internal" href="#general-library-questions">通用的代码库问题</a></li>
|
||
<li><a class="reference internal" href="#common-tasks">通用任务</a></li>
|
||
<li><a class="reference internal" href="#threads">线程相关</a></li>
|
||
<li><a class="reference internal" href="#input-and-output">输入输出</a></li>
|
||
<li><a class="reference internal" href="#network-internet-programming">网络 / Internet 编程</a></li>
|
||
<li><a class="reference internal" href="#databases">数据库</a></li>
|
||
<li><a class="reference internal" href="#mathematics-and-numerics">数学和数字</a></li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
|
||
<h4>上一个主题</h4>
|
||
<p class="topless"><a href="design.html"
|
||
title="上一章">设计和历史常见问题</a></p>
|
||
<h4>下一个主题</h4>
|
||
<p class="topless"><a href="extending.html"
|
||
title="下一章">扩展/嵌入常见问题</a></p>
|
||
<div role="note" aria-label="source link">
|
||
<h3>本页</h3>
|
||
<ul class="this-page-menu">
|
||
<li><a href="../bugs.html">报告 Bug</a></li>
|
||
<li>
|
||
<a href="https://github.com/python/cpython/blob/3.8/Doc/faq/library.rst"
|
||
rel="nofollow">显示源代码
|
||
</a>
|
||
</li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="clearer"></div>
|
||
</div>
|
||
<div class="related" role="navigation" aria-label="related navigation">
|
||
<h3>导航</h3>
|
||
<ul>
|
||
<li class="right" style="margin-right: 10px">
|
||
<a href="../genindex.html" title="总目录"
|
||
>索引</a></li>
|
||
<li class="right" >
|
||
<a href="../py-modindex.html" title="Python 模块索引"
|
||
>模块</a> |</li>
|
||
<li class="right" >
|
||
<a href="extending.html" title="扩展/嵌入常见问题"
|
||
>下一页</a> |</li>
|
||
<li class="right" >
|
||
<a href="design.html" title="设计和历史常见问题"
|
||
>上一页</a> |</li>
|
||
|
||
<li><img src="../_static/py.svg" alt="python logo" style="vertical-align: middle; margin-top: -1px"/></li>
|
||
<li><a href="https://www.python.org/">Python</a> »</li>
|
||
<li class="switchers">
|
||
<div class="language_switcher_placeholder"></div>
|
||
<div class="version_switcher_placeholder"></div>
|
||
</li>
|
||
<li>
|
||
|
||
</li>
|
||
<li id="cpython-language-and-version">
|
||
<a href="../index.html">3.8.20 Documentation</a> »
|
||
</li>
|
||
|
||
<li class="nav-item nav-item-1"><a href="index.html" >Python 常见问题</a> »</li>
|
||
<li class="right">
|
||
|
||
|
||
<div class="inline-search" role="search">
|
||
<form class="inline-search" action="../search.html" method="get">
|
||
<input placeholder="快速搜索" aria-label="快速搜索" type="text" name="q" />
|
||
<input type="submit" value="转向" />
|
||
<input type="hidden" name="check_keywords" value="yes" />
|
||
<input type="hidden" name="area" value="default" />
|
||
</form>
|
||
</div>
|
||
|
|
||
</li>
|
||
|
||
</ul>
|
||
</div>
|
||
<div class="footer">
|
||
© <a href="../copyright.html">版权所有</a> 2001-2024, Python Software Foundation.
|
||
<br />
|
||
This page is licensed under the Python Software Foundation License Version 2.
|
||
<br />
|
||
Examples, recipes, and other code in the documentation are additionally licensed under the Zero Clause BSD License.
|
||
<br />
|
||
|
||
<br />
|
||
|
||
The Python Software Foundation is a non-profit corporation.
|
||
<a href="https://www.python.org/psf/donations/">Please donate.</a>
|
||
<br />
|
||
<br />
|
||
|
||
最后更新于 12月 09, 2024.
|
||
<a href="https://docs.python.org/3/bugs.html">Found a bug</a>?
|
||
<br />
|
||
|
||
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 2.4.4.
|
||
</div>
|
||
|
||
</body>
|
||
</html> |