2790 lines
374 KiB
HTML
2790 lines
374 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>multiprocessing --- 基于进程的并行 — 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="multiprocessing.shared_memory --- 可从进程直接访问的共享内存" href="multiprocessing.shared_memory.html" />
|
||
<link rel="prev" title="threading --- 基于线程的并行" href="threading.html" />
|
||
<link rel="canonical" href="https://docs.python.org/3/library/multiprocessing.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="#"><code class="xref py py-mod docutils literal notranslate"><span class="pre">multiprocessing</span></code> --- 基于进程的并行</a><ul>
|
||
<li><a class="reference internal" href="#introduction">概述</a><ul>
|
||
<li><a class="reference internal" href="#the-process-class"><code class="xref py py-class docutils literal notranslate"><span class="pre">Process</span></code> 类</a></li>
|
||
<li><a class="reference internal" href="#contexts-and-start-methods">上下文和启动方法</a></li>
|
||
<li><a class="reference internal" href="#exchanging-objects-between-processes">在进程之间交换对象</a></li>
|
||
<li><a class="reference internal" href="#synchronization-between-processes">进程间同步</a></li>
|
||
<li><a class="reference internal" href="#sharing-state-between-processes">进程间共享状态</a></li>
|
||
<li><a class="reference internal" href="#using-a-pool-of-workers">使用工作进程</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#reference">参考</a><ul>
|
||
<li><a class="reference internal" href="#process-and-exceptions"><code class="xref py py-class docutils literal notranslate"><span class="pre">Process</span></code> 和异常</a></li>
|
||
<li><a class="reference internal" href="#pipes-and-queues">管道和队列</a></li>
|
||
<li><a class="reference internal" href="#miscellaneous">杂项</a></li>
|
||
<li><a class="reference internal" href="#connection-objects">连接对象(Connection)</a></li>
|
||
<li><a class="reference internal" href="#synchronization-primitives">同步原语</a></li>
|
||
<li><a class="reference internal" href="#shared-ctypes-objects">共享 <code class="xref py py-mod docutils literal notranslate"><span class="pre">ctypes</span></code> 对象</a><ul>
|
||
<li><a class="reference internal" href="#module-multiprocessing.sharedctypes"><code class="xref py py-mod docutils literal notranslate"><span class="pre">multiprocessing.sharedctypes</span></code> 模块</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#managers">管理器</a><ul>
|
||
<li><a class="reference internal" href="#customized-managers">自定义管理器</a></li>
|
||
<li><a class="reference internal" href="#using-a-remote-manager">使用远程管理器</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#proxy-objects">代理对象</a><ul>
|
||
<li><a class="reference internal" href="#cleanup">清理</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#module-multiprocessing.pool">进程池</a></li>
|
||
<li><a class="reference internal" href="#module-multiprocessing.connection">监听器及客户端</a><ul>
|
||
<li><a class="reference internal" href="#address-formats">地址格式</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#authentication-keys">认证密码</a></li>
|
||
<li><a class="reference internal" href="#logging">日志记录</a></li>
|
||
<li><a class="reference internal" href="#module-multiprocessing.dummy"><code class="xref py py-mod docutils literal notranslate"><span class="pre">multiprocessing.dummy</span></code> 模块</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#programming-guidelines">编程指导</a><ul>
|
||
<li><a class="reference internal" href="#all-start-methods">所有start方法</a></li>
|
||
<li><a class="reference internal" href="#the-spawn-and-forkserver-start-methods"><em>spawn</em> 和 <em>forkserver</em> 启动方式</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#examples">例子</a></li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
|
||
<h4>上一个主题</h4>
|
||
<p class="topless"><a href="threading.html"
|
||
title="上一章"><code class="xref py py-mod docutils literal notranslate"><span class="pre">threading</span></code> --- 基于线程的并行</a></p>
|
||
<h4>下一个主题</h4>
|
||
<p class="topless"><a href="multiprocessing.shared_memory.html"
|
||
title="下一章"><code class="xref py py-mod docutils literal notranslate"><span class="pre">multiprocessing.shared_memory</span></code> --- 可从进程直接访问的共享内存</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/library/multiprocessing.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/library/multiprocessing.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="multiprocessing.shared_memory.html" title="multiprocessing.shared_memory --- 可从进程直接访问的共享内存"
|
||
accesskey="N">下一页</a> |</li>
|
||
<li class="right" >
|
||
<a href="threading.html" title="threading --- 基于线程的并行"
|
||
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" >Python 标准库</a> »</li>
|
||
<li class="nav-item nav-item-2"><a href="concurrency.html" accesskey="U">并发执行</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="module-multiprocessing">
|
||
<span id="multiprocessing-process-based-parallelism"></span><h1><a class="reference internal" href="#module-multiprocessing" title="multiprocessing: Process-based parallelism."><code class="xref py py-mod docutils literal notranslate"><span class="pre">multiprocessing</span></code></a> --- 基于进程的并行<a class="headerlink" href="#module-multiprocessing" title="永久链接至标题">¶</a></h1>
|
||
<p><strong>源代码</strong> <a class="reference external" href="https://github.com/python/cpython/tree/3.8/Lib/multiprocessing/">Lib/multiprocessing/</a></p>
|
||
<hr class="docutils" />
|
||
<section id="introduction">
|
||
<h2>概述<a class="headerlink" href="#introduction" title="永久链接至标题">¶</a></h2>
|
||
<p><a class="reference internal" href="#module-multiprocessing" title="multiprocessing: Process-based parallelism."><code class="xref py py-mod docutils literal notranslate"><span class="pre">multiprocessing</span></code></a> 是一个支持使用与 <a class="reference internal" href="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> 模块类似的 API 来产生进程的包。 <a class="reference internal" href="#module-multiprocessing" title="multiprocessing: Process-based parallelism."><code class="xref py py-mod docutils literal notranslate"><span class="pre">multiprocessing</span></code></a> 包同时提供了本地和远程并发操作,通过使用子进程而非线程有效地绕过了 <a class="reference internal" href="../glossary.html#term-global-interpreter-lock"><span class="xref std std-term">全局解释器锁</span></a>。 因此,<a class="reference internal" href="#module-multiprocessing" title="multiprocessing: Process-based parallelism."><code class="xref py py-mod docutils literal notranslate"><span class="pre">multiprocessing</span></code></a> 模块允许程序员充分利用给定机器上的多个处理器。 它在 Unix 和 Windows 上均可运行。</p>
|
||
<p><a class="reference internal" href="#module-multiprocessing" title="multiprocessing: Process-based parallelism."><code class="xref py py-mod docutils literal notranslate"><span class="pre">multiprocessing</span></code></a> 模块还引入了在 <a class="reference internal" href="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> 模块中没有的API。一个主要的例子就是 <a class="reference internal" href="#multiprocessing.pool.Pool" title="multiprocessing.pool.Pool"><code class="xref py py-class docutils literal notranslate"><span class="pre">Pool</span></code></a> 对象,它提供了一种快捷的方法,赋予函数并行化处理一系列输入值的能力,可以将输入数据分配给不同进程处理(数据并行)。下面的例子演示了在模块中定义此类函数的常见做法,以便子进程可以成功导入该模块。这个数据并行的基本例子使用了 <a class="reference internal" href="#multiprocessing.pool.Pool" title="multiprocessing.pool.Pool"><code class="xref py py-class docutils literal notranslate"><span class="pre">Pool</span></code></a> ,</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">multiprocessing</span> <span class="kn">import</span> <span class="n">Pool</span>
|
||
|
||
<span class="k">def</span> <span class="nf">f</span><span class="p">(</span><span class="n">x</span><span class="p">):</span>
|
||
<span class="k">return</span> <span class="n">x</span><span class="o">*</span><span class="n">x</span>
|
||
|
||
<span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s1">'__main__'</span><span class="p">:</span>
|
||
<span class="k">with</span> <span class="n">Pool</span><span class="p">(</span><span class="mi">5</span><span class="p">)</span> <span class="k">as</span> <span class="n">p</span><span class="p">:</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="n">p</span><span class="o">.</span><span class="n">map</span><span class="p">(</span><span class="n">f</span><span class="p">,</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">]))</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>将在标准输出中打印</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">9</span><span class="p">]</span>
|
||
</pre></div>
|
||
</div>
|
||
<section id="the-process-class">
|
||
<h3><code class="xref py py-class docutils literal notranslate"><span class="pre">Process</span></code> 类<a class="headerlink" href="#the-process-class" title="永久链接至标题">¶</a></h3>
|
||
<p>在 <a class="reference internal" href="#module-multiprocessing" title="multiprocessing: Process-based parallelism."><code class="xref py py-mod docutils literal notranslate"><span class="pre">multiprocessing</span></code></a> 中,通过创建一个 <a class="reference internal" href="#multiprocessing.Process" title="multiprocessing.Process"><code class="xref py py-class docutils literal notranslate"><span class="pre">Process</span></code></a> 对象然后调用它的 <code class="xref py py-meth docutils literal notranslate"><span class="pre">start()</span></code> 方法来生成进程。 <a class="reference internal" href="#multiprocessing.Process" title="multiprocessing.Process"><code class="xref py py-class docutils literal notranslate"><span class="pre">Process</span></code></a> 和 <a class="reference internal" href="threading.html#threading.Thread" title="threading.Thread"><code class="xref py py-class docutils literal notranslate"><span class="pre">threading.Thread</span></code></a> API 相同。 一个简单的多进程程序示例是:</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">multiprocessing</span> <span class="kn">import</span> <span class="n">Process</span>
|
||
|
||
<span class="k">def</span> <span class="nf">f</span><span class="p">(</span><span class="n">name</span><span class="p">):</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="s1">'hello'</span><span class="p">,</span> <span class="n">name</span><span class="p">)</span>
|
||
|
||
<span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s1">'__main__'</span><span class="p">:</span>
|
||
<span class="n">p</span> <span class="o">=</span> <span class="n">Process</span><span class="p">(</span><span class="n">target</span><span class="o">=</span><span class="n">f</span><span class="p">,</span> <span class="n">args</span><span class="o">=</span><span class="p">(</span><span class="s1">'bob'</span><span class="p">,))</span>
|
||
<span class="n">p</span><span class="o">.</span><span class="n">start</span><span class="p">()</span>
|
||
<span class="n">p</span><span class="o">.</span><span class="n">join</span><span class="p">()</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>要显示所涉及的各个进程ID,这是一个扩展示例:</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">multiprocessing</span> <span class="kn">import</span> <span class="n">Process</span>
|
||
<span class="kn">import</span> <span class="nn">os</span>
|
||
|
||
<span class="k">def</span> <span class="nf">info</span><span class="p">(</span><span class="n">title</span><span class="p">):</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="n">title</span><span class="p">)</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="s1">'module name:'</span><span class="p">,</span> <span class="vm">__name__</span><span class="p">)</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="s1">'parent process:'</span><span class="p">,</span> <span class="n">os</span><span class="o">.</span><span class="n">getppid</span><span class="p">())</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="s1">'process id:'</span><span class="p">,</span> <span class="n">os</span><span class="o">.</span><span class="n">getpid</span><span class="p">())</span>
|
||
|
||
<span class="k">def</span> <span class="nf">f</span><span class="p">(</span><span class="n">name</span><span class="p">):</span>
|
||
<span class="n">info</span><span class="p">(</span><span class="s1">'function f'</span><span class="p">)</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="s1">'hello'</span><span class="p">,</span> <span class="n">name</span><span class="p">)</span>
|
||
|
||
<span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s1">'__main__'</span><span class="p">:</span>
|
||
<span class="n">info</span><span class="p">(</span><span class="s1">'main line'</span><span class="p">)</span>
|
||
<span class="n">p</span> <span class="o">=</span> <span class="n">Process</span><span class="p">(</span><span class="n">target</span><span class="o">=</span><span class="n">f</span><span class="p">,</span> <span class="n">args</span><span class="o">=</span><span class="p">(</span><span class="s1">'bob'</span><span class="p">,))</span>
|
||
<span class="n">p</span><span class="o">.</span><span class="n">start</span><span class="p">()</span>
|
||
<span class="n">p</span><span class="o">.</span><span class="n">join</span><span class="p">()</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>关于为什么 <code class="docutils literal notranslate"><span class="pre">if</span> <span class="pre">__name__</span> <span class="pre">==</span> <span class="pre">'__main__'</span></code> 部分是必需的解释,请参见 <a class="reference internal" href="#multiprocessing-programming"><span class="std std-ref">编程指导</span></a>。</p>
|
||
</section>
|
||
<section id="contexts-and-start-methods">
|
||
<h3>上下文和启动方法<a class="headerlink" href="#contexts-and-start-methods" title="永久链接至标题">¶</a></h3>
|
||
<p id="multiprocessing-start-methods">根据不同的平台, <a class="reference internal" href="#module-multiprocessing" title="multiprocessing: Process-based parallelism."><code class="xref py py-mod docutils literal notranslate"><span class="pre">multiprocessing</span></code></a> 支持三种启动进程的方法。这些 <em>启动方法</em> 有</p>
|
||
<blockquote>
|
||
<div><dl>
|
||
<dt><em>spawn</em></dt><dd><p>父进程会启动一个全新的 python 解释器进程。 子进程将只继承那些运行进程对象的 <a class="reference internal" href="#multiprocessing.Process.run" title="multiprocessing.Process.run"><code class="xref py py-meth docutils literal notranslate"><span class="pre">run()</span></code></a> 方法所必需的资源。 特别地,来自父进程的非必需文件描述符和句柄将不会被继承。 使用此方法启动进程相比使用 <em>fork</em> 或 <em>forkserver</em> 要慢上许多。</p>
|
||
<p>可在 Unix 和 Windows 上使用。 Windows 和 macOS 上的默认设置。</p>
|
||
</dd>
|
||
<dt><em>fork</em></dt><dd><p>父进程使用 <a class="reference internal" href="os.html#os.fork" title="os.fork"><code class="xref py py-func docutils literal notranslate"><span class="pre">os.fork()</span></code></a> 来产生 Python 解释器分叉。子进程在开始时实际上与父进程相同。父进程的所有资源都由子进程继承。请注意,安全分叉多线程进程是棘手的。</p>
|
||
<p>只存在于 Unix。 Unix 中的默认值。</p>
|
||
</dd>
|
||
<dt><em>forkserver</em></dt><dd><p>程序启动并选择 <em>forkserver</em> 启动方法时,将启动服务器进程。 从那时起,每当需要一个新进程时,父进程就会连接到服务器并请求它分叉一个新进程。 分叉服务器进程是单线程的,因此使用 <a class="reference internal" href="os.html#os.fork" title="os.fork"><code class="xref py py-func docutils literal notranslate"><span class="pre">os.fork()</span></code></a> 是安全的。 没有不必要的资源被继承。</p>
|
||
<p>可在Unix平台上使用,支持通过Unix管道传递文件描述符。</p>
|
||
</dd>
|
||
</dl>
|
||
</div></blockquote>
|
||
<div class="versionchanged">
|
||
<p><span class="versionmodified changed">在 3.8 版更改: </span>对于 macOS,<em>spawn</em> 启动方式是默认方式。 因为 <em>fork</em> 可能导致subprocess崩溃,被认为是不安全的,查看 <a class="reference external" href="https://bugs.python.org/issue?@action=redirect&bpo=33725">bpo-33725</a> 。</p>
|
||
</div>
|
||
<div class="versionchanged">
|
||
<p><span class="versionmodified changed">在 3.4 版更改: </span>在所有unix平台上添加支持了 <em>spawn</em> ,并且为一些unix平台添加了 <em>forkserver</em> 。在Windows上子进程不再继承所有可继承的父进程句柄。</p>
|
||
</div>
|
||
<p>在 Unix 上通过 <em>spawn</em> 和 <em>forkserver</em> 方式启动多进程会同时启动一个 <em>资源追踪</em> 进程,负责追踪当前程序的进程产生的、并且不再被使用的命名系统资源(如命名信号量以及 <a class="reference internal" href="multiprocessing.shared_memory.html#multiprocessing.shared_memory.SharedMemory" title="multiprocessing.shared_memory.SharedMemory"><code class="xref py py-class docutils literal notranslate"><span class="pre">SharedMemory</span></code></a> 对象)。当所有进程退出后,资源追踪会负责释放这些仍被追踪的的对象。通常情况下是不会有这种对象的,但是假如一个子进程被某个信号杀死,就可能存在这一类资源的“泄露”情况。(泄露的信号量以及共享内存不会被释放,直到下一次系统重启,对于这两类资源来说,这是一个比较大的问题,因为操作系统允许的命名信号量的数量是有限的,而共享内存也会占据主内存的一片空间)</p>
|
||
<p>要选择一个启动方法,你应该在主模块的 <code class="docutils literal notranslate"><span class="pre">if</span> <span class="pre">__name__</span> <span class="pre">==</span> <span class="pre">'__main__'</span></code> 子句中调用 <a class="reference internal" href="#multiprocessing.set_start_method" title="multiprocessing.set_start_method"><code class="xref py py-func docutils literal notranslate"><span class="pre">set_start_method()</span></code></a> 。例如:</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">multiprocessing</span> <span class="k">as</span> <span class="nn">mp</span>
|
||
|
||
<span class="k">def</span> <span class="nf">foo</span><span class="p">(</span><span class="n">q</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="s1">'hello'</span><span class="p">)</span>
|
||
|
||
<span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s1">'__main__'</span><span class="p">:</span>
|
||
<span class="n">mp</span><span class="o">.</span><span class="n">set_start_method</span><span class="p">(</span><span class="s1">'spawn'</span><span class="p">)</span>
|
||
<span class="n">q</span> <span class="o">=</span> <span class="n">mp</span><span class="o">.</span><span class="n">Queue</span><span class="p">()</span>
|
||
<span class="n">p</span> <span class="o">=</span> <span class="n">mp</span><span class="o">.</span><span class="n">Process</span><span class="p">(</span><span class="n">target</span><span class="o">=</span><span class="n">foo</span><span class="p">,</span> <span class="n">args</span><span class="o">=</span><span class="p">(</span><span class="n">q</span><span class="p">,))</span>
|
||
<span class="n">p</span><span class="o">.</span><span class="n">start</span><span class="p">()</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="n">q</span><span class="o">.</span><span class="n">get</span><span class="p">())</span>
|
||
<span class="n">p</span><span class="o">.</span><span class="n">join</span><span class="p">()</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>在程序中 <a class="reference internal" href="#multiprocessing.set_start_method" title="multiprocessing.set_start_method"><code class="xref py py-func docutils literal notranslate"><span class="pre">set_start_method()</span></code></a> 不应该被多次调用。</p>
|
||
<p>或者,你可以使用 <a class="reference internal" href="#multiprocessing.get_context" title="multiprocessing.get_context"><code class="xref py py-func docutils literal notranslate"><span class="pre">get_context()</span></code></a> 来获取上下文对象。上下文对象与 multiprocessing 模块具有相同的API,并允许在同一程序中使用多种启动方法。:</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">multiprocessing</span> <span class="k">as</span> <span class="nn">mp</span>
|
||
|
||
<span class="k">def</span> <span class="nf">foo</span><span class="p">(</span><span class="n">q</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="s1">'hello'</span><span class="p">)</span>
|
||
|
||
<span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s1">'__main__'</span><span class="p">:</span>
|
||
<span class="n">ctx</span> <span class="o">=</span> <span class="n">mp</span><span class="o">.</span><span class="n">get_context</span><span class="p">(</span><span class="s1">'spawn'</span><span class="p">)</span>
|
||
<span class="n">q</span> <span class="o">=</span> <span class="n">ctx</span><span class="o">.</span><span class="n">Queue</span><span class="p">()</span>
|
||
<span class="n">p</span> <span class="o">=</span> <span class="n">ctx</span><span class="o">.</span><span class="n">Process</span><span class="p">(</span><span class="n">target</span><span class="o">=</span><span class="n">foo</span><span class="p">,</span> <span class="n">args</span><span class="o">=</span><span class="p">(</span><span class="n">q</span><span class="p">,))</span>
|
||
<span class="n">p</span><span class="o">.</span><span class="n">start</span><span class="p">()</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="n">q</span><span class="o">.</span><span class="n">get</span><span class="p">())</span>
|
||
<span class="n">p</span><span class="o">.</span><span class="n">join</span><span class="p">()</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>请注意,对象在不同上下文创建的进程间可能并不兼容。 特别是,使用 <em>fork</em> 上下文创建的锁不能传递给使用 <em>spawn</em> 或 <em>forkserver</em> 启动方法启动的进程。</p>
|
||
<p>想要使用特定启动方法的库应该使用 <a class="reference internal" href="#multiprocessing.get_context" title="multiprocessing.get_context"><code class="xref py py-func docutils literal notranslate"><span class="pre">get_context()</span></code></a> 以避免干扰库用户的选择。</p>
|
||
<div class="admonition warning">
|
||
<p class="admonition-title">警告</p>
|
||
<p><code class="docutils literal notranslate"><span class="pre">'spawn'</span></code> 和 <code class="docutils literal notranslate"><span class="pre">'forkserver'</span></code> 启动方法当前不能在Unix上和“冻结的”可执行内容一同使用(例如,有类似 <strong>PyInstaller</strong> 和 <strong>cx_Freeze</strong> 的包产生的二进制文件)。 <code class="docutils literal notranslate"><span class="pre">'fork'</span></code> 启动方法可以使用。</p>
|
||
</div>
|
||
</section>
|
||
<section id="exchanging-objects-between-processes">
|
||
<h3>在进程之间交换对象<a class="headerlink" href="#exchanging-objects-between-processes" title="永久链接至标题">¶</a></h3>
|
||
<p><a class="reference internal" href="#module-multiprocessing" title="multiprocessing: Process-based parallelism."><code class="xref py py-mod docutils literal notranslate"><span class="pre">multiprocessing</span></code></a> 支持进程之间的两种通信通道:</p>
|
||
<p><strong>队列</strong></p>
|
||
<blockquote>
|
||
<div><p><a class="reference internal" href="#multiprocessing.Queue" title="multiprocessing.Queue"><code class="xref py py-class docutils literal notranslate"><span class="pre">Queue</span></code></a> 类是一个近似 <a class="reference internal" href="queue.html#queue.Queue" title="queue.Queue"><code class="xref py py-class docutils literal notranslate"><span class="pre">queue.Queue</span></code></a> 的克隆。 例如:</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">multiprocessing</span> <span class="kn">import</span> <span class="n">Process</span><span class="p">,</span> <span class="n">Queue</span>
|
||
|
||
<span class="k">def</span> <span class="nf">f</span><span class="p">(</span><span class="n">q</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="mi">42</span><span class="p">,</span> <span class="kc">None</span><span class="p">,</span> <span class="s1">'hello'</span><span class="p">])</span>
|
||
|
||
<span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s1">'__main__'</span><span class="p">:</span>
|
||
<span class="n">q</span> <span class="o">=</span> <span class="n">Queue</span><span class="p">()</span>
|
||
<span class="n">p</span> <span class="o">=</span> <span class="n">Process</span><span class="p">(</span><span class="n">target</span><span class="o">=</span><span class="n">f</span><span class="p">,</span> <span class="n">args</span><span class="o">=</span><span class="p">(</span><span class="n">q</span><span class="p">,))</span>
|
||
<span class="n">p</span><span class="o">.</span><span class="n">start</span><span class="p">()</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="n">q</span><span class="o">.</span><span class="n">get</span><span class="p">())</span> <span class="c1"># prints "[42, None, 'hello']"</span>
|
||
<span class="n">p</span><span class="o">.</span><span class="n">join</span><span class="p">()</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>队列是线程和进程安全的。</p>
|
||
</div></blockquote>
|
||
<p><strong>管道</strong></p>
|
||
<blockquote>
|
||
<div><p><a class="reference internal" href="#multiprocessing.Pipe" title="multiprocessing.Pipe"><code class="xref py py-func docutils literal notranslate"><span class="pre">Pipe()</span></code></a> 函数返回一个由管道连接的连接对象,默认情况下是双工(双向)。例如:</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">multiprocessing</span> <span class="kn">import</span> <span class="n">Process</span><span class="p">,</span> <span class="n">Pipe</span>
|
||
|
||
<span class="k">def</span> <span class="nf">f</span><span class="p">(</span><span class="n">conn</span><span class="p">):</span>
|
||
<span class="n">conn</span><span class="o">.</span><span class="n">send</span><span class="p">([</span><span class="mi">42</span><span class="p">,</span> <span class="kc">None</span><span class="p">,</span> <span class="s1">'hello'</span><span class="p">])</span>
|
||
<span class="n">conn</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
|
||
|
||
<span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s1">'__main__'</span><span class="p">:</span>
|
||
<span class="n">parent_conn</span><span class="p">,</span> <span class="n">child_conn</span> <span class="o">=</span> <span class="n">Pipe</span><span class="p">()</span>
|
||
<span class="n">p</span> <span class="o">=</span> <span class="n">Process</span><span class="p">(</span><span class="n">target</span><span class="o">=</span><span class="n">f</span><span class="p">,</span> <span class="n">args</span><span class="o">=</span><span class="p">(</span><span class="n">child_conn</span><span class="p">,))</span>
|
||
<span class="n">p</span><span class="o">.</span><span class="n">start</span><span class="p">()</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="n">parent_conn</span><span class="o">.</span><span class="n">recv</span><span class="p">())</span> <span class="c1"># prints "[42, None, 'hello']"</span>
|
||
<span class="n">p</span><span class="o">.</span><span class="n">join</span><span class="p">()</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>返回的两个连接对象 <a class="reference internal" href="#multiprocessing.Pipe" title="multiprocessing.Pipe"><code class="xref py py-func docutils literal notranslate"><span class="pre">Pipe()</span></code></a> 表示管道的两端。每个连接对象都有 <code class="xref py py-meth docutils literal notranslate"><span class="pre">send()</span></code> 和 <code class="xref py py-meth docutils literal notranslate"><span class="pre">recv()</span></code> 方法(相互之间的)。请注意,如果两个进程(或线程)同时尝试读取或写入管道的 <em>同一</em> 端,则管道中的数据可能会损坏。当然,在不同进程中同时使用管道的不同端的情况下不存在损坏的风险。</p>
|
||
</div></blockquote>
|
||
</section>
|
||
<section id="synchronization-between-processes">
|
||
<h3>进程间同步<a class="headerlink" href="#synchronization-between-processes" title="永久链接至标题">¶</a></h3>
|
||
<p><a class="reference internal" href="#module-multiprocessing" title="multiprocessing: Process-based parallelism."><code class="xref py py-mod docutils literal notranslate"><span class="pre">multiprocessing</span></code></a> 包含来自 <a class="reference internal" href="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> 的所有同步原语的等价物。例如,可以使用锁来确保一次只有一个进程打印到标准输出:</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">multiprocessing</span> <span class="kn">import</span> <span class="n">Process</span><span class="p">,</span> <span class="n">Lock</span>
|
||
|
||
<span class="k">def</span> <span class="nf">f</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="n">l</span><span class="o">.</span><span class="n">acquire</span><span class="p">()</span>
|
||
<span class="k">try</span><span class="p">:</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="s1">'hello world'</span><span class="p">,</span> <span class="n">i</span><span class="p">)</span>
|
||
<span class="k">finally</span><span class="p">:</span>
|
||
<span class="n">l</span><span class="o">.</span><span class="n">release</span><span class="p">()</span>
|
||
|
||
<span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s1">'__main__'</span><span class="p">:</span>
|
||
<span class="n">lock</span> <span class="o">=</span> <span class="n">Lock</span><span class="p">()</span>
|
||
|
||
<span class="k">for</span> <span class="n">num</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">Process</span><span class="p">(</span><span class="n">target</span><span class="o">=</span><span class="n">f</span><span class="p">,</span> <span class="n">args</span><span class="o">=</span><span class="p">(</span><span class="n">lock</span><span class="p">,</span> <span class="n">num</span><span class="p">))</span><span class="o">.</span><span class="n">start</span><span class="p">()</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>不使用锁的情况下,来自于多进程的输出很容易产生混淆。</p>
|
||
</section>
|
||
<section id="sharing-state-between-processes">
|
||
<h3>进程间共享状态<a class="headerlink" href="#sharing-state-between-processes" title="永久链接至标题">¶</a></h3>
|
||
<p>如上所述,在进行并发编程时,通常最好尽量避免使用共享状态。使用多个进程时尤其如此。</p>
|
||
<p>但是,如果你真的需要使用一些共享数据,那么 <a class="reference internal" href="#module-multiprocessing" title="multiprocessing: Process-based parallelism."><code class="xref py py-mod docutils literal notranslate"><span class="pre">multiprocessing</span></code></a> 提供了两种方法。</p>
|
||
<p><strong>共享内存</strong></p>
|
||
<blockquote>
|
||
<div><p>可以使用 <a class="reference internal" href="#multiprocessing.Value" title="multiprocessing.Value"><code class="xref py py-class docutils literal notranslate"><span class="pre">Value</span></code></a> 或 <a class="reference internal" href="#multiprocessing.Array" title="multiprocessing.Array"><code class="xref py py-class docutils literal notranslate"><span class="pre">Array</span></code></a> 将数据存储在共享内存映射中。例如,以下代码:</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">multiprocessing</span> <span class="kn">import</span> <span class="n">Process</span><span class="p">,</span> <span class="n">Value</span><span class="p">,</span> <span class="n">Array</span>
|
||
|
||
<span class="k">def</span> <span class="nf">f</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="n">a</span><span class="p">):</span>
|
||
<span class="n">n</span><span class="o">.</span><span class="n">value</span> <span class="o">=</span> <span class="mf">3.1415927</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="nb">len</span><span class="p">(</span><span class="n">a</span><span class="p">)):</span>
|
||
<span class="n">a</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="o">-</span><span class="n">a</span><span class="p">[</span><span class="n">i</span><span class="p">]</span>
|
||
|
||
<span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s1">'__main__'</span><span class="p">:</span>
|
||
<span class="n">num</span> <span class="o">=</span> <span class="n">Value</span><span class="p">(</span><span class="s1">'d'</span><span class="p">,</span> <span class="mf">0.0</span><span class="p">)</span>
|
||
<span class="n">arr</span> <span class="o">=</span> <span class="n">Array</span><span class="p">(</span><span class="s1">'i'</span><span class="p">,</span> <span class="nb">range</span><span class="p">(</span><span class="mi">10</span><span class="p">))</span>
|
||
|
||
<span class="n">p</span> <span class="o">=</span> <span class="n">Process</span><span class="p">(</span><span class="n">target</span><span class="o">=</span><span class="n">f</span><span class="p">,</span> <span class="n">args</span><span class="o">=</span><span class="p">(</span><span class="n">num</span><span class="p">,</span> <span class="n">arr</span><span class="p">))</span>
|
||
<span class="n">p</span><span class="o">.</span><span class="n">start</span><span class="p">()</span>
|
||
<span class="n">p</span><span class="o">.</span><span class="n">join</span><span class="p">()</span>
|
||
|
||
<span class="nb">print</span><span class="p">(</span><span class="n">num</span><span class="o">.</span><span class="n">value</span><span class="p">)</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="n">arr</span><span class="p">[:])</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>将打印</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="mf">3.1415927</span>
|
||
<span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="o">-</span><span class="mi">2</span><span class="p">,</span> <span class="o">-</span><span class="mi">3</span><span class="p">,</span> <span class="o">-</span><span class="mi">4</span><span class="p">,</span> <span class="o">-</span><span class="mi">5</span><span class="p">,</span> <span class="o">-</span><span class="mi">6</span><span class="p">,</span> <span class="o">-</span><span class="mi">7</span><span class="p">,</span> <span class="o">-</span><span class="mi">8</span><span class="p">,</span> <span class="o">-</span><span class="mi">9</span><span class="p">]</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>创建 <code class="docutils literal notranslate"><span class="pre">num</span></code> 和 <code class="docutils literal notranslate"><span class="pre">arr</span></code> 时使用的 <code class="docutils literal notranslate"><span class="pre">'d'</span></code> 和 <code class="docutils literal notranslate"><span class="pre">'i'</span></code> 参数是 <a class="reference internal" href="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> 模块使用的类型的 typecode : <code class="docutils literal notranslate"><span class="pre">'d'</span></code> 表示双精度浮点数, <code class="docutils literal notranslate"><span class="pre">'i'</span></code> 表示有符号整数。这些共享对象将是进程和线程安全的。</p>
|
||
<p>为了更灵活地使用共享内存,可以使用 <a class="reference internal" href="#module-multiprocessing.sharedctypes" title="multiprocessing.sharedctypes: Allocate ctypes objects from shared memory."><code class="xref py py-mod docutils literal notranslate"><span class="pre">multiprocessing.sharedctypes</span></code></a> 模块,该模块支持创建从共享内存分配的任意ctypes对象。</p>
|
||
</div></blockquote>
|
||
<p><strong>服务进程</strong></p>
|
||
<blockquote>
|
||
<div><p>由 <code class="xref py py-func docutils literal notranslate"><span class="pre">Manager()</span></code> 返回的管理器对象控制一个服务进程,该进程保存Python对象并允许其他进程使用代理操作它们。</p>
|
||
<p><code class="xref py py-func docutils literal notranslate"><span class="pre">Manager()</span></code> 返回的管理器支持类型: <a class="reference internal" href="stdtypes.html#list" title="list"><code class="xref py py-class docutils literal notranslate"><span class="pre">list</span></code></a> 、 <a class="reference internal" href="stdtypes.html#dict" title="dict"><code class="xref py py-class docutils literal notranslate"><span class="pre">dict</span></code></a> 、 <a class="reference internal" href="#multiprocessing.managers.Namespace" title="multiprocessing.managers.Namespace"><code class="xref py py-class docutils literal notranslate"><span class="pre">Namespace</span></code></a> 、 <a class="reference internal" href="#multiprocessing.Lock" title="multiprocessing.Lock"><code class="xref py py-class docutils literal notranslate"><span class="pre">Lock</span></code></a> 、 <a class="reference internal" href="#multiprocessing.RLock" title="multiprocessing.RLock"><code class="xref py py-class docutils literal notranslate"><span class="pre">RLock</span></code></a> 、 <a class="reference internal" href="#multiprocessing.Semaphore" title="multiprocessing.Semaphore"><code class="xref py py-class docutils literal notranslate"><span class="pre">Semaphore</span></code></a> 、 <a class="reference internal" href="#multiprocessing.BoundedSemaphore" title="multiprocessing.BoundedSemaphore"><code class="xref py py-class docutils literal notranslate"><span class="pre">BoundedSemaphore</span></code></a> 、 <a class="reference internal" href="#multiprocessing.Condition" title="multiprocessing.Condition"><code class="xref py py-class docutils literal notranslate"><span class="pre">Condition</span></code></a> 、 <a class="reference internal" href="#multiprocessing.Event" title="multiprocessing.Event"><code class="xref py py-class docutils literal notranslate"><span class="pre">Event</span></code></a> 、 <a class="reference internal" href="#multiprocessing.Barrier" title="multiprocessing.Barrier"><code class="xref py py-class docutils literal notranslate"><span class="pre">Barrier</span></code></a> 、 <a class="reference internal" href="#multiprocessing.Queue" title="multiprocessing.Queue"><code class="xref py py-class docutils literal notranslate"><span class="pre">Queue</span></code></a> 、 <a class="reference internal" href="#multiprocessing.Value" title="multiprocessing.Value"><code class="xref py py-class docutils literal notranslate"><span class="pre">Value</span></code></a> 和 <a class="reference internal" href="#multiprocessing.Array" title="multiprocessing.Array"><code class="xref py py-class docutils literal notranslate"><span class="pre">Array</span></code></a> 。例如</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">multiprocessing</span> <span class="kn">import</span> <span class="n">Process</span><span class="p">,</span> <span class="n">Manager</span>
|
||
|
||
<span class="k">def</span> <span class="nf">f</span><span class="p">(</span><span class="n">d</span><span class="p">,</span> <span class="n">l</span><span class="p">):</span>
|
||
<span class="n">d</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="s1">'1'</span>
|
||
<span class="n">d</span><span class="p">[</span><span class="s1">'2'</span><span class="p">]</span> <span class="o">=</span> <span class="mi">2</span>
|
||
<span class="n">d</span><span class="p">[</span><span class="mf">0.25</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
|
||
<span class="n">l</span><span class="o">.</span><span class="n">reverse</span><span class="p">()</span>
|
||
|
||
<span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s1">'__main__'</span><span class="p">:</span>
|
||
<span class="k">with</span> <span class="n">Manager</span><span class="p">()</span> <span class="k">as</span> <span class="n">manager</span><span class="p">:</span>
|
||
<span class="n">d</span> <span class="o">=</span> <span class="n">manager</span><span class="o">.</span><span class="n">dict</span><span class="p">()</span>
|
||
<span class="n">l</span> <span class="o">=</span> <span class="n">manager</span><span class="o">.</span><span class="n">list</span><span class="p">(</span><span class="nb">range</span><span class="p">(</span><span class="mi">10</span><span class="p">))</span>
|
||
|
||
<span class="n">p</span> <span class="o">=</span> <span class="n">Process</span><span class="p">(</span><span class="n">target</span><span class="o">=</span><span class="n">f</span><span class="p">,</span> <span class="n">args</span><span class="o">=</span><span class="p">(</span><span class="n">d</span><span class="p">,</span> <span class="n">l</span><span class="p">))</span>
|
||
<span class="n">p</span><span class="o">.</span><span class="n">start</span><span class="p">()</span>
|
||
<span class="n">p</span><span class="o">.</span><span class="n">join</span><span class="p">()</span>
|
||
|
||
<span class="nb">print</span><span class="p">(</span><span class="n">d</span><span class="p">)</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="n">l</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>将打印</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="p">{</span><span class="mf">0.25</span><span class="p">:</span> <span class="kc">None</span><span class="p">,</span> <span class="mi">1</span><span class="p">:</span> <span class="s1">'1'</span><span class="p">,</span> <span class="s1">'2'</span><span class="p">:</span> <span class="mi">2</span><span class="p">}</span>
|
||
<span class="p">[</span><span class="mi">9</span><span class="p">,</span> <span class="mi">8</span><span class="p">,</span> <span class="mi">7</span><span class="p">,</span> <span class="mi">6</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">]</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>使用服务进程的管理器比使用共享内存对象更灵活,因为它们可以支持任意对象类型。此外,单个管理器可以通过网络由不同计算机上的进程共享。但是,它们比使用共享内存慢。</p>
|
||
</div></blockquote>
|
||
</section>
|
||
<section id="using-a-pool-of-workers">
|
||
<h3>使用工作进程<a class="headerlink" href="#using-a-pool-of-workers" title="永久链接至标题">¶</a></h3>
|
||
<p><a class="reference internal" href="#multiprocessing.pool.Pool" title="multiprocessing.pool.Pool"><code class="xref py py-class docutils literal notranslate"><span class="pre">Pool</span></code></a> 类表示一个工作进程池。它具有允许以几种不同方式将任务分配到工作进程的方法。</p>
|
||
<p>例如:</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">multiprocessing</span> <span class="kn">import</span> <span class="n">Pool</span><span class="p">,</span> <span class="ne">TimeoutError</span>
|
||
<span class="kn">import</span> <span class="nn">time</span>
|
||
<span class="kn">import</span> <span class="nn">os</span>
|
||
|
||
<span class="k">def</span> <span class="nf">f</span><span class="p">(</span><span class="n">x</span><span class="p">):</span>
|
||
<span class="k">return</span> <span class="n">x</span><span class="o">*</span><span class="n">x</span>
|
||
|
||
<span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s1">'__main__'</span><span class="p">:</span>
|
||
<span class="c1"># start 4 worker processes</span>
|
||
<span class="k">with</span> <span class="n">Pool</span><span class="p">(</span><span class="n">processes</span><span class="o">=</span><span class="mi">4</span><span class="p">)</span> <span class="k">as</span> <span class="n">pool</span><span class="p">:</span>
|
||
|
||
<span class="c1"># print "[0, 1, 4,..., 81]"</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="n">pool</span><span class="o">.</span><span class="n">map</span><span class="p">(</span><span class="n">f</span><span class="p">,</span> <span class="nb">range</span><span class="p">(</span><span class="mi">10</span><span class="p">)))</span>
|
||
|
||
<span class="c1"># print same numbers in arbitrary order</span>
|
||
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">pool</span><span class="o">.</span><span class="n">imap_unordered</span><span class="p">(</span><span class="n">f</span><span class="p">,</span> <span class="nb">range</span><span class="p">(</span><span class="mi">10</span><span class="p">)):</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="n">i</span><span class="p">)</span>
|
||
|
||
<span class="c1"># evaluate "f(20)" asynchronously</span>
|
||
<span class="n">res</span> <span class="o">=</span> <span class="n">pool</span><span class="o">.</span><span class="n">apply_async</span><span class="p">(</span><span class="n">f</span><span class="p">,</span> <span class="p">(</span><span class="mi">20</span><span class="p">,))</span> <span class="c1"># runs in *only* one process</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="n">res</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">timeout</span><span class="o">=</span><span class="mi">1</span><span class="p">))</span> <span class="c1"># prints "400"</span>
|
||
|
||
<span class="c1"># evaluate "os.getpid()" asynchronously</span>
|
||
<span class="n">res</span> <span class="o">=</span> <span class="n">pool</span><span class="o">.</span><span class="n">apply_async</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">getpid</span><span class="p">,</span> <span class="p">())</span> <span class="c1"># runs in *only* one process</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="n">res</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">timeout</span><span class="o">=</span><span class="mi">1</span><span class="p">))</span> <span class="c1"># prints the PID of that process</span>
|
||
|
||
<span class="c1"># launching multiple evaluations asynchronously *may* use more processes</span>
|
||
<span class="n">multiple_results</span> <span class="o">=</span> <span class="p">[</span><span class="n">pool</span><span class="o">.</span><span class="n">apply_async</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">getpid</span><span class="p">,</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">4</span><span class="p">)]</span>
|
||
<span class="nb">print</span><span class="p">([</span><span class="n">res</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">timeout</span><span class="o">=</span><span class="mi">1</span><span class="p">)</span> <span class="k">for</span> <span class="n">res</span> <span class="ow">in</span> <span class="n">multiple_results</span><span class="p">])</span>
|
||
|
||
<span class="c1"># make a single worker sleep for 10 secs</span>
|
||
<span class="n">res</span> <span class="o">=</span> <span class="n">pool</span><span class="o">.</span><span class="n">apply_async</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="p">(</span><span class="mi">10</span><span class="p">,))</span>
|
||
<span class="k">try</span><span class="p">:</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="n">res</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">timeout</span><span class="o">=</span><span class="mi">1</span><span class="p">))</span>
|
||
<span class="k">except</span> <span class="ne">TimeoutError</span><span class="p">:</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="s2">"We lacked patience and got a multiprocessing.TimeoutError"</span><span class="p">)</span>
|
||
|
||
<span class="nb">print</span><span class="p">(</span><span class="s2">"For the moment, the pool remains available for more work"</span><span class="p">)</span>
|
||
|
||
<span class="c1"># exiting the 'with'-block has stopped the pool</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="s2">"Now the pool is closed and no longer available"</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>请注意,进程池的方法只能由创建它的进程使用。</p>
|
||
<div class="admonition note">
|
||
<p class="admonition-title">注解</p>
|
||
<p>这个包中的功能要求子进程可以导入 <code class="docutils literal notranslate"><span class="pre">__main__</span></code> 模块。虽然这在 <a class="reference internal" href="#multiprocessing-programming"><span class="std std-ref">编程指导</span></a> 中有描述,但还是需要提前说明一下。这意味着一些示例在交互式解释器中不起作用,比如 <a class="reference internal" href="#multiprocessing.pool.Pool" title="multiprocessing.pool.Pool"><code class="xref py py-class docutils literal notranslate"><span class="pre">multiprocessing.pool.Pool</span></code></a> 示例。例如:</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="kn">from</span> <span class="nn">multiprocessing</span> <span class="kn">import</span> <span class="n">Pool</span>
|
||
<span class="gp">>>> </span><span class="n">p</span> <span class="o">=</span> <span class="n">Pool</span><span class="p">(</span><span class="mi">5</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="k">def</span> <span class="nf">f</span><span class="p">(</span><span class="n">x</span><span class="p">):</span>
|
||
<span class="gp">... </span> <span class="k">return</span> <span class="n">x</span><span class="o">*</span><span class="n">x</span>
|
||
<span class="gp">...</span>
|
||
<span class="gp">>>> </span><span class="k">with</span> <span class="n">p</span><span class="p">:</span>
|
||
<span class="gp">... </span> <span class="n">p</span><span class="o">.</span><span class="n">map</span><span class="p">(</span><span class="n">f</span><span class="p">,</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">])</span>
|
||
<span class="go">Process PoolWorker-1:</span>
|
||
<span class="go">Process PoolWorker-2:</span>
|
||
<span class="go">Process PoolWorker-3:</span>
|
||
<span class="gt">Traceback (most recent call last):</span>
|
||
<span class="gt">Traceback (most recent call last):</span>
|
||
<span class="gt">Traceback (most recent call last):</span>
|
||
<span class="gr">AttributeError</span>: <span class="n">'module' object has no attribute 'f'</span>
|
||
<span class="x">AttributeError: 'module' object has no attribute 'f'</span>
|
||
<span class="x">AttributeError: 'module' object has no attribute 'f'</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>(如果尝试执行上面的代码,它会以一种半随机的方式将三个完整的堆栈内容交替输出,然后你只能以某种方式停止父进程。)</p>
|
||
</div>
|
||
</section>
|
||
</section>
|
||
<section id="reference">
|
||
<h2>参考<a class="headerlink" href="#reference" title="永久链接至标题">¶</a></h2>
|
||
<p><a class="reference internal" href="#module-multiprocessing" title="multiprocessing: Process-based parallelism."><code class="xref py py-mod docutils literal notranslate"><span class="pre">multiprocessing</span></code></a> 包主要复制了 <a class="reference internal" href="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> 模块的API。</p>
|
||
<section id="process-and-exceptions">
|
||
<h3><code class="xref py py-class docutils literal notranslate"><span class="pre">Process</span></code> 和异常<a class="headerlink" href="#process-and-exceptions" title="永久链接至标题">¶</a></h3>
|
||
<dl class="class">
|
||
<dt id="multiprocessing.Process">
|
||
<em class="property">class </em><code class="sig-prename descclassname">multiprocessing.</code><code class="sig-name descname">Process</code><span class="sig-paren">(</span><em class="sig-param">group=None</em>, <em class="sig-param">target=None</em>, <em class="sig-param">name=None</em>, <em class="sig-param">args=()</em>, <em class="sig-param">kwargs={}</em>, <em class="sig-param">*</em>, <em class="sig-param">daemon=None</em><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.Process" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>进程对象表示在单独进程中运行的活动。 <a class="reference internal" href="#multiprocessing.Process" title="multiprocessing.Process"><code class="xref py py-class docutils literal notranslate"><span class="pre">Process</span></code></a> 类拥有和 <a class="reference internal" href="threading.html#threading.Thread" title="threading.Thread"><code class="xref py py-class docutils literal notranslate"><span class="pre">threading.Thread</span></code></a> 等价的大部分方法。</p>
|
||
<p>应始终使用关键字参数调用构造函数。 <em>group</em> 应该始终是 <code class="docutils literal notranslate"><span class="pre">None</span></code> ;它仅用于兼容 <a class="reference internal" href="threading.html#threading.Thread" title="threading.Thread"><code class="xref py py-class docutils literal notranslate"><span class="pre">threading.Thread</span></code></a> 。 <em>target</em> 是由 <a class="reference internal" href="#multiprocessing.Process.run" title="multiprocessing.Process.run"><code class="xref py py-meth docutils literal notranslate"><span class="pre">run()</span></code></a> 方法调用的可调用对象。它默认为 <code class="docutils literal notranslate"><span class="pre">None</span></code> ,意味着什么都没有被调用。 <em>name</em> 是进程名称(有关详细信息,请参阅 <a class="reference internal" href="#multiprocessing.Process.name" title="multiprocessing.Process.name"><code class="xref py py-attr docutils literal notranslate"><span class="pre">name</span></code></a> )。 <em>args</em> 是目标调用的参数元组。 <em>kwargs</em> 是目标调用的关键字参数字典。如果提供,则键参数 <em>daemon</em> 将进程 <a class="reference internal" href="#multiprocessing.Process.daemon" title="multiprocessing.Process.daemon"><code class="xref py py-attr docutils literal notranslate"><span class="pre">daemon</span></code></a> 标志设置为 <code class="docutils literal notranslate"><span class="pre">True</span></code> 或 <code class="docutils literal notranslate"><span class="pre">False</span></code> 。如果是 <code class="docutils literal notranslate"><span class="pre">None</span></code> (默认值),则该标志将从创建的进程继承。</p>
|
||
<p>默认情况下,不会将任何参数传递给 <em>target</em> 。</p>
|
||
<p>如果子类重写构造函数,它必须确保它在对进程执行任何其他操作之前调用基类构造函数( <code class="xref py py-meth docutils literal notranslate"><span class="pre">Process.__init__()</span></code> )。</p>
|
||
<div class="versionchanged">
|
||
<p><span class="versionmodified changed">在 3.3 版更改: </span>加入 <em>daemon</em> 参数。</p>
|
||
</div>
|
||
<dl class="method">
|
||
<dt id="multiprocessing.Process.run">
|
||
<code class="sig-name descname">run</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.Process.run" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>表示进程活动的方法。</p>
|
||
<p>你可以在子类中重写此方法。标准 <a class="reference internal" href="#multiprocessing.Process.run" title="multiprocessing.Process.run"><code class="xref py py-meth docutils literal notranslate"><span class="pre">run()</span></code></a> 方法调用传递给对象构造函数的可调用对象作为目标参数(如果有),分别从 <em>args</em> 和 <em>kwargs</em> 参数中获取顺序和关键字参数。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="method">
|
||
<dt id="multiprocessing.Process.start">
|
||
<code class="sig-name descname">start</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.Process.start" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>启动进程活动。</p>
|
||
<p>这个方法每个进程对象最多只能调用一次。它会将对象的 <a class="reference internal" href="#multiprocessing.Process.run" title="multiprocessing.Process.run"><code class="xref py py-meth docutils literal notranslate"><span class="pre">run()</span></code></a> 方法安排在一个单独的进程中调用。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="method">
|
||
<dt id="multiprocessing.Process.join">
|
||
<code class="sig-name descname">join</code><span class="sig-paren">(</span><span class="optional">[</span><em class="sig-param">timeout</em><span class="optional">]</span><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.Process.join" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>如果可选参数 <em>timeout</em> 是 <code class="docutils literal notranslate"><span class="pre">None</span></code> (默认值),则该方法将阻塞,直到调用 <a class="reference internal" href="#multiprocessing.Process.join" title="multiprocessing.Process.join"><code class="xref py py-meth docutils literal notranslate"><span class="pre">join()</span></code></a> 方法的进程终止。如果 <em>timeout</em> 是一个正数,它最多会阻塞 <em>timeout</em> 秒。请注意,如果进程终止或方法超时,则该方法返回 <code class="docutils literal notranslate"><span class="pre">None</span></code> 。检查进程的 <a class="reference internal" href="#multiprocessing.Process.exitcode" title="multiprocessing.Process.exitcode"><code class="xref py py-attr docutils literal notranslate"><span class="pre">exitcode</span></code></a> 以确定它是否终止。</p>
|
||
<p>一个进程可以被 join 多次。</p>
|
||
<p>进程无法join自身,因为这会导致死锁。尝试在启动进程之前join进程是错误的。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="attribute">
|
||
<dt id="multiprocessing.Process.name">
|
||
<code class="sig-name descname">name</code><a class="headerlink" href="#multiprocessing.Process.name" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>进程的名称。该名称是一个字符串,仅用于识别目的。它没有语义。可以为多个进程指定相同的名称。</p>
|
||
<p>初始名称由构造器设定。 如果没有为构造器提供显式名称,则会构造一个形式为 'Process-N<sub>1</sub>:N<sub>2</sub>:...:N<sub>k</sub>' 的名称,其中每个 N<sub>k</sub> 是其父亲的第 N 个孩子。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="method">
|
||
<dt id="multiprocessing.Process.is_alive">
|
||
<code class="sig-name descname">is_alive</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.Process.is_alive" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>返回进程是否还活着。</p>
|
||
<p>粗略地说,从 <a class="reference internal" href="#multiprocessing.Process.start" title="multiprocessing.Process.start"><code class="xref py py-meth docutils literal notranslate"><span class="pre">start()</span></code></a> 方法返回到子进程终止之前,进程对象仍处于活动状态。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="attribute">
|
||
<dt id="multiprocessing.Process.daemon">
|
||
<code class="sig-name descname">daemon</code><a class="headerlink" href="#multiprocessing.Process.daemon" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>进程的守护标志,一个布尔值。这必须在 <a class="reference internal" href="#multiprocessing.Process.start" title="multiprocessing.Process.start"><code class="xref py py-meth docutils literal notranslate"><span class="pre">start()</span></code></a> 被调用之前设置。</p>
|
||
<p>初始值继承自创建进程。</p>
|
||
<p>当进程退出时,它会尝试终止其所有守护进程子进程。</p>
|
||
<p>请注意,不允许在守护进程中创建子进程。这是因为当守护进程由于父进程退出而中断时,其子进程会变成孤儿进程。 另外,这些 <strong>不是</strong> Unix 守护进程或服务,它们是正常进程,如果非守护进程已经退出,它们将被终止(并且不被合并)。</p>
|
||
</dd></dl>
|
||
|
||
<p>除了 <a class="reference internal" href="threading.html#threading.Thread" title="threading.Thread"><code class="xref py py-class docutils literal notranslate"><span class="pre">threading.Thread</span></code></a> API ,<a class="reference internal" href="#multiprocessing.Process" title="multiprocessing.Process"><code class="xref py py-class docutils literal notranslate"><span class="pre">Process</span></code></a> 对象还支持以下属性和方法:</p>
|
||
<dl class="attribute">
|
||
<dt id="multiprocessing.Process.pid">
|
||
<code class="sig-name descname">pid</code><a class="headerlink" href="#multiprocessing.Process.pid" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>返回进程ID。在生成该进程之前,这将是 <code class="docutils literal notranslate"><span class="pre">None</span></code> 。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="attribute">
|
||
<dt id="multiprocessing.Process.exitcode">
|
||
<code class="sig-name descname">exitcode</code><a class="headerlink" href="#multiprocessing.Process.exitcode" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>子进程的退出代码。如果进程尚未终止,这将是 <code class="docutils literal notranslate"><span class="pre">None</span></code> 。负值 <em>-N</em> 表示子进程被信号 <em>N</em> 终止。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="attribute">
|
||
<dt id="multiprocessing.Process.authkey">
|
||
<code class="sig-name descname">authkey</code><a class="headerlink" href="#multiprocessing.Process.authkey" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>进程的身份验证密钥(字节字符串)。</p>
|
||
<p>当 <a class="reference internal" href="#module-multiprocessing" title="multiprocessing: Process-based parallelism."><code class="xref py py-mod docutils literal notranslate"><span class="pre">multiprocessing</span></code></a> 初始化时,主进程使用 <a class="reference internal" href="os.html#os.urandom" title="os.urandom"><code class="xref py py-func docutils literal notranslate"><span class="pre">os.urandom()</span></code></a> 分配一个随机字符串。</p>
|
||
<p>当创建 <a class="reference internal" href="#multiprocessing.Process" title="multiprocessing.Process"><code class="xref py py-class docutils literal notranslate"><span class="pre">Process</span></code></a> 对象时,它将继承其父进程的身份验证密钥,尽管可以通过将 <a class="reference internal" href="#multiprocessing.Process.authkey" title="multiprocessing.Process.authkey"><code class="xref py py-attr docutils literal notranslate"><span class="pre">authkey</span></code></a> 设置为另一个字节字符串来更改。</p>
|
||
<p>参见 <a class="reference internal" href="#multiprocessing-auth-keys"><span class="std std-ref">认证密码</span></a> 。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="attribute">
|
||
<dt id="multiprocessing.Process.sentinel">
|
||
<code class="sig-name descname">sentinel</code><a class="headerlink" href="#multiprocessing.Process.sentinel" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>系统对象的数字句柄,当进程结束时将变为 "ready" 。</p>
|
||
<p>如果要使用 <a class="reference internal" href="#multiprocessing.connection.wait" title="multiprocessing.connection.wait"><code class="xref py py-func docutils literal notranslate"><span class="pre">multiprocessing.connection.wait()</span></code></a> 一次等待多个事件,可以使用此值。否则调用 <a class="reference internal" href="#multiprocessing.Process.join" title="multiprocessing.Process.join"><code class="xref py py-meth docutils literal notranslate"><span class="pre">join()</span></code></a> 更简单。</p>
|
||
<p>在Windows上,这是一个操作系统句柄,可以与 <code class="docutils literal notranslate"><span class="pre">WaitForSingleObject</span></code> 和 <code class="docutils literal notranslate"><span class="pre">WaitForMultipleObjects</span></code> 系列API调用一起使用。在Unix上,这是一个文件描述符,可以使用来自 <a class="reference internal" href="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> 模块的原语。</p>
|
||
<div class="versionadded">
|
||
<p><span class="versionmodified added">3.3 新版功能.</span></p>
|
||
</div>
|
||
</dd></dl>
|
||
|
||
<dl class="method">
|
||
<dt id="multiprocessing.Process.terminate">
|
||
<code class="sig-name descname">terminate</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.Process.terminate" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>终止进程。 在Unix上,这是使用 <code class="docutils literal notranslate"><span class="pre">SIGTERM</span></code> 信号完成的;在Windows上使用 <code class="xref c c-func docutils literal notranslate"><span class="pre">TerminateProcess()</span></code> 。 请注意,不会执行退出处理程序和finally子句等。</p>
|
||
<p>请注意,进程的后代进程将不会被终止 —— 它们将简单地变成孤立的。</p>
|
||
<div class="admonition warning">
|
||
<p class="admonition-title">警告</p>
|
||
<p>如果在关联进程使用管道或队列时使用此方法,则管道或队列可能会损坏,并可能无法被其他进程使用。类似地,如果进程已获得锁或信号量等,则终止它可能导致其他进程死锁。</p>
|
||
</div>
|
||
</dd></dl>
|
||
|
||
<dl class="method">
|
||
<dt id="multiprocessing.Process.kill">
|
||
<code class="sig-name descname">kill</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.Process.kill" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>与 <a class="reference internal" href="#multiprocessing.Process.terminate" title="multiprocessing.Process.terminate"><code class="xref py py-meth docutils literal notranslate"><span class="pre">terminate()</span></code></a> 相同,但在Unix上使用 <code class="docutils literal notranslate"><span class="pre">SIGKILL</span></code> 信号。</p>
|
||
<div class="versionadded">
|
||
<p><span class="versionmodified added">3.7 新版功能.</span></p>
|
||
</div>
|
||
</dd></dl>
|
||
|
||
<dl class="method">
|
||
<dt id="multiprocessing.Process.close">
|
||
<code class="sig-name descname">close</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.Process.close" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>关闭 <a class="reference internal" href="#multiprocessing.Process" title="multiprocessing.Process"><code class="xref py py-class docutils literal notranslate"><span class="pre">Process</span></code></a> 对象,释放与之关联的所有资源。如果底层进程仍在运行,则会引发 <a class="reference internal" href="exceptions.html#ValueError" title="ValueError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">ValueError</span></code></a> 。一旦 <a class="reference internal" href="#multiprocessing.Process.close" title="multiprocessing.Process.close"><code class="xref py py-meth docutils literal notranslate"><span class="pre">close()</span></code></a> 成功返回, <a class="reference internal" href="#multiprocessing.Process" title="multiprocessing.Process"><code class="xref py py-class docutils literal notranslate"><span class="pre">Process</span></code></a> 对象的大多数其他方法和属性将引发 <a class="reference internal" href="exceptions.html#ValueError" title="ValueError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">ValueError</span></code></a> 。</p>
|
||
<div class="versionadded">
|
||
<p><span class="versionmodified added">3.7 新版功能.</span></p>
|
||
</div>
|
||
</dd></dl>
|
||
|
||
<p>注意 <a class="reference internal" href="#multiprocessing.Process.start" title="multiprocessing.Process.start"><code class="xref py py-meth docutils literal notranslate"><span class="pre">start()</span></code></a> 、 <a class="reference internal" href="#multiprocessing.Process.join" title="multiprocessing.Process.join"><code class="xref py py-meth docutils literal notranslate"><span class="pre">join()</span></code></a> 、 <a class="reference internal" href="#multiprocessing.Process.is_alive" title="multiprocessing.Process.is_alive"><code class="xref py py-meth docutils literal notranslate"><span class="pre">is_alive()</span></code></a> 、 <a class="reference internal" href="#multiprocessing.Process.terminate" title="multiprocessing.Process.terminate"><code class="xref py py-meth docutils literal notranslate"><span class="pre">terminate()</span></code></a> 和 <a class="reference internal" href="#multiprocessing.Process.exitcode" title="multiprocessing.Process.exitcode"><code class="xref py py-attr docutils literal notranslate"><span class="pre">exitcode</span></code></a> 方法只能由创建进程对象的进程调用。</p>
|
||
<p><a class="reference internal" href="#multiprocessing.Process" title="multiprocessing.Process"><code class="xref py py-class docutils literal notranslate"><span class="pre">Process</span></code></a> 一些方法的示例用法:</p>
|
||
<div class="highlight-pycon3 notranslate"><div class="highlight"><pre><span></span><span class="go"> >>> import multiprocessing, time, signal</span>
|
||
<span class="go"> >>> p = multiprocessing.Process(target=time.sleep, args=(1000,))</span>
|
||
<span class="go"> >>> print(p, p.is_alive())</span>
|
||
<span class="go"> <Process ... initial> False</span>
|
||
<span class="go"> >>> p.start()</span>
|
||
<span class="go"> >>> print(p, p.is_alive())</span>
|
||
<span class="go"> <Process ... started> True</span>
|
||
<span class="go"> >>> p.terminate()</span>
|
||
<span class="go"> >>> time.sleep(0.1)</span>
|
||
<span class="go"> >>> print(p, p.is_alive())</span>
|
||
<span class="go"> <Process ... stopped exitcode=-SIGTERM> False</span>
|
||
<span class="go"> >>> p.exitcode == -signal.SIGTERM</span>
|
||
<span class="go"> True</span>
|
||
</pre></div>
|
||
</div>
|
||
</dd></dl>
|
||
|
||
<dl class="exception">
|
||
<dt id="multiprocessing.ProcessError">
|
||
<em class="property">exception </em><code class="sig-prename descclassname">multiprocessing.</code><code class="sig-name descname">ProcessError</code><a class="headerlink" href="#multiprocessing.ProcessError" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>所有 <a class="reference internal" href="#module-multiprocessing" title="multiprocessing: Process-based parallelism."><code class="xref py py-mod docutils literal notranslate"><span class="pre">multiprocessing</span></code></a> 异常的基类。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="exception">
|
||
<dt id="multiprocessing.BufferTooShort">
|
||
<em class="property">exception </em><code class="sig-prename descclassname">multiprocessing.</code><code class="sig-name descname">BufferTooShort</code><a class="headerlink" href="#multiprocessing.BufferTooShort" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>当提供的缓冲区对象太小而无法读取消息时, <code class="xref py py-meth docutils literal notranslate"><span class="pre">Connection.recv_bytes_into()</span></code> 引发的异常。</p>
|
||
<p>如果 <code class="docutils literal notranslate"><span class="pre">e</span></code> 是一个 <a class="reference internal" href="#multiprocessing.BufferTooShort" title="multiprocessing.BufferTooShort"><code class="xref py py-exc docutils literal notranslate"><span class="pre">BufferTooShort</span></code></a> 实例,那么 <code class="docutils literal notranslate"><span class="pre">e.args[0]</span></code> 将把消息作为字节字符串给出。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="exception">
|
||
<dt id="multiprocessing.AuthenticationError">
|
||
<em class="property">exception </em><code class="sig-prename descclassname">multiprocessing.</code><code class="sig-name descname">AuthenticationError</code><a class="headerlink" href="#multiprocessing.AuthenticationError" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>出现身份验证错误时引发。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="exception">
|
||
<dt id="multiprocessing.TimeoutError">
|
||
<em class="property">exception </em><code class="sig-prename descclassname">multiprocessing.</code><code class="sig-name descname">TimeoutError</code><a class="headerlink" href="#multiprocessing.TimeoutError" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>有超时的方法超时时引发。</p>
|
||
</dd></dl>
|
||
|
||
</section>
|
||
<section id="pipes-and-queues">
|
||
<h3>管道和队列<a class="headerlink" href="#pipes-and-queues" title="永久链接至标题">¶</a></h3>
|
||
<p>使用多进程时,一般使用消息机制实现进程间通信,尽可能避免使用同步原语,例如锁。</p>
|
||
<p>消息机制包含: <a class="reference internal" href="#multiprocessing.Pipe" title="multiprocessing.Pipe"><code class="xref py py-func docutils literal notranslate"><span class="pre">Pipe()</span></code></a> (可以用于在两个进程间传递消息),以及队列(能够在多个生产者和消费者之间通信)。</p>
|
||
<p><a class="reference internal" href="#multiprocessing.Queue" title="multiprocessing.Queue"><code class="xref py py-class docutils literal notranslate"><span class="pre">Queue</span></code></a>, <a class="reference internal" href="#multiprocessing.SimpleQueue" title="multiprocessing.SimpleQueue"><code class="xref py py-class docutils literal notranslate"><span class="pre">SimpleQueue</span></code></a> 以及 <a class="reference internal" href="#multiprocessing.JoinableQueue" title="multiprocessing.JoinableQueue"><code class="xref py py-class docutils literal notranslate"><span class="pre">JoinableQueue</span></code></a> 都是多生产者,多消费者,并且实现了 <abbr title="first-in, first-out">FIFO</abbr> 的队列类型,其表现与标准库中的 <a class="reference internal" href="queue.html#queue.Queue" title="queue.Queue"><code class="xref py py-class docutils literal notranslate"><span class="pre">queue.Queue</span></code></a> 类相似。 不同之处在于 <a class="reference internal" href="#multiprocessing.Queue" title="multiprocessing.Queue"><code class="xref py py-class docutils literal notranslate"><span class="pre">Queue</span></code></a> 缺少标准库的 <a class="reference internal" href="queue.html#queue.Queue" title="queue.Queue"><code class="xref py py-class docutils literal notranslate"><span class="pre">queue.Queue</span></code></a> 从 Python 2.5 开始引入的 <a class="reference internal" href="queue.html#queue.Queue.task_done" title="queue.Queue.task_done"><code class="xref py py-meth docutils literal notranslate"><span class="pre">task_done()</span></code></a> 和 <a class="reference internal" href="queue.html#queue.Queue.join" title="queue.Queue.join"><code class="xref py py-meth docutils literal notranslate"><span class="pre">join()</span></code></a> 方法。</p>
|
||
<p>如果你使用了 <a class="reference internal" href="#multiprocessing.JoinableQueue" title="multiprocessing.JoinableQueue"><code class="xref py py-class docutils literal notranslate"><span class="pre">JoinableQueue</span></code></a> ,那么你 <strong>必须</strong> 对每个已经移出队列的任务调用 <a class="reference internal" href="#multiprocessing.JoinableQueue.task_done" title="multiprocessing.JoinableQueue.task_done"><code class="xref py py-meth docutils literal notranslate"><span class="pre">JoinableQueue.task_done()</span></code></a>。 不然的话用于统计未完成任务的信号量最终会溢出并抛出异常。</p>
|
||
<p>另外还可以通过使用一个管理器对象创建一个共享队列,详见 <a class="reference internal" href="#multiprocessing-managers"><span class="std std-ref">管理器</span></a> 。</p>
|
||
<div class="admonition note">
|
||
<p class="admonition-title">注解</p>
|
||
<p><a class="reference internal" href="#module-multiprocessing" title="multiprocessing: Process-based parallelism."><code class="xref py py-mod docutils literal notranslate"><span class="pre">multiprocessing</span></code></a> 使用了普通的 <a class="reference internal" href="queue.html#queue.Empty" title="queue.Empty"><code class="xref py py-exc docutils literal notranslate"><span class="pre">queue.Empty</span></code></a> 和 <a class="reference internal" href="queue.html#queue.Full" title="queue.Full"><code class="xref py py-exc docutils literal notranslate"><span class="pre">queue.Full</span></code></a> 异常去表示超时。 你需要从 <a class="reference internal" href="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="#module-multiprocessing" title="multiprocessing: Process-based parallelism."><code class="xref py py-mod docutils literal notranslate"><span class="pre">multiprocessing</span></code></a> 的命名空间中。</p>
|
||
</div>
|
||
<div class="admonition note">
|
||
<p class="admonition-title">注解</p>
|
||
<p>当一个对象被放入一个队列中时,这个对象首先会被一个后台线程用 pickle 序列化,并将序列化后的数据通过一个底层管道的管道传递到队列中。 这种做法会有点让人惊讶,但一般不会出现什么问题。 如果它们确实妨碍了你,你可以使用一个由管理器 <a class="reference internal" href="#multiprocessing-managers"><span class="std std-ref">manager</span></a> 创建的队列替换它。</p>
|
||
<ol class="arabic simple">
|
||
<li><p>将一个对象放入一个空队列后,可能需要极小的延迟,队列的方法 <a class="reference internal" href="#multiprocessing.Queue.empty" title="multiprocessing.Queue.empty"><code class="xref py py-meth docutils literal notranslate"><span class="pre">empty()</span></code></a> 才会返回 <a class="reference internal" href="constants.html#False" title="False"><code class="xref py py-const docutils literal notranslate"><span class="pre">False</span></code></a> 。而 <a class="reference internal" href="#multiprocessing.Queue.get_nowait" title="multiprocessing.Queue.get_nowait"><code class="xref py py-meth docutils literal notranslate"><span class="pre">get_nowait()</span></code></a> 可以不抛出 <a class="reference internal" href="queue.html#queue.Empty" title="queue.Empty"><code class="xref py py-exc docutils literal notranslate"><span class="pre">queue.Empty</span></code></a> 直接返回。</p></li>
|
||
<li><p>如果有多个进程同时将对象放入队列,那么在队列的另一端接受到的对象可能是无序的。但是由同一个进程放入的多个对象的顺序在另一端输出时总是一样的。</p></li>
|
||
</ol>
|
||
</div>
|
||
<div class="admonition warning">
|
||
<p class="admonition-title">警告</p>
|
||
<p>如果一个进程在尝试使用 <a class="reference internal" href="#multiprocessing.Queue" title="multiprocessing.Queue"><code class="xref py py-class docutils literal notranslate"><span class="pre">Queue</span></code></a> 期间被 <a class="reference internal" href="#multiprocessing.Process.terminate" title="multiprocessing.Process.terminate"><code class="xref py py-meth docutils literal notranslate"><span class="pre">Process.terminate()</span></code></a> 或 <a class="reference internal" href="os.html#os.kill" title="os.kill"><code class="xref py py-func docutils literal notranslate"><span class="pre">os.kill()</span></code></a> 调用终止了,那么队列中的数据很可能被破坏。 这可能导致其他进程在尝试使用该队列时发生异常。</p>
|
||
</div>
|
||
<div class="admonition warning">
|
||
<p class="admonition-title">警告</p>
|
||
<p>正如刚才提到的,如果一个子进程将一些对象放进队列中 (并且它没有用 <a class="reference internal" href="#multiprocessing.Queue.cancel_join_thread" title="multiprocessing.Queue.cancel_join_thread"><code class="xref py py-meth docutils literal notranslate"><span class="pre">JoinableQueue.cancel_join_thread</span></code></a> 方法),那么这个进程在所有缓冲区的对象被刷新进管道之前,是不会终止的。</p>
|
||
<p>这意味着,除非你确定所有放入队列中的对象都已经被消费了,否则如果你试图等待这个进程,你可能会陷入死锁中。相似地,如果该子进程不是后台进程,那么父进程可能在试图等待所有非后台进程退出时挂起。</p>
|
||
<p>注意用管理器创建的队列不存在这个问题,详见 <a class="reference internal" href="#multiprocessing-programming"><span class="std std-ref">编程指导</span></a> 。</p>
|
||
</div>
|
||
<p>该 <a class="reference internal" href="#multiprocessing-examples"><span class="std std-ref">例子</span></a> 展示了如何使用队列实现进程间通信。</p>
|
||
<dl class="function">
|
||
<dt id="multiprocessing.Pipe">
|
||
<code class="sig-prename descclassname">multiprocessing.</code><code class="sig-name descname">Pipe</code><span class="sig-paren">(</span><span class="optional">[</span><em class="sig-param">duplex</em><span class="optional">]</span><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.Pipe" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>返回一对 <a class="reference internal" href="#multiprocessing.connection.Connection" title="multiprocessing.connection.Connection"><code class="xref py py-class docutils literal notranslate"><span class="pre">Connection</span></code></a> 对象 <code class="docutils literal notranslate"><span class="pre">(conn1,</span> <span class="pre">conn2)</span></code> , 分别表示管道的两端。</p>
|
||
<p>如果 <em>duplex</em> 被置为 <code class="docutils literal notranslate"><span class="pre">True</span></code> (默认值),那么该管道是双向的。如果 <em>duplex</em> 被置为 <code class="docutils literal notranslate"><span class="pre">False</span></code> ,那么该管道是单向的,即 <code class="docutils literal notranslate"><span class="pre">conn1</span></code> 只能用于接收消息,而 <code class="docutils literal notranslate"><span class="pre">conn2</span></code> 仅能用于发送消息。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="class">
|
||
<dt id="multiprocessing.Queue">
|
||
<em class="property">class </em><code class="sig-prename descclassname">multiprocessing.</code><code class="sig-name descname">Queue</code><span class="sig-paren">(</span><span class="optional">[</span><em class="sig-param">maxsize</em><span class="optional">]</span><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.Queue" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>返回一个使用一个管道和少量锁和信号量实现的共享队列实例。当一个进程将一个对象放进队列中时,一个写入线程会启动并将对象从缓冲区写入管道中。</p>
|
||
<p>一旦超时,将抛出标准库 <a class="reference internal" href="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="queue.html#queue.Empty" title="queue.Empty"><code class="xref py py-exc docutils literal notranslate"><span class="pre">queue.Empty</span></code></a> 和 <a class="reference internal" href="queue.html#queue.Full" title="queue.Full"><code class="xref py py-exc docutils literal notranslate"><span class="pre">queue.Full</span></code></a>。</p>
|
||
<p>除了 <a class="reference internal" href="queue.html#queue.Queue.task_done" title="queue.Queue.task_done"><code class="xref py py-meth docutils literal notranslate"><span class="pre">task_done()</span></code></a> 和 <a class="reference internal" href="queue.html#queue.Queue.join" title="queue.Queue.join"><code class="xref py py-meth docutils literal notranslate"><span class="pre">join()</span></code></a> 之外,<a class="reference internal" href="#multiprocessing.Queue" title="multiprocessing.Queue"><code class="xref py py-class docutils literal notranslate"><span class="pre">Queue</span></code></a> 实现了标准库类 <a class="reference internal" href="queue.html#queue.Queue" title="queue.Queue"><code class="xref py py-class docutils literal notranslate"><span class="pre">queue.Queue</span></code></a> 中所有的方法。</p>
|
||
<dl class="method">
|
||
<dt id="multiprocessing.Queue.qsize">
|
||
<code class="sig-name descname">qsize</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.Queue.qsize" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>返回队列的大致长度。由于多线程或者多进程的上下文,这个数字是不可靠的。</p>
|
||
<p>注意,在 Unix 平台上,例如 Mac OS X ,这个方法可能会抛出 <a class="reference internal" href="exceptions.html#NotImplementedError" title="NotImplementedError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">NotImplementedError</span></code></a> 异常,因为该平台没有实现 <code class="docutils literal notranslate"><span class="pre">sem_getvalue()</span></code> 。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="method">
|
||
<dt id="multiprocessing.Queue.empty">
|
||
<code class="sig-name descname">empty</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.Queue.empty" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>如果队列是空的,返回 <code class="docutils literal notranslate"><span class="pre">True</span></code> ,反之返回 <code class="docutils literal notranslate"><span class="pre">False</span></code> 。 由于多线程或多进程的环境,该状态是不可靠的。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="method">
|
||
<dt id="multiprocessing.Queue.full">
|
||
<code class="sig-name descname">full</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.Queue.full" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>如果队列是满的,返回 <code class="docutils literal notranslate"><span class="pre">True</span></code> ,反之返回 <code class="docutils literal notranslate"><span class="pre">False</span></code> 。 由于多线程或多进程的环境,该状态是不可靠的。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="method">
|
||
<dt id="multiprocessing.Queue.put">
|
||
<code class="sig-name descname">put</code><span class="sig-paren">(</span><em class="sig-param">obj</em><span class="optional">[</span>, <em class="sig-param">block</em><span class="optional">[</span>, <em class="sig-param">timeout</em><span class="optional">]</span><span class="optional">]</span><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.Queue.put" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>将 obj 放入队列。如果可选参数 <em>block</em> 是 <code class="docutils literal notranslate"><span class="pre">True</span></code> (默认值) 而且 <em>timeout</em> 是 <code class="docutils literal notranslate"><span class="pre">None</span></code> (默认值), 将会阻塞当前进程,直到有空的缓冲槽。如果 <em>timeout</em> 是正数,将会在阻塞了最多 <em>timeout</em> 秒之后还是没有可用的缓冲槽时抛出 <a class="reference internal" href="queue.html#queue.Full" title="queue.Full"><code class="xref py py-exc docutils literal notranslate"><span class="pre">queue.Full</span></code></a> 异常。反之 (<em>block</em> 是 <code class="docutils literal notranslate"><span class="pre">False</span></code> 时),仅当有可用缓冲槽时才放入对象,否则抛出 <a class="reference internal" href="queue.html#queue.Full" title="queue.Full"><code class="xref py py-exc docutils literal notranslate"><span class="pre">queue.Full</span></code></a> 异常 (在这种情形下 <em>timeout</em> 参数会被忽略)。</p>
|
||
<div class="versionchanged">
|
||
<p><span class="versionmodified changed">在 3.8 版更改: </span>如果队列已经关闭,会抛出 <a class="reference internal" href="exceptions.html#ValueError" title="ValueError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">ValueError</span></code></a> 而不是 <a class="reference internal" href="exceptions.html#AssertionError" title="AssertionError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">AssertionError</span></code></a> 。</p>
|
||
</div>
|
||
</dd></dl>
|
||
|
||
<dl class="method">
|
||
<dt id="multiprocessing.Queue.put_nowait">
|
||
<code class="sig-name descname">put_nowait</code><span class="sig-paren">(</span><em class="sig-param">obj</em><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.Queue.put_nowait" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>相当于 <code class="docutils literal notranslate"><span class="pre">put(obj,</span> <span class="pre">False)</span></code>。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="method">
|
||
<dt id="multiprocessing.Queue.get">
|
||
<code class="sig-name descname">get</code><span class="sig-paren">(</span><span class="optional">[</span><em class="sig-param">block</em><span class="optional">[</span>, <em class="sig-param">timeout</em><span class="optional">]</span><span class="optional">]</span><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.Queue.get" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>从队列中取出并返回对象。如果可选参数 <em>block</em> 是 <code class="docutils literal notranslate"><span class="pre">True</span></code> (默认值) 而且 <em>timeout</em> 是 <code class="docutils literal notranslate"><span class="pre">None</span></code> (默认值), 将会阻塞当前进程,直到队列中出现可用的对象。如果 <em>timeout</em> 是正数,将会在阻塞了最多 <em>timeout</em> 秒之后还是没有可用的对象时抛出 <a class="reference internal" href="queue.html#queue.Empty" title="queue.Empty"><code class="xref py py-exc docutils literal notranslate"><span class="pre">queue.Empty</span></code></a> 异常。反之 (<em>block</em> 是 <code class="docutils literal notranslate"><span class="pre">False</span></code> 时),仅当有可用对象能够取出时返回,否则抛出 <a class="reference internal" href="queue.html#queue.Empty" title="queue.Empty"><code class="xref py py-exc docutils literal notranslate"><span class="pre">queue.Empty</span></code></a> 异常 (在这种情形下 <em>timeout</em> 参数会被忽略)。</p>
|
||
<div class="versionchanged">
|
||
<p><span class="versionmodified changed">在 3.8 版更改: </span>如果队列已经关闭,会抛出 <a class="reference internal" href="exceptions.html#ValueError" title="ValueError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">ValueError</span></code></a> 而不是 <a class="reference internal" href="exceptions.html#OSError" title="OSError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">OSError</span></code></a> 。</p>
|
||
</div>
|
||
</dd></dl>
|
||
|
||
<dl class="method">
|
||
<dt id="multiprocessing.Queue.get_nowait">
|
||
<code class="sig-name descname">get_nowait</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.Queue.get_nowait" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>相当于 <code class="docutils literal notranslate"><span class="pre">get(False)</span></code> 。</p>
|
||
</dd></dl>
|
||
|
||
<p><a class="reference internal" href="#multiprocessing.Queue" title="multiprocessing.Queue"><code class="xref py py-class docutils literal notranslate"><span class="pre">multiprocessing.Queue</span></code></a> 类有一些在 <a class="reference internal" href="queue.html#queue.Queue" title="queue.Queue"><code class="xref py py-class docutils literal notranslate"><span class="pre">queue.Queue</span></code></a> 类中没有出现的方法。这些方法在大多数情形下并不是必须的。</p>
|
||
<dl class="method">
|
||
<dt id="multiprocessing.Queue.close">
|
||
<code class="sig-name descname">close</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.Queue.close" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>指示当前进程将不会再往队列中放入对象。一旦所有缓冲区中的数据被写入管道之后,后台的线程会退出。这个方法在队列被gc回收时会自动调用。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="method">
|
||
<dt id="multiprocessing.Queue.join_thread">
|
||
<code class="sig-name descname">join_thread</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.Queue.join_thread" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>等待后台线程。这个方法仅在调用了 <a class="reference internal" href="#multiprocessing.Queue.close" title="multiprocessing.Queue.close"><code class="xref py py-meth docutils literal notranslate"><span class="pre">close()</span></code></a> 方法之后可用。这会阻塞当前进程,直到后台线程退出,确保所有缓冲区中的数据都被写入管道中。</p>
|
||
<p>默认情况下,如果一个不是队列创建者的进程试图退出,它会尝试等待这个队列的后台线程。这个进程可以使用 <a class="reference internal" href="#multiprocessing.Queue.cancel_join_thread" title="multiprocessing.Queue.cancel_join_thread"><code class="xref py py-meth docutils literal notranslate"><span class="pre">cancel_join_thread()</span></code></a> 让 <a class="reference internal" href="#multiprocessing.Queue.join_thread" title="multiprocessing.Queue.join_thread"><code class="xref py py-meth docutils literal notranslate"><span class="pre">join_thread()</span></code></a> 方法什么都不做直接跳过。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="method">
|
||
<dt id="multiprocessing.Queue.cancel_join_thread">
|
||
<code class="sig-name descname">cancel_join_thread</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.Queue.cancel_join_thread" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>防止 <a class="reference internal" href="#multiprocessing.Queue.join_thread" title="multiprocessing.Queue.join_thread"><code class="xref py py-meth docutils literal notranslate"><span class="pre">join_thread()</span></code></a> 方法阻塞当前进程。具体而言,这防止进程退出时自动等待后台线程退出。详见 <a class="reference internal" href="#multiprocessing.Queue.join_thread" title="multiprocessing.Queue.join_thread"><code class="xref py py-meth docutils literal notranslate"><span class="pre">join_thread()</span></code></a>。</p>
|
||
<p>可能这个方法称为”<code class="docutils literal notranslate"><span class="pre">allow_exit_without_flush()</span></code>“ 会更好。这有可能会导致正在排队进入队列的数据丢失,大多数情况下你不需要用到这个方法,仅当你不关心底层管道中可能丢失的数据,只是希望进程能够马上退出时使用。</p>
|
||
</dd></dl>
|
||
|
||
<div class="admonition note">
|
||
<p class="admonition-title">注解</p>
|
||
<p>该类的功能依赖于宿主操作系统具有可用的共享信号量实现。否则该类将被禁用,任何试图实例化一个 <a class="reference internal" href="#multiprocessing.Queue" title="multiprocessing.Queue"><code class="xref py py-class docutils literal notranslate"><span class="pre">Queue</span></code></a> 对象的操作都会抛出 <a class="reference internal" href="exceptions.html#ImportError" title="ImportError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">ImportError</span></code></a> 异常,更多信息详见 <a class="reference external" href="https://bugs.python.org/issue?@action=redirect&bpo=3770">bpo-3770</a> 。后续说明的任何专用队列对象亦如此。</p>
|
||
</div>
|
||
</dd></dl>
|
||
|
||
<dl class="class">
|
||
<dt id="multiprocessing.SimpleQueue">
|
||
<em class="property">class </em><code class="sig-prename descclassname">multiprocessing.</code><code class="sig-name descname">SimpleQueue</code><a class="headerlink" href="#multiprocessing.SimpleQueue" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>这是一个简化的 <a class="reference internal" href="#multiprocessing.Queue" title="multiprocessing.Queue"><code class="xref py py-class docutils literal notranslate"><span class="pre">Queue</span></code></a> 类的实现,很像带锁的 <a class="reference internal" href="#multiprocessing.Pipe" title="multiprocessing.Pipe"><code class="xref py py-class docutils literal notranslate"><span class="pre">Pipe</span></code></a> 。</p>
|
||
<dl class="method">
|
||
<dt id="multiprocessing.SimpleQueue.empty">
|
||
<code class="sig-name descname">empty</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.SimpleQueue.empty" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>如果队列为空返回 <code class="docutils literal notranslate"><span class="pre">True</span></code> ,否则返回 <code class="docutils literal notranslate"><span class="pre">False</span></code> 。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="method">
|
||
<dt id="multiprocessing.SimpleQueue.get">
|
||
<code class="sig-name descname">get</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.SimpleQueue.get" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>从队列中移出并返回一个对象。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="method">
|
||
<dt id="multiprocessing.SimpleQueue.put">
|
||
<code class="sig-name descname">put</code><span class="sig-paren">(</span><em class="sig-param">item</em><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.SimpleQueue.put" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>将 <em>item</em> 放入队列。</p>
|
||
</dd></dl>
|
||
|
||
</dd></dl>
|
||
|
||
<dl class="class">
|
||
<dt id="multiprocessing.JoinableQueue">
|
||
<em class="property">class </em><code class="sig-prename descclassname">multiprocessing.</code><code class="sig-name descname">JoinableQueue</code><span class="sig-paren">(</span><span class="optional">[</span><em class="sig-param">maxsize</em><span class="optional">]</span><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.JoinableQueue" title="永久链接至目标">¶</a></dt>
|
||
<dd><p><a class="reference internal" href="#multiprocessing.JoinableQueue" title="multiprocessing.JoinableQueue"><code class="xref py py-class docutils literal notranslate"><span class="pre">JoinableQueue</span></code></a> 类是 <a class="reference internal" href="#multiprocessing.Queue" title="multiprocessing.Queue"><code class="xref py py-class docutils literal notranslate"><span class="pre">Queue</span></code></a> 的子类,额外添加了 <a class="reference internal" href="#multiprocessing.JoinableQueue.task_done" title="multiprocessing.JoinableQueue.task_done"><code class="xref py py-meth docutils literal notranslate"><span class="pre">task_done()</span></code></a> 和 <a class="reference internal" href="#multiprocessing.JoinableQueue.join" title="multiprocessing.JoinableQueue.join"><code class="xref py py-meth docutils literal notranslate"><span class="pre">join()</span></code></a> 方法。</p>
|
||
<dl class="method">
|
||
<dt id="multiprocessing.JoinableQueue.task_done">
|
||
<code class="sig-name descname">task_done</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.JoinableQueue.task_done" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>指出之前进入队列的任务已经完成。由队列的消费者进程使用。对于每次调用 <a class="reference internal" href="#multiprocessing.Queue.get" title="multiprocessing.Queue.get"><code class="xref py py-meth docutils literal notranslate"><span class="pre">get()</span></code></a> 获取的任务,执行完成后调用 <a class="reference internal" href="#multiprocessing.JoinableQueue.task_done" title="multiprocessing.JoinableQueue.task_done"><code class="xref py py-meth docutils literal notranslate"><span class="pre">task_done()</span></code></a> 告诉队列该任务已经处理完成。</p>
|
||
<p>如果 <a class="reference internal" href="queue.html#queue.Queue.join" title="queue.Queue.join"><code class="xref py py-meth docutils literal notranslate"><span class="pre">join()</span></code></a> 方法正在阻塞之中,该方法会在所有对象都被处理完的时候返回 (即对之前使用 <a class="reference internal" href="#multiprocessing.Queue.put" title="multiprocessing.Queue.put"><code class="xref py py-meth docutils literal notranslate"><span class="pre">put()</span></code></a> 放进队列中的所有对象都已经返回了对应的 <a class="reference internal" href="#multiprocessing.JoinableQueue.task_done" title="multiprocessing.JoinableQueue.task_done"><code class="xref py py-meth docutils literal notranslate"><span class="pre">task_done()</span></code></a> ) 。</p>
|
||
<p>如果被调用的次数多于放入队列中的项目数量,将引发 <a class="reference internal" href="exceptions.html#ValueError" title="ValueError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">ValueError</span></code></a> 异常 。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="method">
|
||
<dt id="multiprocessing.JoinableQueue.join">
|
||
<code class="sig-name descname">join</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.JoinableQueue.join" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>阻塞至队列中所有的元素都被接收和处理完毕。</p>
|
||
<p>当条目添加到队列的时候,未完成任务的计数就会增加。每当消费者进程调用 <a class="reference internal" href="#multiprocessing.JoinableQueue.task_done" title="multiprocessing.JoinableQueue.task_done"><code class="xref py py-meth docutils literal notranslate"><span class="pre">task_done()</span></code></a> 表示这个条目已经被回收,该条目所有工作已经完成,未完成计数就会减少。当未完成计数降到零的时候, <code class="xref py py-meth docutils literal notranslate"><span class="pre">join()</span></code> 阻塞被解除。</p>
|
||
</dd></dl>
|
||
|
||
</dd></dl>
|
||
|
||
</section>
|
||
<section id="miscellaneous">
|
||
<h3>杂项<a class="headerlink" href="#miscellaneous" title="永久链接至标题">¶</a></h3>
|
||
<dl class="function">
|
||
<dt id="multiprocessing.active_children">
|
||
<code class="sig-prename descclassname">multiprocessing.</code><code class="sig-name descname">active_children</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.active_children" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>返回当前进程存活的子进程的列表。</p>
|
||
<p>调用该方法有“等待”已经结束的进程的副作用。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="function">
|
||
<dt id="multiprocessing.cpu_count">
|
||
<code class="sig-prename descclassname">multiprocessing.</code><code class="sig-name descname">cpu_count</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.cpu_count" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>返回系统的CPU数量。</p>
|
||
<p>该数量不同于当前进程可以使用的CPU数量。可用的CPU数量可以由 <code class="docutils literal notranslate"><span class="pre">len(os.sched_getaffinity(0))</span></code> 方法获得。</p>
|
||
<p>可能引发 <a class="reference internal" href="exceptions.html#NotImplementedError" title="NotImplementedError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">NotImplementedError</span></code></a> 。</p>
|
||
<div class="admonition seealso">
|
||
<p class="admonition-title">参见</p>
|
||
<p><a class="reference internal" href="os.html#os.cpu_count" title="os.cpu_count"><code class="xref py py-func docutils literal notranslate"><span class="pre">os.cpu_count()</span></code></a></p>
|
||
</div>
|
||
</dd></dl>
|
||
|
||
<dl class="function">
|
||
<dt id="multiprocessing.current_process">
|
||
<code class="sig-prename descclassname">multiprocessing.</code><code class="sig-name descname">current_process</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.current_process" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>返回与当前进程相对应的 <a class="reference internal" href="#multiprocessing.Process" title="multiprocessing.Process"><code class="xref py py-class docutils literal notranslate"><span class="pre">Process</span></code></a> 对象。</p>
|
||
<p>和 <a class="reference internal" href="threading.html#threading.current_thread" title="threading.current_thread"><code class="xref py py-func docutils literal notranslate"><span class="pre">threading.current_thread()</span></code></a> 相同。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="function">
|
||
<dt id="multiprocessing.parent_process">
|
||
<code class="sig-prename descclassname">multiprocessing.</code><code class="sig-name descname">parent_process</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.parent_process" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>返回父进程 <a class="reference internal" href="#multiprocessing.Process" title="multiprocessing.Process"><code class="xref py py-class docutils literal notranslate"><span class="pre">Process</span></code></a> 对象,和父进程调用 <a class="reference internal" href="#multiprocessing.current_process" title="multiprocessing.current_process"><code class="xref py py-func docutils literal notranslate"><span class="pre">current_process()</span></code></a> 返回的对象一样。如果一个进程已经是主进程, <code class="docutils literal notranslate"><span class="pre">parent_process</span></code> 会返回 <code class="docutils literal notranslate"><span class="pre">None</span></code>.</p>
|
||
<div class="versionadded">
|
||
<p><span class="versionmodified added">3.8 新版功能.</span></p>
|
||
</div>
|
||
</dd></dl>
|
||
|
||
<dl class="function">
|
||
<dt id="multiprocessing.freeze_support">
|
||
<code class="sig-prename descclassname">multiprocessing.</code><code class="sig-name descname">freeze_support</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.freeze_support" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>为使用了 <a class="reference internal" href="#module-multiprocessing" title="multiprocessing: Process-based parallelism."><code class="xref py py-mod docutils literal notranslate"><span class="pre">multiprocessing</span></code></a> 的程序,提供冻结以产生 Windows 可执行文件的支持。(在 <strong>py2exe</strong>, <strong>PyInstaller</strong> 和 <strong>cx_Freeze</strong> 上测试通过)</p>
|
||
<p>需要在 main 模块的 <code class="docutils literal notranslate"><span class="pre">if</span> <span class="pre">__name__</span> <span class="pre">==</span> <span class="pre">'__main__'</span></code> 该行之后马上调用该函数。例如:</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">multiprocessing</span> <span class="kn">import</span> <span class="n">Process</span><span class="p">,</span> <span class="n">freeze_support</span>
|
||
|
||
<span class="k">def</span> <span class="nf">f</span><span class="p">():</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="s1">'hello world!'</span><span class="p">)</span>
|
||
|
||
<span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s1">'__main__'</span><span class="p">:</span>
|
||
<span class="n">freeze_support</span><span class="p">()</span>
|
||
<span class="n">Process</span><span class="p">(</span><span class="n">target</span><span class="o">=</span><span class="n">f</span><span class="p">)</span><span class="o">.</span><span class="n">start</span><span class="p">()</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>如果没有调用 <code class="docutils literal notranslate"><span class="pre">freeze_support()</span></code> 在尝试运行被冻结的可执行文件时会抛出 <a class="reference internal" href="exceptions.html#RuntimeError" title="RuntimeError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">RuntimeError</span></code></a> 异常。</p>
|
||
<p>对 <code class="docutils literal notranslate"><span class="pre">freeze_support()</span></code> 的调用在非 Windows 平台上是无效的。如果该模块在 Windows 平台的 Python 解释器中正常运行 (该程序没有被冻结), 调用 <code class="docutils literal notranslate"><span class="pre">freeze_support()</span></code> 也是无效的。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="function">
|
||
<dt id="multiprocessing.get_all_start_methods">
|
||
<code class="sig-prename descclassname">multiprocessing.</code><code class="sig-name descname">get_all_start_methods</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.get_all_start_methods" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>返回支持的启动方法的列表,该列表的首项即为默认选项。可能的启动方法有 <code class="docutils literal notranslate"><span class="pre">'fork'</span></code> , <code class="docutils literal notranslate"><span class="pre">'spawn'</span></code> 和``'forkserver'`` 。在 Windows 中,只有 <code class="docutils literal notranslate"><span class="pre">'spawn'</span></code> 是可用的。 Unix 平台总是支持 <code class="docutils literal notranslate"><span class="pre">'fork'</span></code> 和 <code class="docutils literal notranslate"><span class="pre">'spawn'</span></code> ,且 <code class="docutils literal notranslate"><span class="pre">'fork'</span></code> 是默认值。</p>
|
||
<div class="versionadded">
|
||
<p><span class="versionmodified added">3.4 新版功能.</span></p>
|
||
</div>
|
||
</dd></dl>
|
||
|
||
<dl class="function">
|
||
<dt id="multiprocessing.get_context">
|
||
<code class="sig-prename descclassname">multiprocessing.</code><code class="sig-name descname">get_context</code><span class="sig-paren">(</span><em class="sig-param">method=None</em><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.get_context" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>返回一个 Context 对象。该对象具有和 <a class="reference internal" href="#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>如果 <em>method</em> 设置成 <code class="docutils literal notranslate"><span class="pre">None</span></code> 那么将返回默认上下文对象。否则 <em>method</em> 应该是 <code class="docutils literal notranslate"><span class="pre">'fork'</span></code>, <code class="docutils literal notranslate"><span class="pre">'spawn'</span></code>, <code class="docutils literal notranslate"><span class="pre">'forkserver'</span></code> 。 如果指定的启动方法不存在,将抛出 <a class="reference internal" href="exceptions.html#ValueError" title="ValueError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">ValueError</span></code></a> 异常。</p>
|
||
<div class="versionadded">
|
||
<p><span class="versionmodified added">3.4 新版功能.</span></p>
|
||
</div>
|
||
</dd></dl>
|
||
|
||
<dl class="function">
|
||
<dt id="multiprocessing.get_start_method">
|
||
<code class="sig-prename descclassname">multiprocessing.</code><code class="sig-name descname">get_start_method</code><span class="sig-paren">(</span><em class="sig-param">allow_none=False</em><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.get_start_method" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>返回启动进程时使用的启动方法名。</p>
|
||
<p>如果启动方法已经固定,并且 <em>allow_none</em> 被设置成 False ,那么启动方法将被固定为默认的启动方法,并且返回其方法名。如果启动方法没有设定,并且 <em>allow_none</em> 被设置成 True ,那么将返回 <code class="docutils literal notranslate"><span class="pre">None</span></code> 。</p>
|
||
<p>返回值将为 <code class="docutils literal notranslate"><span class="pre">'fork'</span></code> , <code class="docutils literal notranslate"><span class="pre">'spawn'</span></code> , <code class="docutils literal notranslate"><span class="pre">'forkserver'</span></code> 或者 <code class="docutils literal notranslate"><span class="pre">None</span></code> 。 <code class="docutils literal notranslate"><span class="pre">'fork'</span></code> 是 Unix 的默认值, <code class="docutils literal notranslate"><span class="pre">'spawn'</span></code> 是 Windows 和 macOS 的默认值。</p>
|
||
</dd></dl>
|
||
|
||
<div class="versionchanged">
|
||
<p><span class="versionmodified changed">在 3.8 版更改: </span>对于 macOS,<em>spawn</em> 启动方式是默认方式。 因为 <em>fork</em> 可能导致subprocess崩溃,被认为是不安全的,查看 <a class="reference external" href="https://bugs.python.org/issue?@action=redirect&bpo=33725">bpo-33725</a> 。</p>
|
||
<div class="versionadded">
|
||
<p><span class="versionmodified added">3.4 新版功能.</span></p>
|
||
</div>
|
||
</div>
|
||
<dl class="function">
|
||
<dt id="multiprocessing.set_executable">
|
||
<code class="sig-prename descclassname">multiprocessing.</code><code class="sig-name descname">set_executable</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.set_executable" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>设置在启动子进程时使用的 Python 解释器路径。 ( 默认使用 <a class="reference internal" href="sys.html#sys.executable" title="sys.executable"><code class="xref py py-data docutils literal notranslate"><span class="pre">sys.executable</span></code></a> ) 嵌入式编程人员可能需要这样做:</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">set_executable</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">exec_prefix</span><span class="p">,</span> <span class="s1">'pythonw.exe'</span><span class="p">))</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>以使他们可以创建子进程。</p>
|
||
<div class="versionchanged">
|
||
<p><span class="versionmodified changed">在 3.4 版更改: </span>现在在 Unix 平台上使用 <code class="docutils literal notranslate"><span class="pre">'spawn'</span></code> 启动方法时支持调用该方法。</p>
|
||
</div>
|
||
</dd></dl>
|
||
|
||
<dl class="function">
|
||
<dt id="multiprocessing.set_start_method">
|
||
<code class="sig-prename descclassname">multiprocessing.</code><code class="sig-name descname">set_start_method</code><span class="sig-paren">(</span><em class="sig-param">method</em><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.set_start_method" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>设置启动子进程的方法。 <em>method</em> 可以是 <code class="docutils literal notranslate"><span class="pre">'fork'</span></code> , <code class="docutils literal notranslate"><span class="pre">'spawn'</span></code> 或者 <code class="docutils literal notranslate"><span class="pre">'forkserver'</span></code> 。</p>
|
||
<p>注意这最多只能调用一次,并且需要藏在 main 模块中,由 <code class="docutils literal notranslate"><span class="pre">if</span> <span class="pre">__name__</span> <span class="pre">==</span> <span class="pre">'__main__'</span></code> 保护着。</p>
|
||
<div class="versionadded">
|
||
<p><span class="versionmodified added">3.4 新版功能.</span></p>
|
||
</div>
|
||
</dd></dl>
|
||
|
||
<div class="admonition note">
|
||
<p class="admonition-title">注解</p>
|
||
<p><a class="reference internal" href="#module-multiprocessing" title="multiprocessing: Process-based parallelism."><code class="xref py py-mod docutils literal notranslate"><span class="pre">multiprocessing</span></code></a> 并没有包含类似 <a class="reference internal" href="threading.html#threading.active_count" title="threading.active_count"><code class="xref py py-func docutils literal notranslate"><span class="pre">threading.active_count()</span></code></a> , <a class="reference internal" href="threading.html#threading.enumerate" title="threading.enumerate"><code class="xref py py-func docutils literal notranslate"><span class="pre">threading.enumerate()</span></code></a> , <a class="reference internal" href="threading.html#threading.settrace" title="threading.settrace"><code class="xref py py-func docutils literal notranslate"><span class="pre">threading.settrace()</span></code></a> , <a class="reference internal" href="threading.html#threading.setprofile" title="threading.setprofile"><code class="xref py py-func docutils literal notranslate"><span class="pre">threading.setprofile()</span></code></a>, <a class="reference internal" href="threading.html#threading.Timer" title="threading.Timer"><code class="xref py py-class docutils literal notranslate"><span class="pre">threading.Timer</span></code></a> , 或者 <a class="reference internal" href="threading.html#threading.local" title="threading.local"><code class="xref py py-class docutils literal notranslate"><span class="pre">threading.local</span></code></a> 的方法和类。</p>
|
||
</div>
|
||
</section>
|
||
<section id="connection-objects">
|
||
<h3>连接对象(Connection)<a class="headerlink" href="#connection-objects" title="永久链接至标题">¶</a></h3>
|
||
<p>Connection 对象允许收发可以序列化的对象或字符串。它们可以看作面向消息的连接套接字。</p>
|
||
<p>通常使用 <a class="reference internal" href="#multiprocessing.Pipe" title="multiprocessing.Pipe"><code class="xref py py-func docutils literal notranslate"><span class="pre">Pipe</span></code></a> 创建 Connection 对象。详见 : <a class="reference internal" href="#multiprocessing-listeners-clients"><span class="std std-ref">监听器及客户端</span></a>.</p>
|
||
<dl class="class">
|
||
<dt id="multiprocessing.connection.Connection">
|
||
<em class="property">class </em><code class="sig-prename descclassname">multiprocessing.connection.</code><code class="sig-name descname">Connection</code><a class="headerlink" href="#multiprocessing.connection.Connection" title="永久链接至目标">¶</a></dt>
|
||
<dd><dl class="method">
|
||
<dt id="multiprocessing.connection.Connection.send">
|
||
<code class="sig-name descname">send</code><span class="sig-paren">(</span><em class="sig-param">obj</em><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.connection.Connection.send" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>将一个对象发送到连接的另一端,可以用 <a class="reference internal" href="#multiprocessing.connection.Connection.recv" title="multiprocessing.connection.Connection.recv"><code class="xref py py-meth docutils literal notranslate"><span class="pre">recv()</span></code></a> 读取。</p>
|
||
<p>发送的对象必须是可以序列化的,过大的对象 ( 接近 32MiB+ ,这个值取决于操作系统 ) 有可能引发 <a class="reference internal" href="exceptions.html#ValueError" title="ValueError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">ValueError</span></code></a> 异常。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="method">
|
||
<dt id="multiprocessing.connection.Connection.recv">
|
||
<code class="sig-name descname">recv</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.connection.Connection.recv" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>返回一个由另一端使用 <a class="reference internal" href="#multiprocessing.connection.Connection.send" title="multiprocessing.connection.Connection.send"><code class="xref py py-meth docutils literal notranslate"><span class="pre">send()</span></code></a> 发送的对象。该方法会一直阻塞直到接收到对象。 如果对端关闭了连接或者没有东西可接收,将抛出 <a class="reference internal" href="exceptions.html#EOFError" title="EOFError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">EOFError</span></code></a> 异常。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="method">
|
||
<dt id="multiprocessing.connection.Connection.fileno">
|
||
<code class="sig-name descname">fileno</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.connection.Connection.fileno" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>返回由连接对象使用的描述符或者句柄。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="method">
|
||
<dt id="multiprocessing.connection.Connection.close">
|
||
<code class="sig-name descname">close</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.connection.Connection.close" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>关闭连接对象。</p>
|
||
<p>当连接对象被垃圾回收时会自动调用。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="method">
|
||
<dt id="multiprocessing.connection.Connection.poll">
|
||
<code class="sig-name descname">poll</code><span class="sig-paren">(</span><span class="optional">[</span><em class="sig-param">timeout</em><span class="optional">]</span><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.connection.Connection.poll" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>返回连接对象中是否有可以读取的数据。</p>
|
||
<p>如果未指定 <em>timeout</em> ,此方法会马上返回。如果 <em>timeout</em> 是一个数字,则指定了最大阻塞的秒数。如果 <em>timeout</em> 是 <code class="docutils literal notranslate"><span class="pre">None</span></code>,那么将一直等待,不会超时。</p>
|
||
<p>注意通过使用 <a class="reference internal" href="#multiprocessing.connection.wait" title="multiprocessing.connection.wait"><code class="xref py py-func docutils literal notranslate"><span class="pre">multiprocessing.connection.wait()</span></code></a> 可以一次轮询多个连接对象。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="method">
|
||
<dt id="multiprocessing.connection.Connection.send_bytes">
|
||
<code class="sig-name descname">send_bytes</code><span class="sig-paren">(</span><em class="sig-param">buffer</em><span class="optional">[</span>, <em class="sig-param">offset</em><span class="optional">[</span>, <em class="sig-param">size</em><span class="optional">]</span><span class="optional">]</span><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.connection.Connection.send_bytes" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>从一个 <a class="reference internal" href="../glossary.html#term-bytes-like-object"><span class="xref std std-term">bytes-like object</span></a> 对象中取出字节数组并作为一条完整消息发送。</p>
|
||
<p>如果由 <em>offset</em> 给定了在 <em>buffer</em> 中读取数据的位置。 如果给定了 <em>size</em> ,那么将会从缓冲区中读取多个字节。 过大的缓冲区 ( 接近 32MiB+ ,此值依赖于操作系统 ) 有可能引发 <a class="reference internal" href="exceptions.html#ValueError" title="ValueError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">ValueError</span></code></a> 异常。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="method">
|
||
<dt id="multiprocessing.connection.Connection.recv_bytes">
|
||
<code class="sig-name descname">recv_bytes</code><span class="sig-paren">(</span><span class="optional">[</span><em class="sig-param">maxlength</em><span class="optional">]</span><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.connection.Connection.recv_bytes" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>以字符串形式返回一条从连接对象另一端发送过来的字节数据。此方法在接收到数据前将一直阻塞。 如果连接对象被对端关闭或者没有数据可读取,将抛出 <a class="reference internal" href="exceptions.html#EOFError" title="EOFError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">EOFError</span></code></a> 异常。</p>
|
||
<p>如果给定了 <em>maxlength</em> 并且消息长于 <em>maxlength</em> 那么将抛出 <a class="reference internal" href="exceptions.html#OSError" title="OSError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">OSError</span></code></a> 并且该连接对象将不再可读。</p>
|
||
<div class="versionchanged">
|
||
<p><span class="versionmodified changed">在 3.3 版更改: </span>曾经该函数抛出 <a class="reference internal" href="exceptions.html#IOError" title="IOError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">IOError</span></code></a> ,现在这是 <a class="reference internal" href="exceptions.html#OSError" title="OSError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">OSError</span></code></a> 的别名。</p>
|
||
</div>
|
||
</dd></dl>
|
||
|
||
<dl class="method">
|
||
<dt id="multiprocessing.connection.Connection.recv_bytes_into">
|
||
<code class="sig-name descname">recv_bytes_into</code><span class="sig-paren">(</span><em class="sig-param">buffer</em><span class="optional">[</span>, <em class="sig-param">offset</em><span class="optional">]</span><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.connection.Connection.recv_bytes_into" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>将一条完整的字节数据消息读入 <em>buffer</em> 中并返回消息的字节数。 此方法在接收到数据前将一直阻塞。 如果连接对象被对端关闭或者没有数据可读取,将抛出 <a class="reference internal" href="exceptions.html#EOFError" title="EOFError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">EOFError</span></code></a> 异常。</p>
|
||
<p><em>buffer</em> must be a writable <a class="reference internal" href="../glossary.html#term-bytes-like-object"><span class="xref std std-term">bytes-like object</span></a>. If
|
||
<em>offset</em> is given then the message will be written into the buffer from
|
||
that position. Offset must be a non-negative integer less than the
|
||
length of <em>buffer</em> (in bytes).</p>
|
||
<p>如果缓冲区太小,则将引发 <code class="xref py py-exc docutils literal notranslate"><span class="pre">BufferTooShort</span></code> 异常,并且完整的消息将会存放在异常实例 <code class="docutils literal notranslate"><span class="pre">e</span></code> 的 <code class="docutils literal notranslate"><span class="pre">e.args[0]</span></code> 中。</p>
|
||
</dd></dl>
|
||
|
||
<div class="versionchanged">
|
||
<p><span class="versionmodified changed">在 3.3 版更改: </span>现在连接对象自身可以通过 <a class="reference internal" href="#multiprocessing.connection.Connection.send" title="multiprocessing.connection.Connection.send"><code class="xref py py-meth docutils literal notranslate"><span class="pre">Connection.send()</span></code></a> 和 <a class="reference internal" href="#multiprocessing.connection.Connection.recv" title="multiprocessing.connection.Connection.recv"><code class="xref py py-meth docutils literal notranslate"><span class="pre">Connection.recv()</span></code></a> 在进程之间传递。</p>
|
||
</div>
|
||
<div class="versionadded">
|
||
<p><span class="versionmodified added">3.3 新版功能: </span>连接对象现已支持上下文管理协议 -- 参见 see <a class="reference internal" href="stdtypes.html#typecontextmanager"><span class="std std-ref">上下文管理器类型</span></a> 。 <a class="reference internal" href="stdtypes.html#contextmanager.__enter__" title="contextmanager.__enter__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__enter__()</span></code></a> 返回连接对象, <a class="reference internal" href="stdtypes.html#contextmanager.__exit__" title="contextmanager.__exit__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__exit__()</span></code></a> 会调用 <a class="reference internal" href="#multiprocessing.connection.Connection.close" title="multiprocessing.connection.Connection.close"><code class="xref py py-meth docutils literal notranslate"><span class="pre">close()</span></code></a> 。</p>
|
||
</div>
|
||
</dd></dl>
|
||
|
||
<p>例如:</p>
|
||
<div class="highlight-pycon3 notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="kn">from</span> <span class="nn">multiprocessing</span> <span class="kn">import</span> <span class="n">Pipe</span>
|
||
<span class="gp">>>> </span><span class="n">a</span><span class="p">,</span> <span class="n">b</span> <span class="o">=</span> <span class="n">Pipe</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="n">a</span><span class="o">.</span><span class="n">send</span><span class="p">([</span><span class="mi">1</span><span class="p">,</span> <span class="s1">'hello'</span><span class="p">,</span> <span class="kc">None</span><span class="p">])</span>
|
||
<span class="gp">>>> </span><span class="n">b</span><span class="o">.</span><span class="n">recv</span><span class="p">()</span>
|
||
<span class="go">[1, 'hello', None]</span>
|
||
<span class="gp">>>> </span><span class="n">b</span><span class="o">.</span><span class="n">send_bytes</span><span class="p">(</span><span class="sa">b</span><span class="s1">'thank you'</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">a</span><span class="o">.</span><span class="n">recv_bytes</span><span class="p">()</span>
|
||
<span class="go">b'thank you'</span>
|
||
<span class="gp">>>> </span><span class="kn">import</span> <span class="nn">array</span>
|
||
<span class="gp">>>> </span><span class="n">arr1</span> <span class="o">=</span> <span class="n">array</span><span class="o">.</span><span class="n">array</span><span class="p">(</span><span class="s1">'i'</span><span class="p">,</span> <span class="nb">range</span><span class="p">(</span><span class="mi">5</span><span class="p">))</span>
|
||
<span class="gp">>>> </span><span class="n">arr2</span> <span class="o">=</span> <span class="n">array</span><span class="o">.</span><span class="n">array</span><span class="p">(</span><span class="s1">'i'</span><span class="p">,</span> <span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">*</span> <span class="mi">10</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">a</span><span class="o">.</span><span class="n">send_bytes</span><span class="p">(</span><span class="n">arr1</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">count</span> <span class="o">=</span> <span class="n">b</span><span class="o">.</span><span class="n">recv_bytes_into</span><span class="p">(</span><span class="n">arr2</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="k">assert</span> <span class="n">count</span> <span class="o">==</span> <span class="nb">len</span><span class="p">(</span><span class="n">arr1</span><span class="p">)</span> <span class="o">*</span> <span class="n">arr1</span><span class="o">.</span><span class="n">itemsize</span>
|
||
<span class="gp">>>> </span><span class="n">arr2</span>
|
||
<span class="go">array('i', [0, 1, 2, 3, 4, 0, 0, 0, 0, 0])</span>
|
||
</pre></div>
|
||
</div>
|
||
<div class="admonition warning">
|
||
<p class="admonition-title">警告</p>
|
||
<p><a class="reference internal" href="#multiprocessing.connection.Connection.recv" title="multiprocessing.connection.Connection.recv"><code class="xref py py-meth docutils literal notranslate"><span class="pre">Connection.recv()</span></code></a> 方法会自动解封它收到的数据,除非你能够信任发送消息的进程,否则此处可能有安全风险。</p>
|
||
<p>因此, 除非连接对象是由 <code class="xref py py-func docutils literal notranslate"><span class="pre">Pipe()</span></code> 产生的,否则你应该仅在使用了某种认证手段之后才使用 <a class="reference internal" href="#multiprocessing.connection.Connection.recv" title="multiprocessing.connection.Connection.recv"><code class="xref py py-meth docutils literal notranslate"><span class="pre">recv()</span></code></a> 和 <a class="reference internal" href="#multiprocessing.connection.Connection.send" title="multiprocessing.connection.Connection.send"><code class="xref py py-meth docutils literal notranslate"><span class="pre">send()</span></code></a> 方法。 参考 <a class="reference internal" href="#multiprocessing-auth-keys"><span class="std std-ref">认证密码</span></a>。</p>
|
||
</div>
|
||
<div class="admonition warning">
|
||
<p class="admonition-title">警告</p>
|
||
<p>如果一个进程在试图读写管道时被终止了,那么管道中的数据很可能是不完整的,因为此时可能无法确定消息的边界。</p>
|
||
</div>
|
||
</section>
|
||
<section id="synchronization-primitives">
|
||
<h3>同步原语<a class="headerlink" href="#synchronization-primitives" title="永久链接至标题">¶</a></h3>
|
||
<p>通常来说同步原语在多进程环境中并不像它们在多线程环境中那么必要。参考 <a class="reference internal" href="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> 模块的文档。</p>
|
||
<p>注意可以使用管理器对象创建同步原语,参考 <a class="reference internal" href="#multiprocessing-managers"><span class="std std-ref">管理器</span></a> 。</p>
|
||
<dl class="class">
|
||
<dt id="multiprocessing.Barrier">
|
||
<em class="property">class </em><code class="sig-prename descclassname">multiprocessing.</code><code class="sig-name descname">Barrier</code><span class="sig-paren">(</span><em class="sig-param">parties</em><span class="optional">[</span>, <em class="sig-param">action</em><span class="optional">[</span>, <em class="sig-param">timeout</em><span class="optional">]</span><span class="optional">]</span><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.Barrier" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>类似 <a class="reference internal" href="threading.html#threading.Barrier" title="threading.Barrier"><code class="xref py py-class docutils literal notranslate"><span class="pre">threading.Barrier</span></code></a> 的栅栏对象。</p>
|
||
<div class="versionadded">
|
||
<p><span class="versionmodified added">3.3 新版功能.</span></p>
|
||
</div>
|
||
</dd></dl>
|
||
|
||
<dl class="class">
|
||
<dt id="multiprocessing.BoundedSemaphore">
|
||
<em class="property">class </em><code class="sig-prename descclassname">multiprocessing.</code><code class="sig-name descname">BoundedSemaphore</code><span class="sig-paren">(</span><span class="optional">[</span><em class="sig-param">value</em><span class="optional">]</span><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.BoundedSemaphore" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>非常类似 <a class="reference internal" href="threading.html#threading.BoundedSemaphore" title="threading.BoundedSemaphore"><code class="xref py py-class docutils literal notranslate"><span class="pre">threading.BoundedSemaphore</span></code></a> 的有界信号量对象。</p>
|
||
<p>一个小小的不同在于,它的 <code class="docutils literal notranslate"><span class="pre">acquire</span></code> 方法的第一个参数名是和 <a class="reference internal" href="#multiprocessing.Lock.acquire" title="multiprocessing.Lock.acquire"><code class="xref py py-meth docutils literal notranslate"><span class="pre">Lock.acquire()</span></code></a> 一样的 <em>block</em> 。</p>
|
||
<div class="admonition note">
|
||
<p class="admonition-title">注解</p>
|
||
<p>在 Mac OS X 平台上, 该对象于 <a class="reference internal" href="#multiprocessing.Semaphore" title="multiprocessing.Semaphore"><code class="xref py py-class docutils literal notranslate"><span class="pre">Semaphore</span></code></a> 不同在于 <code class="docutils literal notranslate"><span class="pre">sem_getvalue()</span></code> 方法并没有在该平台上实现。</p>
|
||
</div>
|
||
</dd></dl>
|
||
|
||
<dl class="class">
|
||
<dt id="multiprocessing.Condition">
|
||
<em class="property">class </em><code class="sig-prename descclassname">multiprocessing.</code><code class="sig-name descname">Condition</code><span class="sig-paren">(</span><span class="optional">[</span><em class="sig-param">lock</em><span class="optional">]</span><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.Condition" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>条件变量: <a class="reference internal" href="threading.html#threading.Condition" title="threading.Condition"><code class="xref py py-class docutils literal notranslate"><span class="pre">threading.Condition</span></code></a> 的别名。</p>
|
||
<p>指定的 <em>lock</em> 参数应该是 <a class="reference internal" href="#module-multiprocessing" title="multiprocessing: Process-based parallelism."><code class="xref py py-mod docutils literal notranslate"><span class="pre">multiprocessing</span></code></a> 模块中的 <a class="reference internal" href="#multiprocessing.Lock" title="multiprocessing.Lock"><code class="xref py py-class docutils literal notranslate"><span class="pre">Lock</span></code></a> 或者 <a class="reference internal" href="#multiprocessing.RLock" title="multiprocessing.RLock"><code class="xref py py-class docutils literal notranslate"><span class="pre">RLock</span></code></a> 对象。</p>
|
||
<div class="versionchanged">
|
||
<p><span class="versionmodified changed">在 3.3 版更改: </span>新增了 <a class="reference internal" href="threading.html#threading.Condition.wait_for" title="threading.Condition.wait_for"><code class="xref py py-meth docutils literal notranslate"><span class="pre">wait_for()</span></code></a> 方法。</p>
|
||
</div>
|
||
</dd></dl>
|
||
|
||
<dl class="class">
|
||
<dt id="multiprocessing.Event">
|
||
<em class="property">class </em><code class="sig-prename descclassname">multiprocessing.</code><code class="sig-name descname">Event</code><a class="headerlink" href="#multiprocessing.Event" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>A clone of <a class="reference internal" href="threading.html#threading.Event" title="threading.Event"><code class="xref py py-class docutils literal notranslate"><span class="pre">threading.Event</span></code></a>.</p>
|
||
</dd></dl>
|
||
|
||
<dl class="class">
|
||
<dt id="multiprocessing.Lock">
|
||
<em class="property">class </em><code class="sig-prename descclassname">multiprocessing.</code><code class="sig-name descname">Lock</code><a class="headerlink" href="#multiprocessing.Lock" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>原始锁(非递归锁)对象,类似于 <a class="reference internal" href="threading.html#threading.Lock" title="threading.Lock"><code class="xref py py-class docutils literal notranslate"><span class="pre">threading.Lock</span></code></a> 。一旦一个进程或者线程拿到了锁,后续的任何其他进程或线程的其他请求都会被阻塞直到锁被释放。任何进程或线程都可以释放锁。除非另有说明,否则 <a class="reference internal" href="#multiprocessing.Lock" title="multiprocessing.Lock"><code class="xref py py-class docutils literal notranslate"><span class="pre">multiprocessing.Lock</span></code></a> 用于进程或者线程的概念和行为都和 <a class="reference internal" href="threading.html#threading.Lock" title="threading.Lock"><code class="xref py py-class docutils literal notranslate"><span class="pre">threading.Lock</span></code></a> 一致。</p>
|
||
<p>注意 <a class="reference internal" href="#multiprocessing.Lock" title="multiprocessing.Lock"><code class="xref py py-class docutils literal notranslate"><span class="pre">Lock</span></code></a> 实际上是一个工厂函数。它返回由默认上下文初始化的 <code class="docutils literal notranslate"><span class="pre">multiprocessing.synchronize.Lock</span></code> 对象。</p>
|
||
<p><a class="reference internal" href="#multiprocessing.Lock" title="multiprocessing.Lock"><code class="xref py py-class docutils literal notranslate"><span class="pre">Lock</span></code></a> supports the <a class="reference internal" href="../glossary.html#term-context-manager"><span class="xref std std-term">context manager</span></a> protocol and thus may be
|
||
used in <a class="reference internal" href="../reference/compound_stmts.html#with"><code class="xref std std-keyword docutils literal notranslate"><span class="pre">with</span></code></a> statements.</p>
|
||
<dl class="method">
|
||
<dt id="multiprocessing.Lock.acquire">
|
||
<code class="sig-name descname">acquire</code><span class="sig-paren">(</span><em class="sig-param">block=True</em>, <em class="sig-param">timeout=None</em><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.Lock.acquire" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>可以阻塞或非阻塞地获得锁。</p>
|
||
<p>如果 <em>block</em> 参数被设为 <code class="docutils literal notranslate"><span class="pre">True</span></code> ( 默认值 ) , 对该方法的调用在锁处于释放状态之前都会阻塞,然后将锁设置为锁住状态并返回 <code class="docutils literal notranslate"><span class="pre">True</span></code> 。需要注意的是第一个参数名与 <a class="reference internal" href="threading.html#threading.Lock.acquire" title="threading.Lock.acquire"><code class="xref py py-meth docutils literal notranslate"><span class="pre">threading.Lock.acquire()</span></code></a> 的不同。</p>
|
||
<p>如果 <em>block</em> 参数被设置成 <code class="docutils literal notranslate"><span class="pre">False</span></code> ,方法的调用将不会阻塞。 如果锁当前处于锁住状态,将返回 <code class="docutils literal notranslate"><span class="pre">False</span></code> ; 否则将锁设置成锁住状态,并返回 <code class="docutils literal notranslate"><span class="pre">True</span></code> 。</p>
|
||
<p>当 <em>timeout</em> 是一个正浮点数时,会在等待锁的过程中最多阻塞等待 <em>timeout</em> 秒,当 <em>timeout</em> 是负数时,效果和 <em>timeout</em> 为0时一样,当 <em>timeout</em> 是 <code class="docutils literal notranslate"><span class="pre">None</span></code> (默认值)时,等待时间是无限长。需要注意的是,对于 <em>timeout</em> 参数是负数和 <code class="docutils literal notranslate"><span class="pre">None</span></code> 的情况, 其行为与 <a class="reference internal" href="threading.html#threading.Lock.acquire" title="threading.Lock.acquire"><code class="xref py py-meth docutils literal notranslate"><span class="pre">threading.Lock.acquire()</span></code></a> 是不一样的。当 <em>block</em> 参数 为 <code class="docutils literal notranslate"><span class="pre">False</span></code> 时, <em>timeout</em> 并没有实际用处,会直接忽略。否则,函数会在拿到锁后返回 <code class="docutils literal notranslate"><span class="pre">True</span></code> 或者 超时没拿到锁后返回 <code class="docutils literal notranslate"><span class="pre">False</span></code> 。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="method">
|
||
<dt id="multiprocessing.Lock.release">
|
||
<code class="sig-name descname">release</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.Lock.release" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>释放锁,可以在任何进程、线程使用,并不限于锁的拥有者。</p>
|
||
<p>当尝试释放一个没有被持有的锁时,会抛出 <a class="reference internal" href="exceptions.html#ValueError" title="ValueError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">ValueError</span></code></a> 异常,除此之外其行为与 <a class="reference internal" href="threading.html#threading.Lock.release" title="threading.Lock.release"><code class="xref py py-meth docutils literal notranslate"><span class="pre">threading.Lock.release()</span></code></a> 一样。</p>
|
||
</dd></dl>
|
||
|
||
</dd></dl>
|
||
|
||
<dl class="class">
|
||
<dt id="multiprocessing.RLock">
|
||
<em class="property">class </em><code class="sig-prename descclassname">multiprocessing.</code><code class="sig-name descname">RLock</code><a class="headerlink" href="#multiprocessing.RLock" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>递归锁对象: 类似于 <a class="reference internal" href="threading.html#threading.RLock" title="threading.RLock"><code class="xref py py-class docutils literal notranslate"><span class="pre">threading.RLock</span></code></a> 。递归锁必须由持有线程、进程亲自释放。如果某个进程或者线程拿到了递归锁,这个进程或者线程可以再次拿到这个锁而不需要等待。但是这个进程或者线程的拿锁操作和释放锁操作的次数必须相同。</p>
|
||
<p>注意 <a class="reference internal" href="#multiprocessing.RLock" title="multiprocessing.RLock"><code class="xref py py-class docutils literal notranslate"><span class="pre">RLock</span></code></a> 是一个工厂函数,调用后返回一个使用默认 context 初始化的 <code class="docutils literal notranslate"><span class="pre">multiprocessing.synchronize.RLock</span></code> 实例。</p>
|
||
<p><a class="reference internal" href="#multiprocessing.RLock" title="multiprocessing.RLock"><code class="xref py py-class docutils literal notranslate"><span class="pre">RLock</span></code></a> 支持 <a class="reference internal" href="../glossary.html#term-context-manager"><span class="xref std std-term">context manager</span></a> 协议,因此可在 <a class="reference internal" href="../reference/compound_stmts.html#with"><code class="xref std std-keyword docutils literal notranslate"><span class="pre">with</span></code></a> 语句内使用。</p>
|
||
<dl class="method">
|
||
<dt id="multiprocessing.RLock.acquire">
|
||
<code class="sig-name descname">acquire</code><span class="sig-paren">(</span><em class="sig-param">block=True</em>, <em class="sig-param">timeout=None</em><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.RLock.acquire" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>可以阻塞或非阻塞地获得锁。</p>
|
||
<p>当 <em>block</em> 参数设置为 <code class="docutils literal notranslate"><span class="pre">True</span></code> 时,会一直阻塞直到锁处于空闲状态(没有被任何进程、线程拥有),除非当前进程或线程已经拥有了这把锁。然后当前进程/线程会持有这把锁(在锁没有其他持有者的情况下),锁内的递归等级加一,并返回 <code class="docutils literal notranslate"><span class="pre">True</span></code> . 注意, 这个函数第一个参数的行为和 <a class="reference internal" href="threading.html#threading.RLock.acquire" title="threading.RLock.acquire"><code class="xref py py-meth docutils literal notranslate"><span class="pre">threading.RLock.acquire()</span></code></a> 的实现有几个不同点,包括参数名本身。</p>
|
||
<p>当 <em>block</em> 参数是 <code class="docutils literal notranslate"><span class="pre">False</span></code> , 将不会阻塞,如果此时锁被其他进程或者线程持有,当前进程、线程获取锁操作失败,锁的递归等级也不会改变,函数返回 <code class="docutils literal notranslate"><span class="pre">False</span></code> , 如果当前锁已经处于释放状态,则当前进程、线程则会拿到锁,并且锁内的递归等级加一,函数返回 <code class="docutils literal notranslate"><span class="pre">True</span></code> 。</p>
|
||
<p><em>timeout</em> 参数的使用方法及行为与 <a class="reference internal" href="#multiprocessing.Lock.acquire" title="multiprocessing.Lock.acquire"><code class="xref py py-meth docutils literal notranslate"><span class="pre">Lock.acquire()</span></code></a> 一样。但是要注意 <em>timeout</em> 的其中一些行为和 <a class="reference internal" href="threading.html#threading.RLock.acquire" title="threading.RLock.acquire"><code class="xref py py-meth docutils literal notranslate"><span class="pre">threading.RLock.acquire()</span></code></a> 中实现的行为是不同的。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="method">
|
||
<dt id="multiprocessing.RLock.release">
|
||
<code class="sig-name descname">release</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.RLock.release" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>释放锁,使锁内的递归等级减一。如果释放后锁内的递归等级降低为0,则会重置锁的状态为释放状态(即没有被任何进程、线程持有),重置后如果有有其他进程和线程在等待这把锁,他们中的一个会获得这个锁而继续运行。如果释放后锁内的递归等级还没到达0,则这个锁仍将保持未释放状态且当前进程和线程仍然是持有者。</p>
|
||
<p>只有当前进程或线程是锁的持有者时,才允许调用这个方法。如果当前进程或线程不是这个锁的拥有者,或者这个锁处于已释放的状态(即没有任何拥有者),调用这个方法会抛出 <a class="reference internal" href="exceptions.html#AssertionError" title="AssertionError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">AssertionError</span></code></a> 异常。注意这里抛出的异常类型和 <a class="reference internal" href="threading.html#threading.RLock.release" title="threading.RLock.release"><code class="xref py py-meth docutils literal notranslate"><span class="pre">threading.RLock.release()</span></code></a> 中实现的行为不一样。</p>
|
||
</dd></dl>
|
||
|
||
</dd></dl>
|
||
|
||
<dl class="class">
|
||
<dt id="multiprocessing.Semaphore">
|
||
<em class="property">class </em><code class="sig-prename descclassname">multiprocessing.</code><code class="sig-name descname">Semaphore</code><span class="sig-paren">(</span><span class="optional">[</span><em class="sig-param">value</em><span class="optional">]</span><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.Semaphore" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>一种信号量对象: 类似于 <a class="reference internal" href="threading.html#threading.Semaphore" title="threading.Semaphore"><code class="xref py py-class docutils literal notranslate"><span class="pre">threading.Semaphore</span></code></a>.</p>
|
||
<p>一个小小的不同在于,它的 <code class="docutils literal notranslate"><span class="pre">acquire</span></code> 方法的第一个参数名是和 <a class="reference internal" href="#multiprocessing.Lock.acquire" title="multiprocessing.Lock.acquire"><code class="xref py py-meth docutils literal notranslate"><span class="pre">Lock.acquire()</span></code></a> 一样的 <em>block</em> 。</p>
|
||
</dd></dl>
|
||
|
||
<div class="admonition note">
|
||
<p class="admonition-title">注解</p>
|
||
<p>在 Mac OS X 上,不支持 <code class="docutils literal notranslate"><span class="pre">sem_timedwait</span></code> ,所以,调用 <code class="docutils literal notranslate"><span class="pre">acquire()</span></code> 时如果使用 timeout 参数,会通过循环sleep来模拟这个函数的行为。</p>
|
||
</div>
|
||
<div class="admonition note">
|
||
<p class="admonition-title">注解</p>
|
||
<p>假如信号 SIGINT 是来自于 <kbd class="kbd docutils literal notranslate">Ctrl-C</kbd> ,并且主线程被 <code class="xref py py-meth docutils literal notranslate"><span class="pre">BoundedSemaphore.acquire()</span></code>, <a class="reference internal" href="#multiprocessing.Lock.acquire" title="multiprocessing.Lock.acquire"><code class="xref py py-meth docutils literal notranslate"><span class="pre">Lock.acquire()</span></code></a>, <a class="reference internal" href="#multiprocessing.RLock.acquire" title="multiprocessing.RLock.acquire"><code class="xref py py-meth docutils literal notranslate"><span class="pre">RLock.acquire()</span></code></a>, <code class="xref py py-meth docutils literal notranslate"><span class="pre">Semaphore.acquire()</span></code>, <code class="xref py py-meth docutils literal notranslate"><span class="pre">Condition.acquire()</span></code> 或 <code class="xref py py-meth docutils literal notranslate"><span class="pre">Condition.wait()</span></code> 阻塞,则调用会立即中断同时抛出 <a class="reference internal" href="exceptions.html#KeyboardInterrupt" title="KeyboardInterrupt"><code class="xref py py-exc docutils literal notranslate"><span class="pre">KeyboardInterrupt</span></code></a> 异常。</p>
|
||
<p>这和 <a class="reference internal" href="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> 的行为不同,此模块中当执行对应的阻塞式调用时,SIGINT 会被忽略。</p>
|
||
</div>
|
||
<div class="admonition note">
|
||
<p class="admonition-title">注解</p>
|
||
<p>这个包的某些功能依赖于宿主机系统的共享信号量的实现,如果系统没有这个特性, <code class="xref py py-mod docutils literal notranslate"><span class="pre">multiprocessing.synchronize</span></code> 会被禁用,尝试导入这个模块会引发 <a class="reference internal" href="exceptions.html#ImportError" title="ImportError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">ImportError</span></code></a> 异常,详细信息请查看 <a class="reference external" href="https://bugs.python.org/issue?@action=redirect&bpo=3770">bpo-3770</a> 。</p>
|
||
</div>
|
||
</section>
|
||
<section id="shared-ctypes-objects">
|
||
<h3>共享 <a class="reference internal" href="ctypes.html#module-ctypes" title="ctypes: A foreign function library for Python."><code class="xref py py-mod docutils literal notranslate"><span class="pre">ctypes</span></code></a> 对象<a class="headerlink" href="#shared-ctypes-objects" title="永久链接至标题">¶</a></h3>
|
||
<p>在共享内存上创建可被子进程继承的共享对象时是可行的。</p>
|
||
<dl class="function">
|
||
<dt id="multiprocessing.Value">
|
||
<code class="sig-prename descclassname">multiprocessing.</code><code class="sig-name descname">Value</code><span class="sig-paren">(</span><em class="sig-param">typecode_or_type</em>, <em class="sig-param">*args</em>, <em class="sig-param">lock=True</em><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.Value" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>返回一个从共享内存上创建的 <a class="reference internal" href="ctypes.html#module-ctypes" title="ctypes: A foreign function library for Python."><code class="xref py py-mod docutils literal notranslate"><span class="pre">ctypes</span></code></a> 对象。默认情况下返回的对象实际上是经过了同步器包装过的。可以通过 <a class="reference internal" href="#multiprocessing.Value" title="multiprocessing.Value"><code class="xref py py-class docutils literal notranslate"><span class="pre">Value</span></code></a> 的 <em>value</em> 属性访问这个对象本身。</p>
|
||
<p><em>typecode_or_type</em> 指明了返回的对象类型: 它可能是一个 ctypes 类型或者 <a class="reference internal" href="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> 模块中每个类型对应的单字符长度的字符串。 <em>*args</em> 会透传给这个类的构造函数。</p>
|
||
<p>如果 <em>lock</em> 参数是 <code class="docutils literal notranslate"><span class="pre">True</span></code> (默认值), 将会新建一个递归锁用于同步对于此值的访问操作。 如果 <em>lock</em> 是 <a class="reference internal" href="#multiprocessing.Lock" title="multiprocessing.Lock"><code class="xref py py-class docutils literal notranslate"><span class="pre">Lock</span></code></a> 或者 <a class="reference internal" href="#multiprocessing.RLock" title="multiprocessing.RLock"><code class="xref py py-class docutils literal notranslate"><span class="pre">RLock</span></code></a> 对象,那么这个传入的锁将会用于同步对这个值的访问操作,如果 <em>lock</em> 是 <code class="docutils literal notranslate"><span class="pre">False</span></code> , 那么对这个对象的访问将没有锁保护,也就是说这个变量不是进程安全的。</p>
|
||
<p>诸如 <code class="docutils literal notranslate"><span class="pre">+=</span></code> 这类的操作会引发独立的读操作和写操作,也就是说这类操作符并不具有原子性。所以,如果你想让递增共享变量的操作具有原子性,仅仅以这样的方式并不能达到要求:</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">counter</span><span class="o">.</span><span class="n">value</span> <span class="o">+=</span> <span class="mi">1</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>共享对象内部关联的锁是递归锁(默认情况下就是)的情况下, 你可以采用这种方式</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">with</span> <span class="n">counter</span><span class="o">.</span><span class="n">get_lock</span><span class="p">():</span>
|
||
<span class="n">counter</span><span class="o">.</span><span class="n">value</span> <span class="o">+=</span> <span class="mi">1</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>注意 <em>lock</em> 只能是命名参数。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="function">
|
||
<dt id="multiprocessing.Array">
|
||
<code class="sig-prename descclassname">multiprocessing.</code><code class="sig-name descname">Array</code><span class="sig-paren">(</span><em class="sig-param">typecode_or_type</em>, <em class="sig-param">size_or_initializer</em>, <em class="sig-param">*</em>, <em class="sig-param">lock=True</em><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.Array" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>从共享内存中申请并返回一个具有ctypes类型的数组对象。默认情况下返回值实际上是被同步器包装过的数组对象。</p>
|
||
<p><em>typecode_or_type</em> 指明了返回的数组中的元素类型: 它可能是一个 ctypes 类型或者 <a class="reference internal" href="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> 模块中每个类型对应的单字符长度的字符串。 如果 <em>size_or_initializer</em> 是一个整数,那就会当做数组的长度,并且整个数组的内存会初始化为0。否则,如果 <em>size_or_initializer</em> 会被当成一个序列用于初始化数组中的每一个元素,并且会根据元素个数自动判断数组的长度。</p>
|
||
<p>如果 <em>lock</em> 为 <code class="docutils literal notranslate"><span class="pre">True</span></code> (默认值) 则将创建一个新的锁对象用于同步对值的访问。 如果 <em>lock</em> 为一个 <a class="reference internal" href="#multiprocessing.Lock" title="multiprocessing.Lock"><code class="xref py py-class docutils literal notranslate"><span class="pre">Lock</span></code></a> 或 <a class="reference internal" href="#multiprocessing.RLock" title="multiprocessing.RLock"><code class="xref py py-class docutils literal notranslate"><span class="pre">RLock</span></code></a> 对象则该对象将被用于同步对值的访问。 如果 <em>lock</em> 为 <code class="docutils literal notranslate"><span class="pre">False</span></code> 则对返回对象的访问将不会自动得到锁的保护,也就是说它不是“进程安全的”。</p>
|
||
<p>请注意 <em>lock</em> 是一个仅限关键字参数。</p>
|
||
<p>请注意 <a class="reference internal" href="ctypes.html#ctypes.c_char" title="ctypes.c_char"><code class="xref py py-data docutils literal notranslate"><span class="pre">ctypes.c_char</span></code></a> 的数组具有 <em>value</em> 和 <em>raw</em> 属性,允许被用来保存和提取字符串。</p>
|
||
</dd></dl>
|
||
|
||
<section id="module-multiprocessing.sharedctypes">
|
||
<span id="the-multiprocessing-sharedctypes-module"></span><h4><a class="reference internal" href="#module-multiprocessing.sharedctypes" title="multiprocessing.sharedctypes: Allocate ctypes objects from shared memory."><code class="xref py py-mod docutils literal notranslate"><span class="pre">multiprocessing.sharedctypes</span></code></a> 模块<a class="headerlink" href="#module-multiprocessing.sharedctypes" title="永久链接至标题">¶</a></h4>
|
||
<p><a class="reference internal" href="#module-multiprocessing.sharedctypes" title="multiprocessing.sharedctypes: Allocate ctypes objects from shared memory."><code class="xref py py-mod docutils literal notranslate"><span class="pre">multiprocessing.sharedctypes</span></code></a> 模块提供了一些函数,用于分配来自共享内存的、可被子进程继承的 <a class="reference internal" href="ctypes.html#module-ctypes" title="ctypes: A foreign function library for Python."><code class="xref py py-mod docutils literal notranslate"><span class="pre">ctypes</span></code></a> 对象。</p>
|
||
<div class="admonition note">
|
||
<p class="admonition-title">注解</p>
|
||
<p>虽然可以将指针存储在共享内存中,但请记住它所引用的是特定进程地址空间中的位置。 而且,指针很可能在第二个进程的上下文中无效,尝试从第二个进程对指针进行解引用可能会导致崩溃。</p>
|
||
</div>
|
||
<dl class="function">
|
||
<dt id="multiprocessing.sharedctypes.RawArray">
|
||
<code class="sig-prename descclassname">multiprocessing.sharedctypes.</code><code class="sig-name descname">RawArray</code><span class="sig-paren">(</span><em class="sig-param">typecode_or_type</em>, <em class="sig-param">size_or_initializer</em><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.sharedctypes.RawArray" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>从共享内存中申请并返回一个 ctypes 数组。</p>
|
||
<p><em>typecode_or_type</em> 指明了返回的数组中的元素类型: 它可能是一个 ctypes 类型或者 <a class="reference internal" href="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> 模块中使用的类型字符。 如果 <em>size_or_initializer</em> 是一个整数,那就会当做数组的长度,并且整个数组的内存会初始化为0。否则,如果 <em>size_or_initializer</em> 会被当成一个序列用于初始化数组中的每一个元素,并且会根据元素个数自动判断数组的长度。</p>
|
||
<p>注意对元素的访问、赋值操作可能是非原子操作 - 使用 <a class="reference internal" href="#multiprocessing.sharedctypes.Array" title="multiprocessing.sharedctypes.Array"><code class="xref py py-func docutils literal notranslate"><span class="pre">Array()</span></code></a> , 从而借助其中的锁保证操作的原子性。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="function">
|
||
<dt id="multiprocessing.sharedctypes.RawValue">
|
||
<code class="sig-prename descclassname">multiprocessing.sharedctypes.</code><code class="sig-name descname">RawValue</code><span class="sig-paren">(</span><em class="sig-param">typecode_or_type</em>, <em class="sig-param">*args</em><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.sharedctypes.RawValue" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>从共享内存中申请并返回一个 ctypes 对象。</p>
|
||
<p><em>typecode_or_type</em> 指明了返回的对象类型: 它可能是一个 ctypes 类型或者 <a class="reference internal" href="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> 模块中每个类型对应的单字符长度的字符串。 <em>*args</em> 会透传给这个类的构造函数。</p>
|
||
<p>注意对 value 的访问、赋值操作可能是非原子操作 - 使用 <a class="reference internal" href="#multiprocessing.sharedctypes.Value" title="multiprocessing.sharedctypes.Value"><code class="xref py py-func docutils literal notranslate"><span class="pre">Value()</span></code></a> ,从而借助其中的锁保证操作的原子性。</p>
|
||
<p>请注意 <a class="reference internal" href="ctypes.html#ctypes.c_char" title="ctypes.c_char"><code class="xref py py-data docutils literal notranslate"><span class="pre">ctypes.c_char</span></code></a> 的数组具有 <em>value</em> 和 <em>raw</em> 属性,允许被用来保存和提取字符串 - 请查看 <a class="reference internal" href="ctypes.html#module-ctypes" title="ctypes: A foreign function library for Python."><code class="xref py py-mod docutils literal notranslate"><span class="pre">ctypes</span></code></a> 文档。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="function">
|
||
<dt id="multiprocessing.sharedctypes.Array">
|
||
<code class="sig-prename descclassname">multiprocessing.sharedctypes.</code><code class="sig-name descname">Array</code><span class="sig-paren">(</span><em class="sig-param">typecode_or_type</em>, <em class="sig-param">size_or_initializer</em>, <em class="sig-param">*</em>, <em class="sig-param">lock=True</em><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.sharedctypes.Array" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>返回一个纯 ctypes 数组, 或者在此之上经过同步器包装过的进程安全的对象,这取决于 <em>lock</em> 参数的值,除此之外,和 <a class="reference internal" href="#multiprocessing.sharedctypes.RawArray" title="multiprocessing.sharedctypes.RawArray"><code class="xref py py-func docutils literal notranslate"><span class="pre">RawArray()</span></code></a> 一样。</p>
|
||
<p>如果 <em>lock</em> 为 <code class="docutils literal notranslate"><span class="pre">True</span></code> (默认值) 则将创建一个新的锁对象用于同步对值的访问。 如果 <em>lock</em> 为一个 <a class="reference internal" href="#multiprocessing.Lock" title="multiprocessing.Lock"><code class="xref py py-class docutils literal notranslate"><span class="pre">Lock</span></code></a> 或 <a class="reference internal" href="#multiprocessing.RLock" title="multiprocessing.RLock"><code class="xref py py-class docutils literal notranslate"><span class="pre">RLock</span></code></a> 对象则该对象将被用于同步对值的访问。 如果 <em>lock</em> 为 <code class="docutils literal notranslate"><span class="pre">False</span></code> 则对所返回对象的访问将不会自动得到锁的保护,也就是说它将不是“进程安全的”。</p>
|
||
<p>注意 <em>lock</em> 只能是命名参数。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="function">
|
||
<dt id="multiprocessing.sharedctypes.Value">
|
||
<code class="sig-prename descclassname">multiprocessing.sharedctypes.</code><code class="sig-name descname">Value</code><span class="sig-paren">(</span><em class="sig-param">typecode_or_type</em>, <em class="sig-param">*args</em>, <em class="sig-param">lock=True</em><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.sharedctypes.Value" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>返回一个纯 ctypes 数组, 或者在此之上经过同步器包装过的进程安全的对象,这取决于 <em>lock</em> 参数的值,除此之外,和 <code class="xref py py-func docutils literal notranslate"><span class="pre">RawArray()</span></code> 一样。</p>
|
||
<p>如果 <em>lock</em> 为 <code class="docutils literal notranslate"><span class="pre">True</span></code> (默认值) 则将创建一个新的锁对象用于同步对值的访问。 如果 <em>lock</em> 为一个 <a class="reference internal" href="#multiprocessing.Lock" title="multiprocessing.Lock"><code class="xref py py-class docutils literal notranslate"><span class="pre">Lock</span></code></a> 或 <a class="reference internal" href="#multiprocessing.RLock" title="multiprocessing.RLock"><code class="xref py py-class docutils literal notranslate"><span class="pre">RLock</span></code></a> 对象则该对象将被用于同步对值的访问。 如果 <em>lock</em> 为 <code class="docutils literal notranslate"><span class="pre">False</span></code> 则对所返回对象的访问将不会自动得到锁的保护,也就是说它将不是“进程安全的”。</p>
|
||
<p>注意 <em>lock</em> 只能是命名参数。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="function">
|
||
<dt id="multiprocessing.sharedctypes.copy">
|
||
<code class="sig-prename descclassname">multiprocessing.sharedctypes.</code><code class="sig-name descname">copy</code><span class="sig-paren">(</span><em class="sig-param">obj</em><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.sharedctypes.copy" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>从共享内存中申请一片空间将 ctypes 对象 <em>obj</em> 过来,然后返回一个新的 ctypes 对象。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="function">
|
||
<dt id="multiprocessing.sharedctypes.synchronized">
|
||
<code class="sig-prename descclassname">multiprocessing.sharedctypes.</code><code class="sig-name descname">synchronized</code><span class="sig-paren">(</span><em class="sig-param">obj</em><span class="optional">[</span>, <em class="sig-param">lock</em><span class="optional">]</span><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.sharedctypes.synchronized" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>将一个 ctypes 对象包装为进程安全的对象并返回,使用 <em>lock</em> 同步对于它的操作。如果 <em>lock</em> 是 <code class="docutils literal notranslate"><span class="pre">None</span></code> (默认值) ,则会自动创建一个 <a class="reference internal" href="#multiprocessing.RLock" title="multiprocessing.RLock"><code class="xref py py-class docutils literal notranslate"><span class="pre">multiprocessing.RLock</span></code></a> 对象。</p>
|
||
<p>同步器包装后的对象会在原有对象基础上额外增加两个方法: <code class="xref py py-meth docutils literal notranslate"><span class="pre">get_obj()</span></code> 返回被包装的对象, <code class="xref py py-meth docutils literal notranslate"><span class="pre">get_lock()</span></code> 返回内部用于同步的锁。</p>
|
||
<p>需要注意的是,访问包装后的ctypes对象会比直接访问原来的纯 ctypes 对象慢得多。</p>
|
||
<div class="versionchanged">
|
||
<p><span class="versionmodified changed">在 3.5 版更改: </span>同步器包装后的对象支持 <a class="reference internal" href="../glossary.html#term-context-manager"><span class="xref std std-term">context manager</span></a> 协议。</p>
|
||
</div>
|
||
</dd></dl>
|
||
|
||
<p>下面的表格对比了创建普通ctypes对象和基于共享内存上创建共享ctypes对象的语法。(表格中的 <code class="docutils literal notranslate"><span class="pre">MyStruct</span></code> 是 <a class="reference internal" href="ctypes.html#ctypes.Structure" title="ctypes.Structure"><code class="xref py py-class docutils literal notranslate"><span class="pre">ctypes.Structure</span></code></a> 的子类)</p>
|
||
<table class="docutils align-default">
|
||
<colgroup>
|
||
<col style="width: 27%" />
|
||
<col style="width: 36%" />
|
||
<col style="width: 37%" />
|
||
</colgroup>
|
||
<thead>
|
||
<tr class="row-odd"><th class="head"><p>ctypes</p></th>
|
||
<th class="head"><p>使用类型的共享ctypes</p></th>
|
||
<th class="head"><p>使用 typecode 的共享 ctypes</p></th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr class="row-even"><td><p>c_double(2.4)</p></td>
|
||
<td><p>RawValue(c_double, 2.4)</p></td>
|
||
<td><p>RawValue('d', 2.4)</p></td>
|
||
</tr>
|
||
<tr class="row-odd"><td><p>MyStruct(4, 6)</p></td>
|
||
<td><p>RawValue(MyStruct, 4, 6)</p></td>
|
||
<td></td>
|
||
</tr>
|
||
<tr class="row-even"><td><p>(c_short * 7)()</p></td>
|
||
<td><p>RawArray(c_short, 7)</p></td>
|
||
<td><p>RawArray('h', 7)</p></td>
|
||
</tr>
|
||
<tr class="row-odd"><td><p>(c_int * 3)(9, 2, 8)</p></td>
|
||
<td><p>RawArray(c_int, (9, 2, 8))</p></td>
|
||
<td><p>RawArray('i', (9, 2, 8))</p></td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<p>下面是一个在子进程中修改多个ctypes对象的例子。</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">multiprocessing</span> <span class="kn">import</span> <span class="n">Process</span><span class="p">,</span> <span class="n">Lock</span>
|
||
<span class="kn">from</span> <span class="nn">multiprocessing.sharedctypes</span> <span class="kn">import</span> <span class="n">Value</span><span class="p">,</span> <span class="n">Array</span>
|
||
<span class="kn">from</span> <span class="nn">ctypes</span> <span class="kn">import</span> <span class="n">Structure</span><span class="p">,</span> <span class="n">c_double</span>
|
||
|
||
<span class="k">class</span> <span class="nc">Point</span><span class="p">(</span><span class="n">Structure</span><span class="p">):</span>
|
||
<span class="n">_fields_</span> <span class="o">=</span> <span class="p">[(</span><span class="s1">'x'</span><span class="p">,</span> <span class="n">c_double</span><span class="p">),</span> <span class="p">(</span><span class="s1">'y'</span><span class="p">,</span> <span class="n">c_double</span><span class="p">)]</span>
|
||
|
||
<span class="k">def</span> <span class="nf">modify</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="n">x</span><span class="p">,</span> <span class="n">s</span><span class="p">,</span> <span class="n">A</span><span class="p">):</span>
|
||
<span class="n">n</span><span class="o">.</span><span class="n">value</span> <span class="o">**=</span> <span class="mi">2</span>
|
||
<span class="n">x</span><span class="o">.</span><span class="n">value</span> <span class="o">**=</span> <span class="mi">2</span>
|
||
<span class="n">s</span><span class="o">.</span><span class="n">value</span> <span class="o">=</span> <span class="n">s</span><span class="o">.</span><span class="n">value</span><span class="o">.</span><span class="n">upper</span><span class="p">()</span>
|
||
<span class="k">for</span> <span class="n">a</span> <span class="ow">in</span> <span class="n">A</span><span class="p">:</span>
|
||
<span class="n">a</span><span class="o">.</span><span class="n">x</span> <span class="o">**=</span> <span class="mi">2</span>
|
||
<span class="n">a</span><span class="o">.</span><span class="n">y</span> <span class="o">**=</span> <span class="mi">2</span>
|
||
|
||
<span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s1">'__main__'</span><span class="p">:</span>
|
||
<span class="n">lock</span> <span class="o">=</span> <span class="n">Lock</span><span class="p">()</span>
|
||
|
||
<span class="n">n</span> <span class="o">=</span> <span class="n">Value</span><span class="p">(</span><span class="s1">'i'</span><span class="p">,</span> <span class="mi">7</span><span class="p">)</span>
|
||
<span class="n">x</span> <span class="o">=</span> <span class="n">Value</span><span class="p">(</span><span class="n">c_double</span><span class="p">,</span> <span class="mf">1.0</span><span class="o">/</span><span class="mf">3.0</span><span class="p">,</span> <span class="n">lock</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span>
|
||
<span class="n">s</span> <span class="o">=</span> <span class="n">Array</span><span class="p">(</span><span class="s1">'c'</span><span class="p">,</span> <span class="sa">b</span><span class="s1">'hello world'</span><span class="p">,</span> <span class="n">lock</span><span class="o">=</span><span class="n">lock</span><span class="p">)</span>
|
||
<span class="n">A</span> <span class="o">=</span> <span class="n">Array</span><span class="p">(</span><span class="n">Point</span><span class="p">,</span> <span class="p">[(</span><span class="mf">1.875</span><span class="p">,</span><span class="o">-</span><span class="mf">6.25</span><span class="p">),</span> <span class="p">(</span><span class="o">-</span><span class="mf">5.75</span><span class="p">,</span><span class="mf">2.0</span><span class="p">),</span> <span class="p">(</span><span class="mf">2.375</span><span class="p">,</span><span class="mf">9.5</span><span class="p">)],</span> <span class="n">lock</span><span class="o">=</span><span class="n">lock</span><span class="p">)</span>
|
||
|
||
<span class="n">p</span> <span class="o">=</span> <span class="n">Process</span><span class="p">(</span><span class="n">target</span><span class="o">=</span><span class="n">modify</span><span class="p">,</span> <span class="n">args</span><span class="o">=</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="n">x</span><span class="p">,</span> <span class="n">s</span><span class="p">,</span> <span class="n">A</span><span class="p">))</span>
|
||
<span class="n">p</span><span class="o">.</span><span class="n">start</span><span class="p">()</span>
|
||
<span class="n">p</span><span class="o">.</span><span class="n">join</span><span class="p">()</span>
|
||
|
||
<span class="nb">print</span><span class="p">(</span><span class="n">n</span><span class="o">.</span><span class="n">value</span><span class="p">)</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="n">x</span><span class="o">.</span><span class="n">value</span><span class="p">)</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="n">s</span><span class="o">.</span><span class="n">value</span><span class="p">)</span>
|
||
<span class="nb">print</span><span class="p">([(</span><span class="n">a</span><span class="o">.</span><span class="n">x</span><span class="p">,</span> <span class="n">a</span><span class="o">.</span><span class="n">y</span><span class="p">)</span> <span class="k">for</span> <span class="n">a</span> <span class="ow">in</span> <span class="n">A</span><span class="p">])</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>输出如下</p>
|
||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>49
|
||
0.1111111111111111
|
||
HELLO WORLD
|
||
[(3.515625, 39.0625), (33.0625, 4.0), (5.640625, 90.25)]
|
||
</pre></div>
|
||
</div>
|
||
</section>
|
||
</section>
|
||
<section id="managers">
|
||
<span id="multiprocessing-managers"></span><h3>管理器<a class="headerlink" href="#managers" title="永久链接至标题">¶</a></h3>
|
||
<p>管理器提供了一种创建共享数据的方法,从而可以在不同进程中共享,甚至可以通过网络跨机器共享数据。管理器维护一个用于管理 <em>共享对象</em> 的服务。其他进程可以通过代理访问这些共享对象。</p>
|
||
<dl class="function">
|
||
<dt id="multiprocessing.sharedctypes.multiprocessing.Manager">
|
||
<code class="sig-prename descclassname">multiprocessing.</code><code class="sig-name descname">Manager</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.sharedctypes.multiprocessing.Manager" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>返回一个已启动的 <a class="reference internal" href="#multiprocessing.managers.SyncManager" title="multiprocessing.managers.SyncManager"><code class="xref py py-class docutils literal notranslate"><span class="pre">SyncManager</span></code></a> 管理器对象,这个对象可以用于在不同进程中共享数据。返回的管理器对象对应了一个已经启动的子进程,并且拥有一系列方法可以用于创建共享对象、返回对应的代理。</p>
|
||
</dd></dl>
|
||
|
||
<span class="target" id="module-multiprocessing.managers"></span><p>当管理器被垃圾回收或者父进程退出时,管理器进程会立即退出。管理器类定义在 <a class="reference internal" href="#module-multiprocessing.managers" title="multiprocessing.managers: Share data between process with shared objects."><code class="xref py py-mod docutils literal notranslate"><span class="pre">multiprocessing.managers</span></code></a> 模块:</p>
|
||
<dl class="class">
|
||
<dt id="multiprocessing.managers.BaseManager">
|
||
<em class="property">class </em><code class="sig-prename descclassname">multiprocessing.managers.</code><code class="sig-name descname">BaseManager</code><span class="sig-paren">(</span><span class="optional">[</span><em class="sig-param">address</em><span class="optional">[</span>, <em class="sig-param">authkey</em><span class="optional">]</span><span class="optional">]</span><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.managers.BaseManager" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>创建一个 BaseManager 对象。</p>
|
||
<p>一旦创建,应该及时调用 <a class="reference internal" href="#multiprocessing.managers.BaseManager.start" title="multiprocessing.managers.BaseManager.start"><code class="xref py py-meth docutils literal notranslate"><span class="pre">start()</span></code></a> 或者 <code class="docutils literal notranslate"><span class="pre">get_server().serve_forever()</span></code> 以确保管理器对象对应的管理进程已经启动。</p>
|
||
<p><em>address</em> 是管理器服务进程监听的地址。如果 <em>address</em> 是 <code class="docutils literal notranslate"><span class="pre">None</span></code> ,则允许和任意主机的请求建立连接。</p>
|
||
<p><em>authkey</em> 是认证标识,用于检查连接服务进程的请求合法性。如果 <em>authkey</em> 是 <code class="docutils literal notranslate"><span class="pre">None</span></code>, 则会使用 <code class="docutils literal notranslate"><span class="pre">current_process().authkey</span></code> , 否则,就使用 <em>authkey</em> , 需要保证它必须是 byte 类型的字符串。</p>
|
||
<dl class="method">
|
||
<dt id="multiprocessing.managers.BaseManager.start">
|
||
<code class="sig-name descname">start</code><span class="sig-paren">(</span><span class="optional">[</span><em class="sig-param">initializer</em><span class="optional">[</span>, <em class="sig-param">initargs</em><span class="optional">]</span><span class="optional">]</span><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.managers.BaseManager.start" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>为管理器开启一个子进程,如果 <em>initializer</em> 不是 <code class="docutils literal notranslate"><span class="pre">None</span></code> , 子进程在启动时将会调用 <code class="docutils literal notranslate"><span class="pre">initializer(*initargs)</span></code> 。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="method">
|
||
<dt id="multiprocessing.managers.BaseManager.get_server">
|
||
<code class="sig-name descname">get_server</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.managers.BaseManager.get_server" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>返回一个 <code class="xref py py-class docutils literal notranslate"><span class="pre">Server</span></code> 对象,它是管理器在后台控制的真实的服务。 <code class="xref py py-class docutils literal notranslate"><span class="pre">Server</span></code> 对象拥有 <code class="xref py py-meth docutils literal notranslate"><span class="pre">serve_forever()</span></code> 方法。</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="kn">from</span> <span class="nn">multiprocessing.managers</span> <span class="kn">import</span> <span class="n">BaseManager</span>
|
||
<span class="gp">>>> </span><span class="n">manager</span> <span class="o">=</span> <span class="n">BaseManager</span><span class="p">(</span><span class="n">address</span><span class="o">=</span><span class="p">(</span><span class="s1">''</span><span class="p">,</span> <span class="mi">50000</span><span class="p">),</span> <span class="n">authkey</span><span class="o">=</span><span class="sa">b</span><span class="s1">'abc'</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">server</span> <span class="o">=</span> <span class="n">manager</span><span class="o">.</span><span class="n">get_server</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="n">server</span><span class="o">.</span><span class="n">serve_forever</span><span class="p">()</span>
|
||
</pre></div>
|
||
</div>
|
||
<p><code class="xref py py-class docutils literal notranslate"><span class="pre">Server</span></code> 额外拥有一个 <a class="reference internal" href="#multiprocessing.managers.BaseManager.address" title="multiprocessing.managers.BaseManager.address"><code class="xref py py-attr docutils literal notranslate"><span class="pre">address</span></code></a> 属性。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="method">
|
||
<dt id="multiprocessing.managers.BaseManager.connect">
|
||
<code class="sig-name descname">connect</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.managers.BaseManager.connect" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>将本地管理器对象连接到一个远程管理器进程:</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="kn">from</span> <span class="nn">multiprocessing.managers</span> <span class="kn">import</span> <span class="n">BaseManager</span>
|
||
<span class="gp">>>> </span><span class="n">m</span> <span class="o">=</span> <span class="n">BaseManager</span><span class="p">(</span><span class="n">address</span><span class="o">=</span><span class="p">(</span><span class="s1">'127.0.0.1'</span><span class="p">,</span> <span class="mi">50000</span><span class="p">),</span> <span class="n">authkey</span><span class="o">=</span><span class="sa">b</span><span class="s1">'abc'</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">m</span><span class="o">.</span><span class="n">connect</span><span class="p">()</span>
|
||
</pre></div>
|
||
</div>
|
||
</dd></dl>
|
||
|
||
<dl class="method">
|
||
<dt id="multiprocessing.managers.BaseManager.shutdown">
|
||
<code class="sig-name descname">shutdown</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.managers.BaseManager.shutdown" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>停止管理器的进程。这个方法只能用于已经使用 <a class="reference internal" href="#multiprocessing.managers.BaseManager.start" title="multiprocessing.managers.BaseManager.start"><code class="xref py py-meth docutils literal notranslate"><span class="pre">start()</span></code></a> 启动的服务进程。</p>
|
||
<p>它可以被多次调用。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="method">
|
||
<dt id="multiprocessing.managers.BaseManager.register">
|
||
<code class="sig-name descname">register</code><span class="sig-paren">(</span><em class="sig-param">typeid</em><span class="optional">[</span>, <em class="sig-param">callable</em><span class="optional">[</span>, <em class="sig-param">proxytype</em><span class="optional">[</span>, <em class="sig-param">exposed</em><span class="optional">[</span>, <em class="sig-param">method_to_typeid</em><span class="optional">[</span>, <em class="sig-param">create_method</em><span class="optional">]</span><span class="optional">]</span><span class="optional">]</span><span class="optional">]</span><span class="optional">]</span><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.managers.BaseManager.register" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>一个 classmethod,可以将一个类型或者可调用对象注册到管理器类。</p>
|
||
<p><em>typeid</em> 是一种 "类型标识符",用于唯一表示某种共享对象类型,必须是一个字符串。</p>
|
||
<p><em>callable</em> 是一个用来为此类型标识符创建对象的可调用对象。如果一个管理器实例将使用 <a class="reference internal" href="#multiprocessing.managers.BaseManager.connect" title="multiprocessing.managers.BaseManager.connect"><code class="xref py py-meth docutils literal notranslate"><span class="pre">connect()</span></code></a> 方法连接到服务器,或者 <em>create_method</em> 参数为 <code class="docutils literal notranslate"><span class="pre">False</span></code>,那么这里可留下 <code class="docutils literal notranslate"><span class="pre">None</span></code>。</p>
|
||
<p><em>proxytype</em> 是 <a class="reference internal" href="#multiprocessing.managers.BaseProxy" title="multiprocessing.managers.BaseProxy"><code class="xref py py-class docutils literal notranslate"><span class="pre">BaseProxy</span></code></a> 的子类,可以根据 <em>typeid</em> 为共享对象创建一个代理,如果是 <code class="docutils literal notranslate"><span class="pre">None</span></code> , 则会自动创建一个代理类。</p>
|
||
<p><em>exposed</em> 是一个函数名组成的序列,用来指明只有这些方法可以使用 <a class="reference internal" href="#multiprocessing.managers.BaseProxy._callmethod" title="multiprocessing.managers.BaseProxy._callmethod"><code class="xref py py-meth docutils literal notranslate"><span class="pre">BaseProxy._callmethod()</span></code></a> 代理。(如果 <em>exposed</em> 是 <code class="docutils literal notranslate"><span class="pre">None</span></code>, 则会在 <code class="xref py py-attr docutils literal notranslate"><span class="pre">proxytype._exposed_</span></code> 存在的情况下转而使用它) 当暴露的方法列表没有指定的时候,共享对象的所有 “公共方法” 都会被代理。(这里的“公共方法”是指所有拥有 <a class="reference internal" href="../reference/datamodel.html#object.__call__" title="object.__call__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__call__()</span></code></a> 方法并且不是以 <code class="docutils literal notranslate"><span class="pre">'_'</span></code> 开头的属性)</p>
|
||
<p><em>method_to_typeid</em> 是一个映射,用来指定那些应该返回代理对象的暴露方法所返回的类型。(如果 <em>method_to_typeid</em> 是 <code class="docutils literal notranslate"><span class="pre">None</span></code>, 则 <code class="xref py py-attr docutils literal notranslate"><span class="pre">proxytype._method_to_typeid_</span></code> 会在存在的情况下被使用)如果方法名称不在这个映射中或者映射是 <code class="docutils literal notranslate"><span class="pre">None</span></code> ,则方法返回的对象会是一个值拷贝。</p>
|
||
<p><em>create_method</em> 指明,是否要创建一个以 <em>typeid</em> 命名并返回一个代理对象的方法,这个函数会被服务进程用于创建共享对象,默认为 <code class="docutils literal notranslate"><span class="pre">True</span></code> 。</p>
|
||
</dd></dl>
|
||
|
||
<p><a class="reference internal" href="#multiprocessing.managers.BaseManager" title="multiprocessing.managers.BaseManager"><code class="xref py py-class docutils literal notranslate"><span class="pre">BaseManager</span></code></a> 实例也有一个只读属性。</p>
|
||
<dl class="attribute">
|
||
<dt id="multiprocessing.managers.BaseManager.address">
|
||
<code class="sig-name descname">address</code><a class="headerlink" href="#multiprocessing.managers.BaseManager.address" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>管理器所用的地址。</p>
|
||
</dd></dl>
|
||
|
||
<div class="versionchanged">
|
||
<p><span class="versionmodified changed">在 3.3 版更改: </span>管理器对象支持上下文管理协议 - 查看 <a class="reference internal" href="stdtypes.html#typecontextmanager"><span class="std std-ref">上下文管理器类型</span></a> 。<a class="reference internal" href="stdtypes.html#contextmanager.__enter__" title="contextmanager.__enter__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__enter__()</span></code></a> 启动服务进程(如果它还没有启动)并且返回管理器对象, <a class="reference internal" href="stdtypes.html#contextmanager.__exit__" title="contextmanager.__exit__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__exit__()</span></code></a> 会调用 <a class="reference internal" href="#multiprocessing.managers.BaseManager.shutdown" title="multiprocessing.managers.BaseManager.shutdown"><code class="xref py py-meth docutils literal notranslate"><span class="pre">shutdown()</span></code></a> 。</p>
|
||
<p>在之前的版本中,如果管理器服务进程没有启动, <a class="reference internal" href="stdtypes.html#contextmanager.__enter__" title="contextmanager.__enter__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__enter__()</span></code></a> 不会负责启动它。</p>
|
||
</div>
|
||
</dd></dl>
|
||
|
||
<dl class="class">
|
||
<dt id="multiprocessing.managers.SyncManager">
|
||
<em class="property">class </em><code class="sig-prename descclassname">multiprocessing.managers.</code><code class="sig-name descname">SyncManager</code><a class="headerlink" href="#multiprocessing.managers.SyncManager" title="永久链接至目标">¶</a></dt>
|
||
<dd><p><a class="reference internal" href="#multiprocessing.managers.BaseManager" title="multiprocessing.managers.BaseManager"><code class="xref py py-class docutils literal notranslate"><span class="pre">BaseManager</span></code></a> 的子类,可用于进程的同步。这个类型的对象使用 <code class="xref py py-func docutils literal notranslate"><span class="pre">multiprocessing.Manager()</span></code> 创建。</p>
|
||
<p>它拥有一系列方法,可以为大部分常用数据类型创建并返回 <a class="reference internal" href="#multiprocessing-proxy-objects"><span class="std std-ref">代理对象</span></a> 代理,用于进程间同步。甚至包括共享列表和字典。</p>
|
||
<dl class="method">
|
||
<dt id="multiprocessing.managers.SyncManager.Barrier">
|
||
<code class="sig-name descname">Barrier</code><span class="sig-paren">(</span><em class="sig-param">parties</em><span class="optional">[</span>, <em class="sig-param">action</em><span class="optional">[</span>, <em class="sig-param">timeout</em><span class="optional">]</span><span class="optional">]</span><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.managers.SyncManager.Barrier" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>创建一个共享的 <a class="reference internal" href="threading.html#threading.Barrier" title="threading.Barrier"><code class="xref py py-class docutils literal notranslate"><span class="pre">threading.Barrier</span></code></a> 对象并返回它的代理。</p>
|
||
<div class="versionadded">
|
||
<p><span class="versionmodified added">3.3 新版功能.</span></p>
|
||
</div>
|
||
</dd></dl>
|
||
|
||
<dl class="method">
|
||
<dt id="multiprocessing.managers.SyncManager.BoundedSemaphore">
|
||
<code class="sig-name descname">BoundedSemaphore</code><span class="sig-paren">(</span><span class="optional">[</span><em class="sig-param">value</em><span class="optional">]</span><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.managers.SyncManager.BoundedSemaphore" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>创建一个共享的 <a class="reference internal" href="threading.html#threading.BoundedSemaphore" title="threading.BoundedSemaphore"><code class="xref py py-class docutils literal notranslate"><span class="pre">threading.BoundedSemaphore</span></code></a> 对象并返回它的代理。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="method">
|
||
<dt id="multiprocessing.managers.SyncManager.Condition">
|
||
<code class="sig-name descname">Condition</code><span class="sig-paren">(</span><span class="optional">[</span><em class="sig-param">lock</em><span class="optional">]</span><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.managers.SyncManager.Condition" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>创建一个共享的 <a class="reference internal" href="threading.html#threading.Condition" title="threading.Condition"><code class="xref py py-class docutils literal notranslate"><span class="pre">threading.Condition</span></code></a> 对象并返回它的代理。</p>
|
||
<p>如果提供了 <em>lock</em> 参数,那它必须是 <a class="reference internal" href="threading.html#threading.Lock" title="threading.Lock"><code class="xref py py-class docutils literal notranslate"><span class="pre">threading.Lock</span></code></a> 或 <a class="reference internal" href="threading.html#threading.RLock" title="threading.RLock"><code class="xref py py-class docutils literal notranslate"><span class="pre">threading.RLock</span></code></a> 的代理对象。</p>
|
||
<div class="versionchanged">
|
||
<p><span class="versionmodified changed">在 3.3 版更改: </span>新增了 <a class="reference internal" href="threading.html#threading.Condition.wait_for" title="threading.Condition.wait_for"><code class="xref py py-meth docutils literal notranslate"><span class="pre">wait_for()</span></code></a> 方法。</p>
|
||
</div>
|
||
</dd></dl>
|
||
|
||
<dl class="method">
|
||
<dt id="multiprocessing.managers.SyncManager.Event">
|
||
<code class="sig-name descname">Event</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.managers.SyncManager.Event" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>创建一个共享的 <a class="reference internal" href="threading.html#threading.Event" title="threading.Event"><code class="xref py py-class docutils literal notranslate"><span class="pre">threading.Event</span></code></a> 对象并返回它的代理。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="method">
|
||
<dt id="multiprocessing.managers.SyncManager.Lock">
|
||
<code class="sig-name descname">Lock</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.managers.SyncManager.Lock" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>创建一个共享的 <a class="reference internal" href="threading.html#threading.Lock" title="threading.Lock"><code class="xref py py-class docutils literal notranslate"><span class="pre">threading.Lock</span></code></a> 对象并返回它的代理。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="method">
|
||
<dt id="multiprocessing.managers.SyncManager.Namespace">
|
||
<code class="sig-name descname">Namespace</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.managers.SyncManager.Namespace" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>创建一个共享的 <a class="reference internal" href="#multiprocessing.managers.Namespace" title="multiprocessing.managers.Namespace"><code class="xref py py-class docutils literal notranslate"><span class="pre">Namespace</span></code></a> 对象并返回它的代理。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="method">
|
||
<dt id="multiprocessing.managers.SyncManager.Queue">
|
||
<code class="sig-name descname">Queue</code><span class="sig-paren">(</span><span class="optional">[</span><em class="sig-param">maxsize</em><span class="optional">]</span><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.managers.SyncManager.Queue" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>创建一个共享的 <a class="reference internal" href="queue.html#queue.Queue" title="queue.Queue"><code class="xref py py-class docutils literal notranslate"><span class="pre">queue.Queue</span></code></a> 对象并返回它的代理。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="method">
|
||
<dt id="multiprocessing.managers.SyncManager.RLock">
|
||
<code class="sig-name descname">RLock</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.managers.SyncManager.RLock" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>创建一个共享的 <a class="reference internal" href="threading.html#threading.RLock" title="threading.RLock"><code class="xref py py-class docutils literal notranslate"><span class="pre">threading.RLock</span></code></a> 对象并返回它的代理。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="method">
|
||
<dt id="multiprocessing.managers.SyncManager.Semaphore">
|
||
<code class="sig-name descname">Semaphore</code><span class="sig-paren">(</span><span class="optional">[</span><em class="sig-param">value</em><span class="optional">]</span><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.managers.SyncManager.Semaphore" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>创建一个共享的 <a class="reference internal" href="threading.html#threading.Semaphore" title="threading.Semaphore"><code class="xref py py-class docutils literal notranslate"><span class="pre">threading.Semaphore</span></code></a> 对象并返回它的代理。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="method">
|
||
<dt id="multiprocessing.managers.SyncManager.Array">
|
||
<code class="sig-name descname">Array</code><span class="sig-paren">(</span><em class="sig-param">typecode</em>, <em class="sig-param">sequence</em><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.managers.SyncManager.Array" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>创建一个数组并返回它的代理。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="method">
|
||
<dt id="multiprocessing.managers.SyncManager.Value">
|
||
<code class="sig-name descname">Value</code><span class="sig-paren">(</span><em class="sig-param">typecode</em>, <em class="sig-param">value</em><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.managers.SyncManager.Value" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>创建一个具有可写 <code class="docutils literal notranslate"><span class="pre">value</span></code> 属性的对象并返回它的代理。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="method">
|
||
<dt id="multiprocessing.managers.SyncManager.dict">
|
||
<code class="sig-name descname">dict</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.managers.SyncManager.dict" title="永久链接至目标">¶</a></dt>
|
||
<dt>
|
||
<code class="sig-name descname">dict</code><span class="sig-paren">(</span><em class="sig-param">mapping</em><span class="sig-paren">)</span></dt>
|
||
<dt>
|
||
<code class="sig-name descname">dict</code><span class="sig-paren">(</span><em class="sig-param">sequence</em><span class="sig-paren">)</span></dt>
|
||
<dd><p>创建一个共享的 <a class="reference internal" href="stdtypes.html#dict" title="dict"><code class="xref py py-class docutils literal notranslate"><span class="pre">dict</span></code></a> 对象并返回它的代理。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="method">
|
||
<dt id="multiprocessing.managers.SyncManager.list">
|
||
<code class="sig-name descname">list</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.managers.SyncManager.list" title="永久链接至目标">¶</a></dt>
|
||
<dt>
|
||
<code class="sig-name descname">list</code><span class="sig-paren">(</span><em class="sig-param">sequence</em><span class="sig-paren">)</span></dt>
|
||
<dd><p>创建一个共享的 <a class="reference internal" href="stdtypes.html#list" title="list"><code class="xref py py-class docutils literal notranslate"><span class="pre">list</span></code></a> 对象并返回它的代理。</p>
|
||
</dd></dl>
|
||
|
||
<div class="versionchanged">
|
||
<p><span class="versionmodified changed">在 3.6 版更改: </span>共享对象能够嵌套。例如, 共享的容器对象如共享列表,可以包含另一个共享对象,他们全都会在 <a class="reference internal" href="#multiprocessing.managers.SyncManager" title="multiprocessing.managers.SyncManager"><code class="xref py py-class docutils literal notranslate"><span class="pre">SyncManager</span></code></a> 中进行管理和同步。</p>
|
||
</div>
|
||
</dd></dl>
|
||
|
||
<dl class="class">
|
||
<dt id="multiprocessing.managers.Namespace">
|
||
<em class="property">class </em><code class="sig-prename descclassname">multiprocessing.managers.</code><code class="sig-name descname">Namespace</code><a class="headerlink" href="#multiprocessing.managers.Namespace" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>一个可以注册到 <a class="reference internal" href="#multiprocessing.managers.SyncManager" title="multiprocessing.managers.SyncManager"><code class="xref py py-class docutils literal notranslate"><span class="pre">SyncManager</span></code></a> 的类型。</p>
|
||
<p>命名空间对象没有公共方法,但是拥有可写的属性。直接print会显示所有属性的值。</p>
|
||
<p>值得一提的是,当对命名空间对象使用代理的时候,访问所有名称以 <code class="docutils literal notranslate"><span class="pre">'_'</span></code> 开头的属性都只是代理器上的属性,而不是命名空间对象的属性。</p>
|
||
<div class="highlight-pycon3 notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">manager</span> <span class="o">=</span> <span class="n">multiprocessing</span><span class="o">.</span><span class="n">Manager</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="n">Global</span> <span class="o">=</span> <span class="n">manager</span><span class="o">.</span><span class="n">Namespace</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="n">Global</span><span class="o">.</span><span class="n">x</span> <span class="o">=</span> <span class="mi">10</span>
|
||
<span class="gp">>>> </span><span class="n">Global</span><span class="o">.</span><span class="n">y</span> <span class="o">=</span> <span class="s1">'hello'</span>
|
||
<span class="gp">>>> </span><span class="n">Global</span><span class="o">.</span><span class="n">_z</span> <span class="o">=</span> <span class="mf">12.3</span> <span class="c1"># this is an attribute of the proxy</span>
|
||
<span class="gp">>>> </span><span class="nb">print</span><span class="p">(</span><span class="n">Global</span><span class="p">)</span>
|
||
<span class="go">Namespace(x=10, y='hello')</span>
|
||
</pre></div>
|
||
</div>
|
||
</dd></dl>
|
||
|
||
<section id="customized-managers">
|
||
<h4>自定义管理器<a class="headerlink" href="#customized-managers" title="永久链接至标题">¶</a></h4>
|
||
<p>要创建一个自定义的管理器,需要新建一个 <a class="reference internal" href="#multiprocessing.managers.BaseManager" title="multiprocessing.managers.BaseManager"><code class="xref py py-class docutils literal notranslate"><span class="pre">BaseManager</span></code></a> 的子类,然后使用这个管理器类上的 <a class="reference internal" href="#multiprocessing.managers.BaseManager.register" title="multiprocessing.managers.BaseManager.register"><code class="xref py py-meth docutils literal notranslate"><span class="pre">register()</span></code></a> 类方法将新类型或者可调用方法注册上去。例如:</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">multiprocessing.managers</span> <span class="kn">import</span> <span class="n">BaseManager</span>
|
||
|
||
<span class="k">class</span> <span class="nc">MathsClass</span><span class="p">:</span>
|
||
<span class="k">def</span> <span class="nf">add</span><span class="p">(</span><span class="bp">self</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="k">return</span> <span class="n">x</span> <span class="o">+</span> <span class="n">y</span>
|
||
<span class="k">def</span> <span class="nf">mul</span><span class="p">(</span><span class="bp">self</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="k">return</span> <span class="n">x</span> <span class="o">*</span> <span class="n">y</span>
|
||
|
||
<span class="k">class</span> <span class="nc">MyManager</span><span class="p">(</span><span class="n">BaseManager</span><span class="p">):</span>
|
||
<span class="k">pass</span>
|
||
|
||
<span class="n">MyManager</span><span class="o">.</span><span class="n">register</span><span class="p">(</span><span class="s1">'Maths'</span><span class="p">,</span> <span class="n">MathsClass</span><span class="p">)</span>
|
||
|
||
<span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s1">'__main__'</span><span class="p">:</span>
|
||
<span class="k">with</span> <span class="n">MyManager</span><span class="p">()</span> <span class="k">as</span> <span class="n">manager</span><span class="p">:</span>
|
||
<span class="n">maths</span> <span class="o">=</span> <span class="n">manager</span><span class="o">.</span><span class="n">Maths</span><span class="p">()</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="n">maths</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="mi">4</span><span class="p">,</span> <span class="mi">3</span><span class="p">))</span> <span class="c1"># prints 7</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="n">maths</span><span class="o">.</span><span class="n">mul</span><span class="p">(</span><span class="mi">7</span><span class="p">,</span> <span class="mi">8</span><span class="p">))</span> <span class="c1"># prints 56</span>
|
||
</pre></div>
|
||
</div>
|
||
</section>
|
||
<section id="using-a-remote-manager">
|
||
<h4>使用远程管理器<a class="headerlink" href="#using-a-remote-manager" title="永久链接至标题">¶</a></h4>
|
||
<p>可以将管理器服务运行在一台机器上,然后使用客户端从其他机器上访问。(假设它们的防火墙允许)</p>
|
||
<p>运行下面的代码可以启动一个服务,此付包含了一个共享队列,允许远程客户端访问:</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="kn">from</span> <span class="nn">multiprocessing.managers</span> <span class="kn">import</span> <span class="n">BaseManager</span>
|
||
<span class="gp">>>> </span><span class="kn">from</span> <span class="nn">queue</span> <span class="kn">import</span> <span class="n">Queue</span>
|
||
<span class="gp">>>> </span><span class="n">queue</span> <span class="o">=</span> <span class="n">Queue</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="k">class</span> <span class="nc">QueueManager</span><span class="p">(</span><span class="n">BaseManager</span><span class="p">):</span> <span class="k">pass</span>
|
||
<span class="gp">>>> </span><span class="n">QueueManager</span><span class="o">.</span><span class="n">register</span><span class="p">(</span><span class="s1">'get_queue'</span><span class="p">,</span> <span class="nb">callable</span><span class="o">=</span><span class="k">lambda</span><span class="p">:</span><span class="n">queue</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">m</span> <span class="o">=</span> <span class="n">QueueManager</span><span class="p">(</span><span class="n">address</span><span class="o">=</span><span class="p">(</span><span class="s1">''</span><span class="p">,</span> <span class="mi">50000</span><span class="p">),</span> <span class="n">authkey</span><span class="o">=</span><span class="sa">b</span><span class="s1">'abracadabra'</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">s</span> <span class="o">=</span> <span class="n">m</span><span class="o">.</span><span class="n">get_server</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="n">s</span><span class="o">.</span><span class="n">serve_forever</span><span class="p">()</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>远程客户端可以通过下面的方式访问服务:</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="kn">from</span> <span class="nn">multiprocessing.managers</span> <span class="kn">import</span> <span class="n">BaseManager</span>
|
||
<span class="gp">>>> </span><span class="k">class</span> <span class="nc">QueueManager</span><span class="p">(</span><span class="n">BaseManager</span><span class="p">):</span> <span class="k">pass</span>
|
||
<span class="gp">>>> </span><span class="n">QueueManager</span><span class="o">.</span><span class="n">register</span><span class="p">(</span><span class="s1">'get_queue'</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">m</span> <span class="o">=</span> <span class="n">QueueManager</span><span class="p">(</span><span class="n">address</span><span class="o">=</span><span class="p">(</span><span class="s1">'foo.bar.org'</span><span class="p">,</span> <span class="mi">50000</span><span class="p">),</span> <span class="n">authkey</span><span class="o">=</span><span class="sa">b</span><span class="s1">'abracadabra'</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">m</span><span class="o">.</span><span class="n">connect</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="n">queue</span> <span class="o">=</span> <span class="n">m</span><span class="o">.</span><span class="n">get_queue</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="n">queue</span><span class="o">.</span><span class="n">put</span><span class="p">(</span><span class="s1">'hello'</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>也可以通过下面的方式:</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="kn">from</span> <span class="nn">multiprocessing.managers</span> <span class="kn">import</span> <span class="n">BaseManager</span>
|
||
<span class="gp">>>> </span><span class="k">class</span> <span class="nc">QueueManager</span><span class="p">(</span><span class="n">BaseManager</span><span class="p">):</span> <span class="k">pass</span>
|
||
<span class="gp">>>> </span><span class="n">QueueManager</span><span class="o">.</span><span class="n">register</span><span class="p">(</span><span class="s1">'get_queue'</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">m</span> <span class="o">=</span> <span class="n">QueueManager</span><span class="p">(</span><span class="n">address</span><span class="o">=</span><span class="p">(</span><span class="s1">'foo.bar.org'</span><span class="p">,</span> <span class="mi">50000</span><span class="p">),</span> <span class="n">authkey</span><span class="o">=</span><span class="sa">b</span><span class="s1">'abracadabra'</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">m</span><span class="o">.</span><span class="n">connect</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="n">queue</span> <span class="o">=</span> <span class="n">m</span><span class="o">.</span><span class="n">get_queue</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="n">queue</span><span class="o">.</span><span class="n">get</span><span class="p">()</span>
|
||
<span class="go">'hello'</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>本地进程也可以访问这个队列,利用上面的客户端代码通过远程方式访问:</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="kn">from</span> <span class="nn">multiprocessing</span> <span class="kn">import</span> <span class="n">Process</span><span class="p">,</span> <span class="n">Queue</span>
|
||
<span class="gp">>>> </span><span class="kn">from</span> <span class="nn">multiprocessing.managers</span> <span class="kn">import</span> <span class="n">BaseManager</span>
|
||
<span class="gp">>>> </span><span class="k">class</span> <span class="nc">Worker</span><span class="p">(</span><span class="n">Process</span><span class="p">):</span>
|
||
<span class="gp">... </span> <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">q</span><span class="p">):</span>
|
||
<span class="gp">... </span> <span class="bp">self</span><span class="o">.</span><span class="n">q</span> <span class="o">=</span> <span class="n">q</span>
|
||
<span class="gp">... </span> <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">()</span>
|
||
<span class="gp">... </span> <span class="k">def</span> <span class="nf">run</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||
<span class="gp">... </span> <span class="bp">self</span><span class="o">.</span><span class="n">q</span><span class="o">.</span><span class="n">put</span><span class="p">(</span><span class="s1">'local hello'</span><span class="p">)</span>
|
||
<span class="gp">...</span>
|
||
<span class="gp">>>> </span><span class="n">queue</span> <span class="o">=</span> <span class="n">Queue</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="n">w</span> <span class="o">=</span> <span class="n">Worker</span><span class="p">(</span><span class="n">queue</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">w</span><span class="o">.</span><span class="n">start</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="k">class</span> <span class="nc">QueueManager</span><span class="p">(</span><span class="n">BaseManager</span><span class="p">):</span> <span class="k">pass</span>
|
||
<span class="gp">...</span>
|
||
<span class="gp">>>> </span><span class="n">QueueManager</span><span class="o">.</span><span class="n">register</span><span class="p">(</span><span class="s1">'get_queue'</span><span class="p">,</span> <span class="nb">callable</span><span class="o">=</span><span class="k">lambda</span><span class="p">:</span> <span class="n">queue</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">m</span> <span class="o">=</span> <span class="n">QueueManager</span><span class="p">(</span><span class="n">address</span><span class="o">=</span><span class="p">(</span><span class="s1">''</span><span class="p">,</span> <span class="mi">50000</span><span class="p">),</span> <span class="n">authkey</span><span class="o">=</span><span class="sa">b</span><span class="s1">'abracadabra'</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">s</span> <span class="o">=</span> <span class="n">m</span><span class="o">.</span><span class="n">get_server</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="n">s</span><span class="o">.</span><span class="n">serve_forever</span><span class="p">()</span>
|
||
</pre></div>
|
||
</div>
|
||
</section>
|
||
</section>
|
||
<section id="proxy-objects">
|
||
<span id="multiprocessing-proxy-objects"></span><h3>代理对象<a class="headerlink" href="#proxy-objects" title="永久链接至标题">¶</a></h3>
|
||
<p>代理是一个 <em>指向</em> 其他共享对象的对象,这个对象(很可能)在另外一个进程中。共享对象也可以说是代理 <em>指涉</em> 的对象。多个代理对象可能指向同一个指涉对象。</p>
|
||
<p>代理对象代理了指涉对象的一系列方法调用(虽然并不是指涉对象的每个方法都有必要被代理)。通过这种方式,代理的使用方法可以和它的指涉对象一样:</p>
|
||
<div class="highlight-pycon3 notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="kn">from</span> <span class="nn">multiprocessing</span> <span class="kn">import</span> <span class="n">Manager</span>
|
||
<span class="gp">>>> </span><span class="n">manager</span> <span class="o">=</span> <span class="n">Manager</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="n">l</span> <span class="o">=</span> <span class="n">manager</span><span class="o">.</span><span class="n">list</span><span class="p">([</span><span class="n">i</span><span class="o">*</span><span class="n">i</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="gp">>>> </span><span class="nb">print</span><span class="p">(</span><span class="n">l</span><span class="p">)</span>
|
||
<span class="go">[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]</span>
|
||
<span class="gp">>>> </span><span class="nb">print</span><span class="p">(</span><span class="nb">repr</span><span class="p">(</span><span class="n">l</span><span class="p">))</span>
|
||
<span class="go"><ListProxy object, typeid 'list' at 0x...></span>
|
||
<span class="gp">>>> </span><span class="n">l</span><span class="p">[</span><span class="mi">4</span><span class="p">]</span>
|
||
<span class="go">16</span>
|
||
<span class="gp">>>> </span><span class="n">l</span><span class="p">[</span><span class="mi">2</span><span class="p">:</span><span class="mi">5</span><span class="p">]</span>
|
||
<span class="go">[4, 9, 16]</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>注意,对代理使用 <a class="reference internal" href="stdtypes.html#str" title="str"><code class="xref py py-func docutils literal notranslate"><span class="pre">str()</span></code></a> 函数会返回指涉对象的字符串表示,但是 <a class="reference internal" href="functions.html#repr" title="repr"><code class="xref py py-func docutils literal notranslate"><span class="pre">repr()</span></code></a> 却会返回代理本身的内部字符串表示。</p>
|
||
<p>被代理的对象很重要的一点是必须可以被序列化,这样才能允许他们在进程间传递。因此,指涉对象可以包含 <a class="reference internal" href="#multiprocessing-proxy-objects"><span class="std std-ref">代理对象</span></a> 。这允许管理器中列表、字典或者其他 <a class="reference internal" href="#multiprocessing-proxy-objects"><span class="std std-ref">代理对象</span></a> 对象之间的嵌套。</p>
|
||
<div class="highlight-pycon3 notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">a</span> <span class="o">=</span> <span class="n">manager</span><span class="o">.</span><span class="n">list</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="n">b</span> <span class="o">=</span> <span class="n">manager</span><span class="o">.</span><span class="n">list</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="n">a</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">b</span><span class="p">)</span> <span class="c1"># referent of a now contains referent of b</span>
|
||
<span class="gp">>>> </span><span class="nb">print</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">)</span>
|
||
<span class="go">[<ListProxy object, typeid 'list' at ...>] []</span>
|
||
<span class="gp">>>> </span><span class="n">b</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s1">'hello'</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="nb">print</span><span class="p">(</span><span class="n">a</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">b</span><span class="p">)</span>
|
||
<span class="go">['hello'] ['hello']</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>类似地,字典和列表代理也可以相互嵌套:</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">l_outer</span> <span class="o">=</span> <span class="n">manager</span><span class="o">.</span><span class="n">list</span><span class="p">([</span> <span class="n">manager</span><span class="o">.</span><span class="n">dict</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">2</span><span class="p">)</span> <span class="p">])</span>
|
||
<span class="gp">>>> </span><span class="n">d_first_inner</span> <span class="o">=</span> <span class="n">l_outer</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
|
||
<span class="gp">>>> </span><span class="n">d_first_inner</span><span class="p">[</span><span class="s1">'a'</span><span class="p">]</span> <span class="o">=</span> <span class="mi">1</span>
|
||
<span class="gp">>>> </span><span class="n">d_first_inner</span><span class="p">[</span><span class="s1">'b'</span><span class="p">]</span> <span class="o">=</span> <span class="mi">2</span>
|
||
<span class="gp">>>> </span><span class="n">l_outer</span><span class="p">[</span><span class="mi">1</span><span class="p">][</span><span class="s1">'c'</span><span class="p">]</span> <span class="o">=</span> <span class="mi">3</span>
|
||
<span class="gp">>>> </span><span class="n">l_outer</span><span class="p">[</span><span class="mi">1</span><span class="p">][</span><span class="s1">'z'</span><span class="p">]</span> <span class="o">=</span> <span class="mi">26</span>
|
||
<span class="gp">>>> </span><span class="nb">print</span><span class="p">(</span><span class="n">l_outer</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>
|
||
<span class="go">{'a': 1, 'b': 2}</span>
|
||
<span class="gp">>>> </span><span class="nb">print</span><span class="p">(</span><span class="n">l_outer</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span>
|
||
<span class="go">{'c': 3, 'z': 26}</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>如果指涉对象包含了普通 <a class="reference internal" href="stdtypes.html#list" title="list"><code class="xref py py-class docutils literal notranslate"><span class="pre">list</span></code></a> 或 <a class="reference internal" href="stdtypes.html#dict" title="dict"><code class="xref py py-class docutils literal notranslate"><span class="pre">dict</span></code></a> 对象,对这些内部可变对象的修改不会通过管理器传播,因为代理无法得知被包含的值什么时候被修改了。但是把存放在容器代理中的值本身是会通过管理器传播的(会触发代理对象中的 <code class="docutils literal notranslate"><span class="pre">__setitem__</span></code> )从而有效修改这些对象,所以可以把修改过的值重新赋值给容器代理:</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="c1"># create a list proxy and append a mutable object (a dictionary)</span>
|
||
<span class="n">lproxy</span> <span class="o">=</span> <span class="n">manager</span><span class="o">.</span><span class="n">list</span><span class="p">()</span>
|
||
<span class="n">lproxy</span><span class="o">.</span><span class="n">append</span><span class="p">({})</span>
|
||
<span class="c1"># now mutate the dictionary</span>
|
||
<span class="n">d</span> <span class="o">=</span> <span class="n">lproxy</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
|
||
<span class="n">d</span><span class="p">[</span><span class="s1">'a'</span><span class="p">]</span> <span class="o">=</span> <span class="mi">1</span>
|
||
<span class="n">d</span><span class="p">[</span><span class="s1">'b'</span><span class="p">]</span> <span class="o">=</span> <span class="mi">2</span>
|
||
<span class="c1"># at this point, the changes to d are not yet synced, but by</span>
|
||
<span class="c1"># updating the dictionary, the proxy is notified of the change</span>
|
||
<span class="n">lproxy</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">d</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>在大多是使用情形下,这种实现方式并不比嵌套 <a class="reference internal" href="#multiprocessing-proxy-objects"><span class="std std-ref">代理对象</span></a> 方便,但是依然演示了对于同步的一种控制级别。</p>
|
||
<div class="admonition note">
|
||
<p class="admonition-title">注解</p>
|
||
<p><a class="reference internal" href="#module-multiprocessing" title="multiprocessing: Process-based parallelism."><code class="xref py py-mod docutils literal notranslate"><span class="pre">multiprocessing</span></code></a> 中的代理类并没有提供任何对于代理值比较的支持。所以,我们会得到如下结果:</p>
|
||
<div class="highlight-pycon3 notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">manager</span><span class="o">.</span><span class="n">list</span><span class="p">([</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">])</span> <span class="o">==</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">]</span>
|
||
<span class="go">False</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>当需要比较值的时候,应该替换为使用指涉对象的拷贝。</p>
|
||
</div>
|
||
<dl class="class">
|
||
<dt id="multiprocessing.managers.BaseProxy">
|
||
<em class="property">class </em><code class="sig-prename descclassname">multiprocessing.managers.</code><code class="sig-name descname">BaseProxy</code><a class="headerlink" href="#multiprocessing.managers.BaseProxy" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>代理对象是 <a class="reference internal" href="#multiprocessing.managers.BaseProxy" title="multiprocessing.managers.BaseProxy"><code class="xref py py-class docutils literal notranslate"><span class="pre">BaseProxy</span></code></a> 派生类的实例。</p>
|
||
<dl class="method">
|
||
<dt id="multiprocessing.managers.BaseProxy._callmethod">
|
||
<code class="sig-name descname">_callmethod</code><span class="sig-paren">(</span><em class="sig-param">methodname</em><span class="optional">[</span>, <em class="sig-param">args</em><span class="optional">[</span>, <em class="sig-param">kwds</em><span class="optional">]</span><span class="optional">]</span><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.managers.BaseProxy._callmethod" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>调用指涉对象的方法并返回结果。</p>
|
||
<p>如果 <code class="docutils literal notranslate"><span class="pre">proxy</span></code> 是一个代理且其指涉的是 <code class="docutils literal notranslate"><span class="pre">obj</span></code> , 那么下面的表达式:</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">proxy</span><span class="o">.</span><span class="n">_callmethod</span><span class="p">(</span><span class="n">methodname</span><span class="p">,</span> <span class="n">args</span><span class="p">,</span> <span class="n">kwds</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>相当于求取以下表达式的值:</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="nb">getattr</span><span class="p">(</span><span class="n">obj</span><span class="p">,</span> <span class="n">methodname</span><span class="p">)(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwds</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>于管理器进程。</p>
|
||
<p>返回结果会是一个值拷贝或者一个新的共享对象的代理 - 见函数 <a class="reference internal" href="#multiprocessing.managers.BaseManager.register" title="multiprocessing.managers.BaseManager.register"><code class="xref py py-meth docutils literal notranslate"><span class="pre">BaseManager.register()</span></code></a> 中关于参数 <em>method_to_typeid</em> 的文档。</p>
|
||
<p>如果这个调用熬出了异常,则这个异常会被 <a class="reference internal" href="#multiprocessing.managers.BaseProxy._callmethod" title="multiprocessing.managers.BaseProxy._callmethod"><code class="xref py py-meth docutils literal notranslate"><span class="pre">_callmethod()</span></code></a> 透传出来。如果是管理器进程本身抛出的一些其他异常,则会被 <a class="reference internal" href="#multiprocessing.managers.BaseProxy._callmethod" title="multiprocessing.managers.BaseProxy._callmethod"><code class="xref py py-meth docutils literal notranslate"><span class="pre">_callmethod()</span></code></a> 转换为 <code class="xref py py-exc docutils literal notranslate"><span class="pre">RemoteError</span></code> 异常重新抛出。</p>
|
||
<p>特别注意,如果 <em>methodname</em> 没有 <em>暴露</em> 出来,将会引发一个异常。</p>
|
||
<p><a class="reference internal" href="#multiprocessing.managers.BaseProxy._callmethod" title="multiprocessing.managers.BaseProxy._callmethod"><code class="xref py py-meth docutils literal notranslate"><span class="pre">_callmethod()</span></code></a> 的一个使用示例:</p>
|
||
<div class="highlight-pycon3 notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">l</span> <span class="o">=</span> <span class="n">manager</span><span class="o">.</span><span class="n">list</span><span class="p">(</span><span class="nb">range</span><span class="p">(</span><span class="mi">10</span><span class="p">))</span>
|
||
<span class="gp">>>> </span><span class="n">l</span><span class="o">.</span><span class="n">_callmethod</span><span class="p">(</span><span class="s1">'__len__'</span><span class="p">)</span>
|
||
<span class="go">10</span>
|
||
<span class="gp">>>> </span><span class="n">l</span><span class="o">.</span><span class="n">_callmethod</span><span class="p">(</span><span class="s1">'__getitem__'</span><span class="p">,</span> <span class="p">(</span><span class="nb">slice</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="mi">7</span><span class="p">),))</span> <span class="c1"># equivalent to l[2:7]</span>
|
||
<span class="go">[2, 3, 4, 5, 6]</span>
|
||
<span class="gp">>>> </span><span class="n">l</span><span class="o">.</span><span class="n">_callmethod</span><span class="p">(</span><span class="s1">'__getitem__'</span><span class="p">,</span> <span class="p">(</span><span class="mi">20</span><span class="p">,))</span> <span class="c1"># equivalent to l[20]</span>
|
||
<span class="gt">Traceback (most recent call last):</span>
|
||
<span class="c">...</span>
|
||
<span class="gr">IndexError</span>: <span class="n">list index out of range</span>
|
||
</pre></div>
|
||
</div>
|
||
</dd></dl>
|
||
|
||
<dl class="method">
|
||
<dt id="multiprocessing.managers.BaseProxy._getvalue">
|
||
<code class="sig-name descname">_getvalue</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.managers.BaseProxy._getvalue" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>返回指涉对象的一份拷贝。</p>
|
||
<p>如果指涉对象无法序列化,则会抛出一个异常。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="method">
|
||
<dt id="multiprocessing.managers.BaseProxy.__repr__">
|
||
<code class="sig-name descname">__repr__</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.managers.BaseProxy.__repr__" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>返回代理对象的内部字符串表示。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="method">
|
||
<dt id="multiprocessing.managers.BaseProxy.__str__">
|
||
<code class="sig-name descname">__str__</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.managers.BaseProxy.__str__" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>返回指涉对象的内部字符串表示。</p>
|
||
</dd></dl>
|
||
|
||
</dd></dl>
|
||
|
||
<section id="cleanup">
|
||
<h4>清理<a class="headerlink" href="#cleanup" title="永久链接至标题">¶</a></h4>
|
||
<p>代理对象使用了一个弱引用回调函数,当它被垃圾回收时,会将自己从拥有此指涉对象的管理器上反注册,</p>
|
||
<p>当共享对象没有被任何代理器引用时,会被管理器进程删除。</p>
|
||
</section>
|
||
</section>
|
||
<section id="module-multiprocessing.pool">
|
||
<span id="process-pools"></span><h3>进程池<a class="headerlink" href="#module-multiprocessing.pool" title="永久链接至标题">¶</a></h3>
|
||
<p>可以创建一个进程池,它将使用 <a class="reference internal" href="#multiprocessing.pool.Pool" title="multiprocessing.pool.Pool"><code class="xref py py-class docutils literal notranslate"><span class="pre">Pool</span></code></a> 类执行提交给它的任务。</p>
|
||
<dl class="class">
|
||
<dt id="multiprocessing.pool.Pool">
|
||
<em class="property">class </em><code class="sig-prename descclassname">multiprocessing.pool.</code><code class="sig-name descname">Pool</code><span class="sig-paren">(</span><span class="optional">[</span><em class="sig-param">processes</em><span class="optional">[</span>, <em class="sig-param">initializer</em><span class="optional">[</span>, <em class="sig-param">initargs</em><span class="optional">[</span>, <em class="sig-param">maxtasksperchild</em><span class="optional">[</span>, <em class="sig-param">context</em><span class="optional">]</span><span class="optional">]</span><span class="optional">]</span><span class="optional">]</span><span class="optional">]</span><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.pool.Pool" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>一个进程池对象,它控制可以提交作业的工作进程池。它支持带有超时和回调的异步结果,以及一个并行的 map 实现。</p>
|
||
<p><em>processes</em> 是要使用的工作进程数目。如果 <em>processes</em> 为 <code class="docutils literal notranslate"><span class="pre">None</span></code>,则使用 <a class="reference internal" href="os.html#os.cpu_count" title="os.cpu_count"><code class="xref py py-func docutils literal notranslate"><span class="pre">os.cpu_count()</span></code></a> 返回的值。</p>
|
||
<p>如果 <em>initializer</em> 不为 <code class="docutils literal notranslate"><span class="pre">None</span></code>,则每个工作进程将会在启动时调用 <code class="docutils literal notranslate"><span class="pre">initializer(*initargs)</span></code>。</p>
|
||
<p><em>maxtasksperchild</em> 是一个工作进程在它退出或被一个新的工作进程代替之前能完成的任务数量,为了释放未使用的资源。默认的 <em>maxtasksperchild</em> 是 <code class="docutils literal notranslate"><span class="pre">None</span></code>,意味着工作进程寿与池齐。</p>
|
||
<p><em>context</em> 可被用于指定启动的工作进程的上下文。通常一个进程池是使用函数 <code class="xref py py-func docutils literal notranslate"><span class="pre">multiprocessing.Pool()</span></code> 或者一个上下文对象的 <a class="reference internal" href="#multiprocessing.pool.Pool" title="multiprocessing.pool.Pool"><code class="xref py py-meth docutils literal notranslate"><span class="pre">Pool()</span></code></a> 方法创建的。在这两种情况下, <em>context</em> 都是适当设置的。</p>
|
||
<p>注意,进程池对象的方法只有创建它的进程能够调用。</p>
|
||
<div class="admonition warning">
|
||
<p class="admonition-title">警告</p>
|
||
<p><a class="reference internal" href="#module-multiprocessing.pool" title="multiprocessing.pool: Create pools of processes."><code class="xref py py-class docutils literal notranslate"><span class="pre">multiprocessing.pool</span></code></a> 对象具有需要正确管理的内部资源 (像任何其他资源一样),具体方式是将进程池用作上下文管理器,或者手动调用 <a class="reference internal" href="#multiprocessing.pool.Pool.close" title="multiprocessing.pool.Pool.close"><code class="xref py py-meth docutils literal notranslate"><span class="pre">close()</span></code></a> 和 <a class="reference internal" href="#multiprocessing.pool.Pool.terminate" title="multiprocessing.pool.Pool.terminate"><code class="xref py py-meth docutils literal notranslate"><span class="pre">terminate()</span></code></a>。 未做此类操作将导致进程在终结阶段挂起。</p>
|
||
<p>请注意依赖垃圾回收器来销毁进程池是 <strong>不正确</strong> 的做法,因为 CPython 并不保证会调用进程池终结程序(请参阅 <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">object.__del__()</span></code></a> 来了解详情)。</p>
|
||
</div>
|
||
<div class="versionadded">
|
||
<p><span class="versionmodified added">3.2 新版功能: </span><em>maxtasksperchild</em></p>
|
||
</div>
|
||
<div class="versionadded">
|
||
<p><span class="versionmodified added">3.4 新版功能: </span><em>context</em></p>
|
||
</div>
|
||
<div class="admonition note">
|
||
<p class="admonition-title">注解</p>
|
||
<p>通常来说,<a class="reference internal" href="#multiprocessing.pool.Pool" title="multiprocessing.pool.Pool"><code class="xref py py-class docutils literal notranslate"><span class="pre">Pool</span></code></a> 中的 Worker 进程的生命周期和进程池的工作队列一样长。一些其他系统中(如 Apache, mod_wsgi 等)也可以发现另一种模式,他们会让工作进程在完成一些任务后退出,清理、释放资源,然后启动一个新的进程代替旧的工作进程。 <a class="reference internal" href="#multiprocessing.pool.Pool" title="multiprocessing.pool.Pool"><code class="xref py py-class docutils literal notranslate"><span class="pre">Pool</span></code></a> 的 <em>maxtasksperchild</em> 参数给用户提供了这种能力。</p>
|
||
</div>
|
||
<dl class="method">
|
||
<dt id="multiprocessing.pool.Pool.apply">
|
||
<code class="sig-name descname">apply</code><span class="sig-paren">(</span><em class="sig-param">func</em><span class="optional">[</span>, <em class="sig-param">args</em><span class="optional">[</span>, <em class="sig-param">kwds</em><span class="optional">]</span><span class="optional">]</span><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.pool.Pool.apply" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>使用 <em>args</em> 参数以及 <em>kwds</em> 命名参数调用 <em>func</em> , 它会返回结果前阻塞。这种情况下,<a class="reference internal" href="#multiprocessing.pool.Pool.apply_async" title="multiprocessing.pool.Pool.apply_async"><code class="xref py py-meth docutils literal notranslate"><span class="pre">apply_async()</span></code></a> 更适合并行化工作。另外 <em>func</em> 只会在一个进程池中的一个工作进程中执行。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="method">
|
||
<dt id="multiprocessing.pool.Pool.apply_async">
|
||
<code class="sig-name descname">apply_async</code><span class="sig-paren">(</span><em class="sig-param">func</em><span class="optional">[</span>, <em class="sig-param">args</em><span class="optional">[</span>, <em class="sig-param">kwds</em><span class="optional">[</span>, <em class="sig-param">callback</em><span class="optional">[</span>, <em class="sig-param">error_callback</em><span class="optional">]</span><span class="optional">]</span><span class="optional">]</span><span class="optional">]</span><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.pool.Pool.apply_async" title="永久链接至目标">¶</a></dt>
|
||
<dd><p><a class="reference internal" href="#multiprocessing.pool.Pool.apply" title="multiprocessing.pool.Pool.apply"><code class="xref py py-meth docutils literal notranslate"><span class="pre">apply()</span></code></a> 方法的一个变种,返回一个 <a class="reference internal" href="#multiprocessing.pool.AsyncResult" title="multiprocessing.pool.AsyncResult"><code class="xref py py-class docutils literal notranslate"><span class="pre">AsyncResult</span></code></a> 对象。</p>
|
||
<p>如果指定了 <em>callback</em> , 它必须是一个接受单个参数的可调用对象。当执行成功时, <em>callback</em> 会被用于处理执行后的返回结果,否则,调用 <em>error_callback</em> 。</p>
|
||
<p>如果指定了 <em>error_callback</em> , 它必须是一个接受单个参数的可调用对象。当目标函数执行失败时, 会将抛出的异常对象作为参数传递给 <em>error_callback</em> 执行。</p>
|
||
<p>回调函数应该立即执行完成,否则会阻塞负责处理结果的线程。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="method">
|
||
<dt id="multiprocessing.pool.Pool.map">
|
||
<code class="sig-name descname">map</code><span class="sig-paren">(</span><em class="sig-param">func</em>, <em class="sig-param">iterable</em><span class="optional">[</span>, <em class="sig-param">chunksize</em><span class="optional">]</span><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.pool.Pool.map" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>内置 <a class="reference internal" href="functions.html#map" title="map"><code class="xref py py-func docutils literal notranslate"><span class="pre">map()</span></code></a> 函数的并行版本 (但它只支持一个 <em>iterable</em> 参数,对于多个可迭代对象请参阅 <a class="reference internal" href="#multiprocessing.pool.Pool.starmap" title="multiprocessing.pool.Pool.starmap"><code class="xref py py-meth docutils literal notranslate"><span class="pre">starmap()</span></code></a>)。 它会保持阻塞直到获得结果。</p>
|
||
<p>这个方法会将可迭代对象分割为许多块,然后提交给进程池。 可以将 <em>chunksize</em> 设置为一个正整数来指定每个块的(近似)大小。</p>
|
||
<p>注意对于很长的迭代对象,可能消耗很多内存。可以考虑使用 <a class="reference internal" href="#multiprocessing.pool.Pool.imap" title="multiprocessing.pool.Pool.imap"><code class="xref py py-meth docutils literal notranslate"><span class="pre">imap()</span></code></a> 或 <a class="reference internal" href="#multiprocessing.pool.Pool.imap_unordered" title="multiprocessing.pool.Pool.imap_unordered"><code class="xref py py-meth docutils literal notranslate"><span class="pre">imap_unordered()</span></code></a> 并且显式指定 <em>chunksize</em> 以提升效率。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="method">
|
||
<dt id="multiprocessing.pool.Pool.map_async">
|
||
<code class="sig-name descname">map_async</code><span class="sig-paren">(</span><em class="sig-param">func</em>, <em class="sig-param">iterable</em><span class="optional">[</span>, <em class="sig-param">chunksize</em><span class="optional">[</span>, <em class="sig-param">callback</em><span class="optional">[</span>, <em class="sig-param">error_callback</em><span class="optional">]</span><span class="optional">]</span><span class="optional">]</span><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.pool.Pool.map_async" title="永久链接至目标">¶</a></dt>
|
||
<dd><p><a class="reference internal" href="#multiprocessing.pool.Pool.map" title="multiprocessing.pool.Pool.map"><code class="xref py py-meth docutils literal notranslate"><span class="pre">map()</span></code></a> 方法的一个变种,返回一个 <a class="reference internal" href="#multiprocessing.pool.AsyncResult" title="multiprocessing.pool.AsyncResult"><code class="xref py py-class docutils literal notranslate"><span class="pre">AsyncResult</span></code></a> 对象。</p>
|
||
<p>如果指定了 <em>callback</em> , 它必须是一个接受单个参数的可调用对象。当执行成功时, <em>callback</em> 会被用于处理执行后的返回结果,否则,调用 <em>error_callback</em> 。</p>
|
||
<p>如果指定了 <em>error_callback</em> , 它必须是一个接受单个参数的可调用对象。当目标函数执行失败时, 会将抛出的异常对象作为参数传递给 <em>error_callback</em> 执行。</p>
|
||
<p>回调函数应该立即执行完成,否则会阻塞负责处理结果的线程。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="method">
|
||
<dt id="multiprocessing.pool.Pool.imap">
|
||
<code class="sig-name descname">imap</code><span class="sig-paren">(</span><em class="sig-param">func</em>, <em class="sig-param">iterable</em><span class="optional">[</span>, <em class="sig-param">chunksize</em><span class="optional">]</span><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.pool.Pool.imap" title="永久链接至目标">¶</a></dt>
|
||
<dd><p><a class="reference internal" href="#multiprocessing.pool.Pool.map" title="multiprocessing.pool.Pool.map"><code class="xref py py-meth docutils literal notranslate"><span class="pre">map()</span></code></a> 的延迟执行版本。</p>
|
||
<p><em>chunksize</em> 参数的作用和 <a class="reference internal" href="#multiprocessing.pool.Pool.map" title="multiprocessing.pool.Pool.map"><code class="xref py py-meth docutils literal notranslate"><span class="pre">map()</span></code></a> 方法的一样。对于很长的迭代器,给 <em>chunksize</em> 设置一个很大的值会比默认值 <code class="docutils literal notranslate"><span class="pre">1</span></code> <strong>极大</strong> 地加快执行速度。</p>
|
||
<p>同样,如果 <em>chunksize</em> 是 <code class="docutils literal notranslate"><span class="pre">1</span></code> , 那么 <a class="reference internal" href="#multiprocessing.pool.Pool.imap" title="multiprocessing.pool.Pool.imap"><code class="xref py py-meth docutils literal notranslate"><span class="pre">imap()</span></code></a> 方法所返回的迭代器的 <code class="xref py py-meth docutils literal notranslate"><span class="pre">next()</span></code> 方法拥有一个可选的 <em>timeout</em> 参数: 如果无法在 <em>timeout</em> 秒内执行得到结果,则 <code class="docutils literal notranslate"><span class="pre">next(timeout)</span></code> 会抛出 <a class="reference internal" href="#multiprocessing.TimeoutError" title="multiprocessing.TimeoutError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">multiprocessing.TimeoutError</span></code></a> 异常。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="method">
|
||
<dt id="multiprocessing.pool.Pool.imap_unordered">
|
||
<code class="sig-name descname">imap_unordered</code><span class="sig-paren">(</span><em class="sig-param">func</em>, <em class="sig-param">iterable</em><span class="optional">[</span>, <em class="sig-param">chunksize</em><span class="optional">]</span><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.pool.Pool.imap_unordered" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>和 <a class="reference internal" href="#multiprocessing.pool.Pool.imap" title="multiprocessing.pool.Pool.imap"><code class="xref py py-meth docutils literal notranslate"><span class="pre">imap()</span></code></a> 相同,只不过通过迭代器返回的结果是任意的。(当进程池中只有一个工作进程的时候,返回结果的顺序才能认为是"有序"的)</p>
|
||
</dd></dl>
|
||
|
||
<dl class="method">
|
||
<dt id="multiprocessing.pool.Pool.starmap">
|
||
<code class="sig-name descname">starmap</code><span class="sig-paren">(</span><em class="sig-param">func</em>, <em class="sig-param">iterable</em><span class="optional">[</span>, <em class="sig-param">chunksize</em><span class="optional">]</span><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.pool.Pool.starmap" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>和 <a class="reference internal" href="functions.html#map" title="map"><code class="xref py py-meth docutils literal notranslate"><span class="pre">map()</span></code></a> 类似,不过 <em>iterable</em> 中的每一项会被解包再作为函数参数。</p>
|
||
<p>比如可迭代对象 <code class="docutils literal notranslate"><span class="pre">[(1,2),</span> <span class="pre">(3,</span> <span class="pre">4)]</span></code> 会转化为等价于 <code class="docutils literal notranslate"><span class="pre">[func(1,2),</span> <span class="pre">func(3,4)]</span></code> 的调用。</p>
|
||
<div class="versionadded">
|
||
<p><span class="versionmodified added">3.3 新版功能.</span></p>
|
||
</div>
|
||
</dd></dl>
|
||
|
||
<dl class="method">
|
||
<dt id="multiprocessing.pool.Pool.starmap_async">
|
||
<code class="sig-name descname">starmap_async</code><span class="sig-paren">(</span><em class="sig-param">func</em>, <em class="sig-param">iterable</em><span class="optional">[</span>, <em class="sig-param">chunksize</em><span class="optional">[</span>, <em class="sig-param">callback</em><span class="optional">[</span>, <em class="sig-param">error_callback</em><span class="optional">]</span><span class="optional">]</span><span class="optional">]</span><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.pool.Pool.starmap_async" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>相当于 <a class="reference internal" href="#multiprocessing.pool.Pool.starmap" title="multiprocessing.pool.Pool.starmap"><code class="xref py py-meth docutils literal notranslate"><span class="pre">starmap()</span></code></a> 与 <a class="reference internal" href="#multiprocessing.pool.Pool.map_async" title="multiprocessing.pool.Pool.map_async"><code class="xref py py-meth docutils literal notranslate"><span class="pre">map_async()</span></code></a> 的结合,迭代 <em>iterable</em> 的每一项,解包作为 <em>func</em> 的参数并执行,返回用于获取结果的对象。</p>
|
||
<div class="versionadded">
|
||
<p><span class="versionmodified added">3.3 新版功能.</span></p>
|
||
</div>
|
||
</dd></dl>
|
||
|
||
<dl class="method">
|
||
<dt id="multiprocessing.pool.Pool.close">
|
||
<code class="sig-name descname">close</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.pool.Pool.close" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>阻止后续任务提交到进程池,当所有任务执行完成后,工作进程会退出。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="method">
|
||
<dt id="multiprocessing.pool.Pool.terminate">
|
||
<code class="sig-name descname">terminate</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.pool.Pool.terminate" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>不必等待未完成的任务,立即停止工作进程。当进程池对象被垃圾回收时,会立即调用 <a class="reference internal" href="#multiprocessing.pool.Pool.terminate" title="multiprocessing.pool.Pool.terminate"><code class="xref py py-meth docutils literal notranslate"><span class="pre">terminate()</span></code></a>。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="method">
|
||
<dt id="multiprocessing.pool.Pool.join">
|
||
<code class="sig-name descname">join</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.pool.Pool.join" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>等待工作进程结束。调用 <a class="reference internal" href="#multiprocessing.pool.Pool.join" title="multiprocessing.pool.Pool.join"><code class="xref py py-meth docutils literal notranslate"><span class="pre">join()</span></code></a> 前必须先调用 <a class="reference internal" href="#multiprocessing.pool.Pool.close" title="multiprocessing.pool.Pool.close"><code class="xref py py-meth docutils literal notranslate"><span class="pre">close()</span></code></a> 或者 <a class="reference internal" href="#multiprocessing.pool.Pool.terminate" title="multiprocessing.pool.Pool.terminate"><code class="xref py py-meth docutils literal notranslate"><span class="pre">terminate()</span></code></a> 。</p>
|
||
</dd></dl>
|
||
|
||
<div class="versionadded">
|
||
<p><span class="versionmodified added">3.3 新版功能: </span>进程池对象现在支持上下文管理器协议 - 参见 <a class="reference internal" href="stdtypes.html#typecontextmanager"><span class="std std-ref">上下文管理器类型</span></a> 。<a class="reference internal" href="stdtypes.html#contextmanager.__enter__" title="contextmanager.__enter__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__enter__()</span></code></a> 返回进程池对象, <a class="reference internal" href="stdtypes.html#contextmanager.__exit__" title="contextmanager.__exit__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__exit__()</span></code></a> 会调用 <a class="reference internal" href="#multiprocessing.pool.Pool.terminate" title="multiprocessing.pool.Pool.terminate"><code class="xref py py-meth docutils literal notranslate"><span class="pre">terminate()</span></code></a> 。</p>
|
||
</div>
|
||
</dd></dl>
|
||
|
||
<dl class="class">
|
||
<dt id="multiprocessing.pool.AsyncResult">
|
||
<em class="property">class </em><code class="sig-prename descclassname">multiprocessing.pool.</code><code class="sig-name descname">AsyncResult</code><a class="headerlink" href="#multiprocessing.pool.AsyncResult" title="永久链接至目标">¶</a></dt>
|
||
<dd><p><a class="reference internal" href="#multiprocessing.pool.Pool.apply_async" title="multiprocessing.pool.Pool.apply_async"><code class="xref py py-meth docutils literal notranslate"><span class="pre">Pool.apply_async()</span></code></a> 和 <a class="reference internal" href="#multiprocessing.pool.Pool.map_async" title="multiprocessing.pool.Pool.map_async"><code class="xref py py-meth docutils literal notranslate"><span class="pre">Pool.map_async()</span></code></a> 返回对象所属的类。</p>
|
||
<dl class="method">
|
||
<dt id="multiprocessing.pool.AsyncResult.get">
|
||
<code class="sig-name descname">get</code><span class="sig-paren">(</span><span class="optional">[</span><em class="sig-param">timeout</em><span class="optional">]</span><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.pool.AsyncResult.get" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>用于获取执行结果。如果 <em>timeout</em> 不是 <code class="docutils literal notranslate"><span class="pre">None</span></code> 并且在 <em>timeout</em> 秒内仍然没有执行完得到结果,则抛出 <a class="reference internal" href="#multiprocessing.TimeoutError" title="multiprocessing.TimeoutError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">multiprocessing.TimeoutError</span></code></a> 异常。如果远程调用发生异常,这个异常会通过 <a class="reference internal" href="#multiprocessing.pool.AsyncResult.get" title="multiprocessing.pool.AsyncResult.get"><code class="xref py py-meth docutils literal notranslate"><span class="pre">get()</span></code></a> 重新抛出。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="method">
|
||
<dt id="multiprocessing.pool.AsyncResult.wait">
|
||
<code class="sig-name descname">wait</code><span class="sig-paren">(</span><span class="optional">[</span><em class="sig-param">timeout</em><span class="optional">]</span><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.pool.AsyncResult.wait" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>阻塞,直到返回结果,或者 <em>timeout</em> 秒后超时。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="method">
|
||
<dt id="multiprocessing.pool.AsyncResult.ready">
|
||
<code class="sig-name descname">ready</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.pool.AsyncResult.ready" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>返回执行状态,是否已经完成。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="method">
|
||
<dt id="multiprocessing.pool.AsyncResult.successful">
|
||
<code class="sig-name descname">successful</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.pool.AsyncResult.successful" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>判断调用是否已经完成并且未引发异常。 如果还未获得结果则将引发 <a class="reference internal" href="exceptions.html#ValueError" title="ValueError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">ValueError</span></code></a>。</p>
|
||
<div class="versionchanged">
|
||
<p><span class="versionmodified changed">在 3.7 版更改: </span>如果没有执行完,会抛出 <a class="reference internal" href="exceptions.html#ValueError" title="ValueError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">ValueError</span></code></a> 异常而不是 <a class="reference internal" href="exceptions.html#AssertionError" title="AssertionError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">AssertionError</span></code></a> 。</p>
|
||
</div>
|
||
</dd></dl>
|
||
|
||
</dd></dl>
|
||
|
||
<p>下面的例子演示了进程池的用法:</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">multiprocessing</span> <span class="kn">import</span> <span class="n">Pool</span>
|
||
<span class="kn">import</span> <span class="nn">time</span>
|
||
|
||
<span class="k">def</span> <span class="nf">f</span><span class="p">(</span><span class="n">x</span><span class="p">):</span>
|
||
<span class="k">return</span> <span class="n">x</span><span class="o">*</span><span class="n">x</span>
|
||
|
||
<span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s1">'__main__'</span><span class="p">:</span>
|
||
<span class="k">with</span> <span class="n">Pool</span><span class="p">(</span><span class="n">processes</span><span class="o">=</span><span class="mi">4</span><span class="p">)</span> <span class="k">as</span> <span class="n">pool</span><span class="p">:</span> <span class="c1"># start 4 worker processes</span>
|
||
<span class="n">result</span> <span class="o">=</span> <span class="n">pool</span><span class="o">.</span><span class="n">apply_async</span><span class="p">(</span><span class="n">f</span><span class="p">,</span> <span class="p">(</span><span class="mi">10</span><span class="p">,))</span> <span class="c1"># evaluate "f(10)" asynchronously in a single process</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="n">result</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">timeout</span><span class="o">=</span><span class="mi">1</span><span class="p">))</span> <span class="c1"># prints "100" unless your computer is *very* slow</span>
|
||
|
||
<span class="nb">print</span><span class="p">(</span><span class="n">pool</span><span class="o">.</span><span class="n">map</span><span class="p">(</span><span class="n">f</span><span class="p">,</span> <span class="nb">range</span><span class="p">(</span><span class="mi">10</span><span class="p">)))</span> <span class="c1"># prints "[0, 1, 4,..., 81]"</span>
|
||
|
||
<span class="n">it</span> <span class="o">=</span> <span class="n">pool</span><span class="o">.</span><span class="n">imap</span><span class="p">(</span><span class="n">f</span><span class="p">,</span> <span class="nb">range</span><span class="p">(</span><span class="mi">10</span><span class="p">))</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="nb">next</span><span class="p">(</span><span class="n">it</span><span class="p">))</span> <span class="c1"># prints "0"</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="nb">next</span><span class="p">(</span><span class="n">it</span><span class="p">))</span> <span class="c1"># prints "1"</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="n">it</span><span class="o">.</span><span class="n">next</span><span class="p">(</span><span class="n">timeout</span><span class="o">=</span><span class="mi">1</span><span class="p">))</span> <span class="c1"># prints "4" unless your computer is *very* slow</span>
|
||
|
||
<span class="n">result</span> <span class="o">=</span> <span class="n">pool</span><span class="o">.</span><span class="n">apply_async</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="p">(</span><span class="mi">10</span><span class="p">,))</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="n">result</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">timeout</span><span class="o">=</span><span class="mi">1</span><span class="p">))</span> <span class="c1"># raises multiprocessing.TimeoutError</span>
|
||
</pre></div>
|
||
</div>
|
||
</section>
|
||
<section id="module-multiprocessing.connection">
|
||
<span id="listeners-and-clients"></span><span id="multiprocessing-listeners-clients"></span><h3>监听器及客户端<a class="headerlink" href="#module-multiprocessing.connection" title="永久链接至标题">¶</a></h3>
|
||
<p>通常情况下,进程间通过队列或者 <a class="reference internal" href="#multiprocessing.Pipe" title="multiprocessing.Pipe"><code class="xref py py-func docutils literal notranslate"><span class="pre">Pipe()</span></code></a> 返回的 <a class="reference internal" href="#multiprocessing.connection.Connection" title="multiprocessing.connection.Connection"><code class="xref py py-class docutils literal notranslate"><span class="pre">Connection</span></code></a> 传递消息。</p>
|
||
<p>不过,<a class="reference internal" href="#module-multiprocessing.connection" title="multiprocessing.connection: API for dealing with sockets."><code class="xref py py-mod docutils literal notranslate"><span class="pre">multiprocessing.connection</span></code></a> 模块其实提供了一些更灵活的特性。最基础的用法是通过它抽象出来的高级API来操作socket或者Windows命名管道。也提供一些高级用法,如通过 <a class="reference internal" href="hmac.html#module-hmac" title="hmac: Keyed-Hashing for Message Authentication (HMAC) implementation"><code class="xref py py-mod docutils literal notranslate"><span class="pre">hmac</span></code></a> 模块来支持 <em>摘要认证</em>,以及同时监听多个管道连接。</p>
|
||
<dl class="function">
|
||
<dt id="multiprocessing.connection.deliver_challenge">
|
||
<code class="sig-prename descclassname">multiprocessing.connection.</code><code class="sig-name descname">deliver_challenge</code><span class="sig-paren">(</span><em class="sig-param">connection</em>, <em class="sig-param">authkey</em><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.connection.deliver_challenge" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>发送一个随机生成的消息到另一端,并等待回复。</p>
|
||
<p>如果收到的回复与使用 <em>authkey</em> 作为键生成的信息摘要匹配成功,就会发送一个欢迎信息给管道另一端。否则抛出 <a class="reference internal" href="#multiprocessing.AuthenticationError" title="multiprocessing.AuthenticationError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">AuthenticationError</span></code></a> 异常。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="function">
|
||
<dt id="multiprocessing.connection.answer_challenge">
|
||
<code class="sig-prename descclassname">multiprocessing.connection.</code><code class="sig-name descname">answer_challenge</code><span class="sig-paren">(</span><em class="sig-param">connection</em>, <em class="sig-param">authkey</em><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.connection.answer_challenge" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>接收一条信息,使用 <em>authkey</em> 作为键计算信息摘要,然后将摘要发送回去。</p>
|
||
<p>如果没有收到欢迎消息,就抛出 <a class="reference internal" href="#multiprocessing.AuthenticationError" title="multiprocessing.AuthenticationError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">AuthenticationError</span></code></a> 异常。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="function">
|
||
<dt id="multiprocessing.connection.Client">
|
||
<code class="sig-prename descclassname">multiprocessing.connection.</code><code class="sig-name descname">Client</code><span class="sig-paren">(</span><em class="sig-param">address</em><span class="optional">[</span>, <em class="sig-param">family</em><span class="optional">[</span>, <em class="sig-param">authkey</em><span class="optional">]</span><span class="optional">]</span><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.connection.Client" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>尝试使用 <em>address</em> 地址上的监听器建立一个连接,返回 <a class="reference internal" href="#multiprocessing.connection.Connection" title="multiprocessing.connection.Connection"><code class="xref py py-class docutils literal notranslate"><span class="pre">Connection</span></code></a> 。</p>
|
||
<p>连接的类型取决于 <em>family</em> 参数,但是通常可以省略,因为可以通过 <em>address</em> 的格式推导出来。(查看 <a class="reference internal" href="#multiprocessing-address-formats"><span class="std std-ref">地址格式</span></a> )</p>
|
||
<p>如果提供了 <em>authkey</em> 参数并且不是 None,那它必须是一个字符串并且会被当做基于 HMAC 认证的密钥。如果 <em>authkey</em> 是None 则不会有认证行为。认证失败抛出 <a class="reference internal" href="#multiprocessing.AuthenticationError" title="multiprocessing.AuthenticationError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">AuthenticationError</span></code></a> 异常,请查看 See <a class="reference internal" href="#multiprocessing-auth-keys"><span class="std std-ref">认证密码</span></a> 。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="class">
|
||
<dt id="multiprocessing.connection.Listener">
|
||
<em class="property">class </em><code class="sig-prename descclassname">multiprocessing.connection.</code><code class="sig-name descname">Listener</code><span class="sig-paren">(</span><span class="optional">[</span><em class="sig-param">address</em><span class="optional">[</span>, <em class="sig-param">family</em><span class="optional">[</span>, <em class="sig-param">backlog</em><span class="optional">[</span>, <em class="sig-param">authkey</em><span class="optional">]</span><span class="optional">]</span><span class="optional">]</span><span class="optional">]</span><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.connection.Listener" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>可以监听连接请求,是对于绑定套接字或者 Windows 命名管道的封装。</p>
|
||
<p><em>address</em> 是监听器对象中的绑定套接字或命名管道使用的地址。</p>
|
||
<div class="admonition note">
|
||
<p class="admonition-title">注解</p>
|
||
<p>如果使用 '0.0.0.0' 作为监听地址,那么在Windows上这个地址无法建立连接。想要建立一个可连接的端点,应该使用 '127.0.0.1' 。</p>
|
||
</div>
|
||
<p><em>family</em> 是套接字(或者命名管道)使用的类型。它可以是以下一种: <code class="docutils literal notranslate"><span class="pre">'AF_INET'</span></code> ( TCP 套接字类型), <code class="docutils literal notranslate"><span class="pre">'AF_UNIX'</span></code> ( Unix 域套接字) 或者 <code class="docutils literal notranslate"><span class="pre">'AF_PIPE'</span></code> ( Windows 命名管道)。其中只有第一个保证各平台可用。如果 <em>family</em> 是 <code class="docutils literal notranslate"><span class="pre">None</span></code> ,那么 family 会根据 <em>address</em> 的格式自动推导出来。如果 <em>address</em> 也是 <code class="docutils literal notranslate"><span class="pre">None</span></code> , 则取默认值。默认值为可用类型中速度最快的。见 <a class="reference internal" href="#multiprocessing-address-formats"><span class="std std-ref">地址格式</span></a> 。注意,如果 <em>family</em> 是 <code class="docutils literal notranslate"><span class="pre">'AF_UNIX'</span></code> 而address是 <code class="docutils literal notranslate"><span class="pre">None</span></code> ,套接字会在一个 <a class="reference internal" href="tempfile.html#tempfile.mkstemp" title="tempfile.mkstemp"><code class="xref py py-func docutils literal notranslate"><span class="pre">tempfile.mkstemp()</span></code></a> 创建的私有临时目录中创建。</p>
|
||
<p>如果监听器对象使用了套接字,<em>backlog</em> (默认值为1) 会在套接字绑定后传递给它的 <a class="reference internal" href="socket.html#socket.socket.listen" title="socket.socket.listen"><code class="xref py py-meth docutils literal notranslate"><span class="pre">listen()</span></code></a> 方法。</p>
|
||
<p>如果提供了 <em>authkey</em> 参数并且不是 None,那它必须是一个字符串并且会被当做基于 HMAC 认证的密钥。如果 <em>authkey</em> 是None 则不会有认证行为。认证失败抛出 <a class="reference internal" href="#multiprocessing.AuthenticationError" title="multiprocessing.AuthenticationError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">AuthenticationError</span></code></a> 异常,请查看 See <a class="reference internal" href="#multiprocessing-auth-keys"><span class="std std-ref">认证密码</span></a> 。</p>
|
||
<dl class="method">
|
||
<dt id="multiprocessing.connection.Listener.accept">
|
||
<code class="sig-name descname">accept</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.connection.Listener.accept" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>接受一个连接并返回一个 <a class="reference internal" href="#multiprocessing.connection.Connection" title="multiprocessing.connection.Connection"><code class="xref py py-class docutils literal notranslate"><span class="pre">Connection</span></code></a> 对象,其连接到的监听器对象已绑定套接字或者命名管道。如果已经尝试过认证并且失败了,则会抛出 <a class="reference internal" href="#multiprocessing.AuthenticationError" title="multiprocessing.AuthenticationError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">AuthenticationError</span></code></a> 异常。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="method">
|
||
<dt id="multiprocessing.connection.Listener.close">
|
||
<code class="sig-name descname">close</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.connection.Listener.close" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>关闭监听器对象上的绑定套接字或者命名管道。此函数会在监听器被垃圾回收后自动调用。不过仍然建议显式调用函数关闭。</p>
|
||
</dd></dl>
|
||
|
||
<p>监听器对象拥有下列只读属性:</p>
|
||
<dl class="attribute">
|
||
<dt id="multiprocessing.connection.Listener.address">
|
||
<code class="sig-name descname">address</code><a class="headerlink" href="#multiprocessing.connection.Listener.address" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>监听器对象使用的地址。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="attribute">
|
||
<dt id="multiprocessing.connection.Listener.last_accepted">
|
||
<code class="sig-name descname">last_accepted</code><a class="headerlink" href="#multiprocessing.connection.Listener.last_accepted" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>最后一个连接所使用的地址。如果没有的话就是 <code class="docutils literal notranslate"><span class="pre">None</span></code> 。</p>
|
||
</dd></dl>
|
||
|
||
<div class="versionadded">
|
||
<p><span class="versionmodified added">3.3 新版功能: </span>监听器对象现在支持了上下文管理协议 - 见 <a class="reference internal" href="stdtypes.html#typecontextmanager"><span class="std std-ref">上下文管理器类型</span></a> 。 <a class="reference internal" href="stdtypes.html#contextmanager.__enter__" title="contextmanager.__enter__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__enter__()</span></code></a> 返回一个监听器对象, <a class="reference internal" href="stdtypes.html#contextmanager.__exit__" title="contextmanager.__exit__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__exit__()</span></code></a> 会调用 <a class="reference internal" href="#multiprocessing.connection.Listener.close" title="multiprocessing.connection.Listener.close"><code class="xref py py-meth docutils literal notranslate"><span class="pre">close()</span></code></a> 。</p>
|
||
</div>
|
||
</dd></dl>
|
||
|
||
<dl class="function">
|
||
<dt id="multiprocessing.connection.wait">
|
||
<code class="sig-prename descclassname">multiprocessing.connection.</code><code class="sig-name descname">wait</code><span class="sig-paren">(</span><em class="sig-param">object_list</em>, <em class="sig-param">timeout=None</em><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.connection.wait" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>一直等待直到 <em>object_list</em> 中某个对象处于就绪状态。返回 <em>object_list</em> 中处于就绪状态的对象。如果 <em>timeout</em> 是一个浮点型,该方法会最多阻塞这么多秒。如果 <em>timeout</em> 是 <code class="docutils literal notranslate"><span class="pre">None</span></code> ,则会允许阻塞的事件没有限制。timeout为负数的情况下和为0的情况相同。</p>
|
||
<p>对于 Unix 和 Windows ,满足下列条件的对象可以出现在 <em>object_list</em> 中</p>
|
||
<ul class="simple">
|
||
<li><p>可读的 <a class="reference internal" href="#multiprocessing.connection.Connection" title="multiprocessing.connection.Connection"><code class="xref py py-class docutils literal notranslate"><span class="pre">Connection</span></code></a> 对象;</p></li>
|
||
<li><p>一个已连接并且可读的 <a class="reference internal" href="socket.html#socket.socket" title="socket.socket"><code class="xref py py-class docutils literal notranslate"><span class="pre">socket.socket</span></code></a> 对象;或者</p></li>
|
||
<li><p><a class="reference internal" href="#multiprocessing.Process" title="multiprocessing.Process"><code class="xref py py-class docutils literal notranslate"><span class="pre">Process</span></code></a> 对象中的 <a class="reference internal" href="#multiprocessing.Process.sentinel" title="multiprocessing.Process.sentinel"><code class="xref py py-attr docutils literal notranslate"><span class="pre">sentinel</span></code></a> 属性。</p></li>
|
||
</ul>
|
||
<p>当一个连接或者套接字对象拥有有效的数据可被读取的时候,或者另一端关闭后,这个对象就处于就绪状态。</p>
|
||
<p><strong>Unix</strong>: <code class="docutils literal notranslate"><span class="pre">wait(object_list,</span> <span class="pre">timeout)</span></code> 和 <code class="docutils literal notranslate"><span class="pre">select.select(object_list,</span> <span class="pre">[],</span> <span class="pre">[],</span> <span class="pre">timeout)</span></code> 几乎相同。差别在于,如果 <a class="reference internal" href="select.html#select.select" title="select.select"><code class="xref py py-func docutils literal notranslate"><span class="pre">select.select()</span></code></a> 被信号中断,它会抛出一个附带错误号为 <code class="docutils literal notranslate"><span class="pre">EINTR</span></code> 的 <a class="reference internal" href="exceptions.html#OSError" title="OSError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">OSError</span></code></a> 异常,而 <a class="reference internal" href="#multiprocessing.connection.wait" title="multiprocessing.connection.wait"><code class="xref py py-func docutils literal notranslate"><span class="pre">wait()</span></code></a> 不会。</p>
|
||
<p><strong>Windows</strong>: <em>object_list</em> 中的元素必须是一个表示为整数的可等待的句柄(按照 Win32 函数 <code class="docutils literal notranslate"><span class="pre">WaitForMultipleObjects()</span></code> 的文档中所定义) 或者一个拥有 <code class="xref py py-meth docutils literal notranslate"><span class="pre">fileno()</span></code> 方法的对象,这个对象返回一个套接字句柄或者管道句柄。(注意管道和套接字两种句柄 <strong>不是</strong> 可等待的句柄)</p>
|
||
<div class="versionadded">
|
||
<p><span class="versionmodified added">3.3 新版功能.</span></p>
|
||
</div>
|
||
</dd></dl>
|
||
|
||
<p><strong>示例</strong></p>
|
||
<p>下面的服务代码创建了一个使用 <code class="docutils literal notranslate"><span class="pre">'secret</span> <span class="pre">password'</span></code> 作为认证密码的监听器。它会等待连接然后发送一些数据给客户端:</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">multiprocessing.connection</span> <span class="kn">import</span> <span class="n">Listener</span>
|
||
<span class="kn">from</span> <span class="nn">array</span> <span class="kn">import</span> <span class="n">array</span>
|
||
|
||
<span class="n">address</span> <span class="o">=</span> <span class="p">(</span><span class="s1">'localhost'</span><span class="p">,</span> <span class="mi">6000</span><span class="p">)</span> <span class="c1"># family is deduced to be 'AF_INET'</span>
|
||
|
||
<span class="k">with</span> <span class="n">Listener</span><span class="p">(</span><span class="n">address</span><span class="p">,</span> <span class="n">authkey</span><span class="o">=</span><span class="sa">b</span><span class="s1">'secret password'</span><span class="p">)</span> <span class="k">as</span> <span class="n">listener</span><span class="p">:</span>
|
||
<span class="k">with</span> <span class="n">listener</span><span class="o">.</span><span class="n">accept</span><span class="p">()</span> <span class="k">as</span> <span class="n">conn</span><span class="p">:</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="s1">'connection accepted from'</span><span class="p">,</span> <span class="n">listener</span><span class="o">.</span><span class="n">last_accepted</span><span class="p">)</span>
|
||
|
||
<span class="n">conn</span><span class="o">.</span><span class="n">send</span><span class="p">([</span><span class="mf">2.25</span><span class="p">,</span> <span class="kc">None</span><span class="p">,</span> <span class="s1">'junk'</span><span class="p">,</span> <span class="nb">float</span><span class="p">])</span>
|
||
|
||
<span class="n">conn</span><span class="o">.</span><span class="n">send_bytes</span><span class="p">(</span><span class="sa">b</span><span class="s1">'hello'</span><span class="p">)</span>
|
||
|
||
<span class="n">conn</span><span class="o">.</span><span class="n">send_bytes</span><span class="p">(</span><span class="n">array</span><span class="p">(</span><span class="s1">'i'</span><span class="p">,</span> <span class="p">[</span><span class="mi">42</span><span class="p">,</span> <span class="mi">1729</span><span class="p">]))</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>下面的代码连接到服务然后从服务器上j接收一些数据:</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">multiprocessing.connection</span> <span class="kn">import</span> <span class="n">Client</span>
|
||
<span class="kn">from</span> <span class="nn">array</span> <span class="kn">import</span> <span class="n">array</span>
|
||
|
||
<span class="n">address</span> <span class="o">=</span> <span class="p">(</span><span class="s1">'localhost'</span><span class="p">,</span> <span class="mi">6000</span><span class="p">)</span>
|
||
|
||
<span class="k">with</span> <span class="n">Client</span><span class="p">(</span><span class="n">address</span><span class="p">,</span> <span class="n">authkey</span><span class="o">=</span><span class="sa">b</span><span class="s1">'secret password'</span><span class="p">)</span> <span class="k">as</span> <span class="n">conn</span><span class="p">:</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="n">conn</span><span class="o">.</span><span class="n">recv</span><span class="p">())</span> <span class="c1"># => [2.25, None, 'junk', float]</span>
|
||
|
||
<span class="nb">print</span><span class="p">(</span><span class="n">conn</span><span class="o">.</span><span class="n">recv_bytes</span><span class="p">())</span> <span class="c1"># => 'hello'</span>
|
||
|
||
<span class="n">arr</span> <span class="o">=</span> <span class="n">array</span><span class="p">(</span><span class="s1">'i'</span><span class="p">,</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">])</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="n">conn</span><span class="o">.</span><span class="n">recv_bytes_into</span><span class="p">(</span><span class="n">arr</span><span class="p">))</span> <span class="c1"># => 8</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="n">arr</span><span class="p">)</span> <span class="c1"># => array('i', [42, 1729, 0, 0, 0])</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>下面的代码使用了 <a class="reference internal" href="#multiprocessing.connection.wait" title="multiprocessing.connection.wait"><code class="xref py py-func docutils literal notranslate"><span class="pre">wait()</span></code></a> ,以便在同时等待多个进程发来消息。</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">time</span><span class="o">,</span> <span class="nn">random</span>
|
||
<span class="kn">from</span> <span class="nn">multiprocessing</span> <span class="kn">import</span> <span class="n">Process</span><span class="p">,</span> <span class="n">Pipe</span><span class="p">,</span> <span class="n">current_process</span>
|
||
<span class="kn">from</span> <span class="nn">multiprocessing.connection</span> <span class="kn">import</span> <span class="n">wait</span>
|
||
|
||
<span class="k">def</span> <span class="nf">foo</span><span class="p">(</span><span class="n">w</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">w</span><span class="o">.</span><span class="n">send</span><span class="p">((</span><span class="n">i</span><span class="p">,</span> <span class="n">current_process</span><span class="p">()</span><span class="o">.</span><span class="n">name</span><span class="p">))</span>
|
||
<span class="n">w</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
|
||
|
||
<span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s1">'__main__'</span><span class="p">:</span>
|
||
<span class="n">readers</span> <span class="o">=</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">4</span><span class="p">):</span>
|
||
<span class="n">r</span><span class="p">,</span> <span class="n">w</span> <span class="o">=</span> <span class="n">Pipe</span><span class="p">(</span><span class="n">duplex</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span>
|
||
<span class="n">readers</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">r</span><span class="p">)</span>
|
||
<span class="n">p</span> <span class="o">=</span> <span class="n">Process</span><span class="p">(</span><span class="n">target</span><span class="o">=</span><span class="n">foo</span><span class="p">,</span> <span class="n">args</span><span class="o">=</span><span class="p">(</span><span class="n">w</span><span class="p">,))</span>
|
||
<span class="n">p</span><span class="o">.</span><span class="n">start</span><span class="p">()</span>
|
||
<span class="c1"># We close the writable end of the pipe now to be sure that</span>
|
||
<span class="c1"># p is the only process which owns a handle for it. This</span>
|
||
<span class="c1"># ensures that when p closes its handle for the writable end,</span>
|
||
<span class="c1"># wait() will promptly report the readable end as being ready.</span>
|
||
<span class="n">w</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
|
||
|
||
<span class="k">while</span> <span class="n">readers</span><span class="p">:</span>
|
||
<span class="k">for</span> <span class="n">r</span> <span class="ow">in</span> <span class="n">wait</span><span class="p">(</span><span class="n">readers</span><span class="p">):</span>
|
||
<span class="k">try</span><span class="p">:</span>
|
||
<span class="n">msg</span> <span class="o">=</span> <span class="n">r</span><span class="o">.</span><span class="n">recv</span><span class="p">()</span>
|
||
<span class="k">except</span> <span class="ne">EOFError</span><span class="p">:</span>
|
||
<span class="n">readers</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">r</span><span class="p">)</span>
|
||
<span class="k">else</span><span class="p">:</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="n">msg</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
<section id="address-formats">
|
||
<span id="multiprocessing-address-formats"></span><h4>地址格式<a class="headerlink" href="#address-formats" title="永久链接至标题">¶</a></h4>
|
||
<ul class="simple">
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">'AF_INET'</span></code> 地址是 <code class="docutils literal notranslate"><span class="pre">(hostname,</span> <span class="pre">port)</span></code> 形式的元组类型,其中 <em>hostname</em> 是一个字符串,<em>port</em> 是整数。</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">'AF_UNIX'</span></code> 地址是文件系统上文件名的字符串。</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">'AF_PIPE'</span></code> 地址是一个 <code class="samp docutils literal notranslate"><span class="pre">r'\.\pipe{PipeName}'</span></code> 形式的字符串。 要使用 <a class="reference internal" href="#multiprocessing.connection.Client" title="multiprocessing.connection.Client"><code class="xref py py-func docutils literal notranslate"><span class="pre">Client()</span></code></a> 来连接到远程计算机上一个名为 <em>ServerName</em> 的命名管道,则应当改用 <code class="samp docutils literal notranslate"><span class="pre">r'\</span><em><span class="pre">ServerName</span></em><span class="pre">\pipe{PipeName}'</span></code> 形式的地址。</p></li>
|
||
</ul>
|
||
<p>注意,使用两个反斜线开头的字符串默认被当做 <code class="docutils literal notranslate"><span class="pre">'AF_PIPE'</span></code> 地址而不是 <code class="docutils literal notranslate"><span class="pre">'AF_UNIX'</span></code> 地址。</p>
|
||
</section>
|
||
</section>
|
||
<section id="authentication-keys">
|
||
<span id="multiprocessing-auth-keys"></span><h3>认证密码<a class="headerlink" href="#authentication-keys" title="永久链接至标题">¶</a></h3>
|
||
<p>当使用 <a class="reference internal" href="#multiprocessing.connection.Connection.recv" title="multiprocessing.connection.Connection.recv"><code class="xref py py-meth docutils literal notranslate"><span class="pre">Connection.recv</span></code></a> 接收数据时,数据会自动被反序列化。不幸的是,对于一个不可信的数据源发来的数据,反序列化是存在安全风险的。所以 <a class="reference internal" href="#multiprocessing.connection.Listener" title="multiprocessing.connection.Listener"><code class="xref py py-class docutils literal notranslate"><span class="pre">Listener</span></code></a> 和 <a class="reference internal" href="#multiprocessing.connection.Client" title="multiprocessing.connection.Client"><code class="xref py py-func docutils literal notranslate"><span class="pre">Client()</span></code></a> 之间使用 <a class="reference internal" href="hmac.html#module-hmac" title="hmac: Keyed-Hashing for Message Authentication (HMAC) implementation"><code class="xref py py-mod docutils literal notranslate"><span class="pre">hmac</span></code></a> 模块进行摘要认证。</p>
|
||
<p>认证密钥是一个 byte 类型的字符串,可以认为是和密码一样的东西,连接建立好后,双方都会要求另一方证明知道认证密钥。(这个证明过程不会通过连接发送密钥)</p>
|
||
<p>如果要求认证但是没有指定认证密钥,则会使用 <code class="docutils literal notranslate"><span class="pre">current_process().authkey</span></code> 的返回值 (参见 <a class="reference internal" href="#multiprocessing.Process" title="multiprocessing.Process"><code class="xref py py-class docutils literal notranslate"><span class="pre">Process</span></code></a>)。 这个值将被当前进程所创建的任何 <a class="reference internal" href="#multiprocessing.Process" title="multiprocessing.Process"><code class="xref py py-class docutils literal notranslate"><span class="pre">Process</span></code></a> 对象自动继承。 这意味着 (在默认情况下) 一个包含多进程的程序中的所有进程会在相互间建立连接的时候共享单个认证密钥。</p>
|
||
<p><a class="reference internal" href="os.html#os.urandom" title="os.urandom"><code class="xref py py-func docutils literal notranslate"><span class="pre">os.urandom()</span></code></a> 也可以用来生成合适的认证密钥。</p>
|
||
</section>
|
||
<section id="logging">
|
||
<h3>日志记录<a class="headerlink" href="#logging" title="永久链接至标题">¶</a></h3>
|
||
<p>当前模块也提供了一些对 logging 的支持。注意, <a class="reference internal" href="logging.html#module-logging" title="logging: Flexible event logging system for applications."><code class="xref py py-mod docutils literal notranslate"><span class="pre">logging</span></code></a> 模块本身并没有使用进程间共享的锁,所以来自于多个进程的日志可能(具体取决于使用的日志 handler 类型)相互覆盖或者混杂。</p>
|
||
<dl class="function">
|
||
<dt id="multiprocessing.get_logger">
|
||
<code class="sig-prename descclassname">multiprocessing.</code><code class="sig-name descname">get_logger</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.get_logger" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>返回 <a class="reference internal" href="#module-multiprocessing" title="multiprocessing: Process-based parallelism."><code class="xref py py-mod docutils literal notranslate"><span class="pre">multiprocessing</span></code></a> 使用的 logger,必要的话会创建一个新的。</p>
|
||
<p>如果创建的首个 logger 日志级别为 <code class="xref py py-data docutils literal notranslate"><span class="pre">logging.NOTSET</span></code> 并且没有默认 handler。通过这个 logger 打印的消息不会传递到根 logger。</p>
|
||
<p>注意在 Windows 上,子进程只会继承父进程 logger 的日志级别 - 对于logger的其他自定义项不会继承。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="function">
|
||
<dt id="multiprocessing.log_to_stderr">
|
||
<code class="sig-prename descclassname">multiprocessing.</code><code class="sig-name descname">log_to_stderr</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.log_to_stderr" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>此函数会调用 <a class="reference internal" href="#multiprocessing.get_logger" title="multiprocessing.get_logger"><code class="xref py py-func docutils literal notranslate"><span class="pre">get_logger()</span></code></a> 但是会在返回的 logger 上增加一个 handler,将所有输出都使用 <code class="docutils literal notranslate"><span class="pre">'[%(levelname)s/%(processName)s]</span> <span class="pre">%(message)s'</span></code> 的格式发送到 <a class="reference internal" href="sys.html#sys.stderr" title="sys.stderr"><code class="xref py py-data docutils literal notranslate"><span class="pre">sys.stderr</span></code></a> 。</p>
|
||
</dd></dl>
|
||
|
||
<p>下面是一个在交互式解释器中打开日志功能的例子:</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="kn">import</span> <span class="nn">multiprocessing</span><span class="o">,</span> <span class="nn">logging</span>
|
||
<span class="gp">>>> </span><span class="n">logger</span> <span class="o">=</span> <span class="n">multiprocessing</span><span class="o">.</span><span class="n">log_to_stderr</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="n">logger</span><span class="o">.</span><span class="n">setLevel</span><span class="p">(</span><span class="n">logging</span><span class="o">.</span><span class="n">INFO</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">logger</span><span class="o">.</span><span class="n">warning</span><span class="p">(</span><span class="s1">'doomed'</span><span class="p">)</span>
|
||
<span class="go">[WARNING/MainProcess] doomed</span>
|
||
<span class="gp">>>> </span><span class="n">m</span> <span class="o">=</span> <span class="n">multiprocessing</span><span class="o">.</span><span class="n">Manager</span><span class="p">()</span>
|
||
<span class="go">[INFO/SyncManager-...] child process calling self.run()</span>
|
||
<span class="go">[INFO/SyncManager-...] created temp directory /.../pymp-...</span>
|
||
<span class="go">[INFO/SyncManager-...] manager serving at '/.../listener-...'</span>
|
||
<span class="gp">>>> </span><span class="k">del</span> <span class="n">m</span>
|
||
<span class="go">[INFO/MainProcess] sending shutdown message to manager</span>
|
||
<span class="go">[INFO/SyncManager-...] manager exiting with exitcode 0</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>要查看日志等级的完整列表,见 <a class="reference internal" href="logging.html#module-logging" title="logging: Flexible event logging system for applications."><code class="xref py py-mod docutils literal notranslate"><span class="pre">logging</span></code></a> 模块。</p>
|
||
</section>
|
||
<section id="module-multiprocessing.dummy">
|
||
<span id="the-multiprocessing-dummy-module"></span><h3><a class="reference internal" href="#module-multiprocessing.dummy" title="multiprocessing.dummy: Dumb wrapper around threading."><code class="xref py py-mod docutils literal notranslate"><span class="pre">multiprocessing.dummy</span></code></a> 模块<a class="headerlink" href="#module-multiprocessing.dummy" title="永久链接至标题">¶</a></h3>
|
||
<p><a class="reference internal" href="#module-multiprocessing.dummy" title="multiprocessing.dummy: Dumb wrapper around threading."><code class="xref py py-mod docutils literal notranslate"><span class="pre">multiprocessing.dummy</span></code></a> 复制了 <a class="reference internal" href="#module-multiprocessing" title="multiprocessing: Process-based parallelism."><code class="xref py py-mod docutils literal notranslate"><span class="pre">multiprocessing</span></code></a> 的 API,不过是在 <a class="reference internal" href="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> 模块之上包装了一层。</p>
|
||
<p>特别地,<a class="reference internal" href="#module-multiprocessing.dummy" title="multiprocessing.dummy: Dumb wrapper around threading."><code class="xref py py-mod docutils literal notranslate"><span class="pre">multiprocessing.dummy</span></code></a> 所提供的 <code class="docutils literal notranslate"><span class="pre">Pool</span></code> 函数会返回一个 <a class="reference internal" href="#multiprocessing.pool.ThreadPool" title="multiprocessing.pool.ThreadPool"><code class="xref py py-class docutils literal notranslate"><span class="pre">ThreadPool</span></code></a> 的实例,该类是 <a class="reference internal" href="#multiprocessing.pool.Pool" title="multiprocessing.pool.Pool"><code class="xref py py-class docutils literal notranslate"><span class="pre">Pool</span></code></a> 的子类,它支持所有相同的方法调用但会使用一个工作线程池而非工作进程池。</p>
|
||
<dl class="class">
|
||
<dt id="multiprocessing.pool.ThreadPool">
|
||
<em class="property">class </em><code class="sig-prename descclassname">multiprocessing.pool.</code><code class="sig-name descname">ThreadPool</code><span class="sig-paren">(</span><span class="optional">[</span><em class="sig-param">processes</em><span class="optional">[</span>, <em class="sig-param">initializer</em><span class="optional">[</span>, <em class="sig-param">initargs</em><span class="optional">]</span><span class="optional">]</span><span class="optional">]</span><span class="sig-paren">)</span><a class="headerlink" href="#multiprocessing.pool.ThreadPool" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>一个线程池对象,用来控制可向其提交任务的工作线程池。 <a class="reference internal" href="#multiprocessing.pool.ThreadPool" title="multiprocessing.pool.ThreadPool"><code class="xref py py-class docutils literal notranslate"><span class="pre">ThreadPool</span></code></a> 实例与 <a class="reference internal" href="#multiprocessing.pool.Pool" title="multiprocessing.pool.Pool"><code class="xref py py-class docutils literal notranslate"><span class="pre">Pool</span></code></a> 实例是完全接口兼容的,并且它们的资源也必须被正确地管理,或者是将线程池作为上下文管理器来使用,或者是通过手动调用 <a class="reference internal" href="#multiprocessing.pool.Pool.close" title="multiprocessing.pool.Pool.close"><code class="xref py py-meth docutils literal notranslate"><span class="pre">close()</span></code></a> 和 <a class="reference internal" href="#multiprocessing.pool.Pool.terminate" title="multiprocessing.pool.Pool.terminate"><code class="xref py py-meth docutils literal notranslate"><span class="pre">terminate()</span></code></a>。</p>
|
||
<p><em>processes</em> 是要使用的工作线程数目。 如果 <em>processes</em> 为 <code class="docutils literal notranslate"><span class="pre">None</span></code>,则使用 <a class="reference internal" href="os.html#os.cpu_count" title="os.cpu_count"><code class="xref py py-func docutils literal notranslate"><span class="pre">os.cpu_count()</span></code></a> 返回的值。</p>
|
||
<p>如果 <em>initializer</em> 不为 <code class="docutils literal notranslate"><span class="pre">None</span></code>,则每个工作进程将会在启动时调用 <code class="docutils literal notranslate"><span class="pre">initializer(*initargs)</span></code>。</p>
|
||
<p>不同于 <a class="reference internal" href="#multiprocessing.pool.Pool" title="multiprocessing.pool.Pool"><code class="xref py py-class docutils literal notranslate"><span class="pre">Pool</span></code></a>,<em>maxtasksperchild</em> 和 <em>context</em> 不可被提供。</p>
|
||
<blockquote>
|
||
<div><div class="admonition note">
|
||
<p class="admonition-title">注解</p>
|
||
<p><a class="reference internal" href="#multiprocessing.pool.ThreadPool" title="multiprocessing.pool.ThreadPool"><code class="xref py py-class docutils literal notranslate"><span class="pre">ThreadPool</span></code></a> 具有与 <a class="reference internal" href="#multiprocessing.pool.Pool" title="multiprocessing.pool.Pool"><code class="xref py py-class docutils literal notranslate"><span class="pre">Pool</span></code></a> 相同的接口,它围绕一个进程池进行设计并且先于 <a class="reference internal" href="concurrent.futures.html#module-concurrent.futures" title="concurrent.futures: Execute computations concurrently using threads or processes."><code class="xref py py-class docutils literal notranslate"><span class="pre">concurrent.futures</span></code></a> 模块的引入。 因此,它继承了一些对于基于线程的池来说没有意义的操作,并且它具有自己的用于表示异步任务状态的类型 <a class="reference internal" href="#multiprocessing.pool.AsyncResult" title="multiprocessing.pool.AsyncResult"><code class="xref py py-class docutils literal notranslate"><span class="pre">AsyncResult</span></code></a>,该类型不为任何其他库所知。</p>
|
||
<p>用户通常应该倾向于使用 <a class="reference internal" href="concurrent.futures.html#concurrent.futures.ThreadPoolExecutor" title="concurrent.futures.ThreadPoolExecutor"><code class="xref py py-class docutils literal notranslate"><span class="pre">concurrent.futures.ThreadPoolExecutor</span></code></a>,它拥有从一开始就围绕线程进行设计的更简单接口,并且返回与许多其他库相兼容的 <a class="reference internal" href="concurrent.futures.html#concurrent.futures.Future" title="concurrent.futures.Future"><code class="xref py py-class docutils literal notranslate"><span class="pre">concurrent.futures.Future</span></code></a> 实例,包括 <a class="reference internal" href="asyncio.html#module-asyncio" title="asyncio: Asynchronous I/O."><code class="xref py py-mod docutils literal notranslate"><span class="pre">asyncio</span></code></a> 库。</p>
|
||
</div>
|
||
</div></blockquote>
|
||
</dd></dl>
|
||
|
||
</section>
|
||
</section>
|
||
<section id="programming-guidelines">
|
||
<span id="multiprocessing-programming"></span><h2>编程指导<a class="headerlink" href="#programming-guidelines" title="永久链接至标题">¶</a></h2>
|
||
<p>使用 <a class="reference internal" href="#module-multiprocessing" title="multiprocessing: Process-based parallelism."><code class="xref py py-mod docutils literal notranslate"><span class="pre">multiprocessing</span></code></a> 时,应遵循一些指导原则和习惯用法。</p>
|
||
<section id="all-start-methods">
|
||
<h3>所有start方法<a class="headerlink" href="#all-start-methods" title="永久链接至标题">¶</a></h3>
|
||
<p>下面这些适用于所有start方法。</p>
|
||
<p>避免共享状态</p>
|
||
<blockquote>
|
||
<div><p>应该尽可能避免在进程间传递大量数据,越少越好。</p>
|
||
<p>最好坚持使用队列或者管道进行进程间通信,而不是底层的同步原语。</p>
|
||
</div></blockquote>
|
||
<p>可序列化</p>
|
||
<blockquote>
|
||
<div><p>保证所代理的方法的参数是可以序列化的。</p>
|
||
</div></blockquote>
|
||
<p>代理的线程安全性</p>
|
||
<blockquote>
|
||
<div><p>不要在多线程中同时使用一个代理对象,除非你用锁保护它。</p>
|
||
<p>(而在不同进程中使用 <em>相同</em> 的代理对象却没有问题。)</p>
|
||
</div></blockquote>
|
||
<p>使用 Join 避免僵尸进程</p>
|
||
<blockquote>
|
||
<div><p>在 Unix 上,如果一个进程执行完成但是没有被 join,就会变成僵尸进程。一般来说,僵尸进程不会很多,因为每次新启动进程(或者 <a class="reference internal" href="#multiprocessing.active_children" title="multiprocessing.active_children"><code class="xref py py-func docutils literal notranslate"><span class="pre">active_children()</span></code></a> 被调用)时,所有已执行完成且没有被 join 的进程都会自动被 join,而且对一个执行完的进程调用 <a class="reference internal" href="#multiprocessing.Process.is_alive" title="multiprocessing.Process.is_alive"><code class="xref py py-meth docutils literal notranslate"><span class="pre">Process.is_alive</span></code></a> 也会 join 这个进程。尽管如此,对自己启动的进程显式调用 join 依然是最佳实践。</p>
|
||
</div></blockquote>
|
||
<p>继承优于序列化、反序列化</p>
|
||
<blockquote>
|
||
<div><p>当使用 <em>spawn</em> 或者 <em>forkserver</em> 的启动方式时,<a class="reference internal" href="#module-multiprocessing" title="multiprocessing: Process-based parallelism."><code class="xref py py-mod docutils literal notranslate"><span class="pre">multiprocessing</span></code></a> 中的许多类型都必须是可序列化的,这样子进程才能使用它们。但是通常我们都应该避免使用管道和队列发送共享对象到另外一个进程,而是重新组织代码,对于其他进程创建出来的共享对象,让那些需要访问这些对象的子进程可以直接将这些对象从父进程继承过来。</p>
|
||
</div></blockquote>
|
||
<p>避免杀死进程</p>
|
||
<blockquote>
|
||
<div><p>通过 <a class="reference internal" href="#multiprocessing.Process.terminate" title="multiprocessing.Process.terminate"><code class="xref py py-meth docutils literal notranslate"><span class="pre">Process.terminate</span></code></a> 停止一个进程很容易导致这个进程正在使用的共享资源(如锁、信号量、管道和队列)损坏或者变得不可用,无法在其他进程中继续使用。</p>
|
||
<p>所以,最好只对那些从来不使用共享资源的进程调用 <a class="reference internal" href="#multiprocessing.Process.terminate" title="multiprocessing.Process.terminate"><code class="xref py py-meth docutils literal notranslate"><span class="pre">Process.terminate</span></code></a> 。</p>
|
||
</div></blockquote>
|
||
<p>Join 使用队列的进程</p>
|
||
<blockquote>
|
||
<div><p>记住,往队列放入数据的进程会一直等待直到队列中所有项被"feeder" 线程传给底层管道。(子进程可以调用队列的 <a class="reference internal" href="#multiprocessing.Queue.cancel_join_thread" title="multiprocessing.Queue.cancel_join_thread"><code class="xref py py-meth docutils literal notranslate"><span class="pre">Queue.cancel_join_thread</span></code></a> 方法禁止这种行为)</p>
|
||
<p>这意味着,任何使用队列的时候,你都要确保在进程join之前,所有存放到队列中的项将会被其他进程、线程完全消费。否则不能保证这个写过队列的进程可以正常终止。记住非精灵进程会自动 join 。</p>
|
||
<p>下面是一个会导致死锁的例子:</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">multiprocessing</span> <span class="kn">import</span> <span class="n">Process</span><span class="p">,</span> <span class="n">Queue</span>
|
||
|
||
<span class="k">def</span> <span class="nf">f</span><span class="p">(</span><span class="n">q</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="s1">'X'</span> <span class="o">*</span> <span class="mi">1000000</span><span class="p">)</span>
|
||
|
||
<span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s1">'__main__'</span><span class="p">:</span>
|
||
<span class="n">queue</span> <span class="o">=</span> <span class="n">Queue</span><span class="p">()</span>
|
||
<span class="n">p</span> <span class="o">=</span> <span class="n">Process</span><span class="p">(</span><span class="n">target</span><span class="o">=</span><span class="n">f</span><span class="p">,</span> <span class="n">args</span><span class="o">=</span><span class="p">(</span><span class="n">queue</span><span class="p">,))</span>
|
||
<span class="n">p</span><span class="o">.</span><span class="n">start</span><span class="p">()</span>
|
||
<span class="n">p</span><span class="o">.</span><span class="n">join</span><span class="p">()</span> <span class="c1"># this deadlocks</span>
|
||
<span class="n">obj</span> <span class="o">=</span> <span class="n">queue</span><span class="o">.</span><span class="n">get</span><span class="p">()</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>交换最后两行可以修复这个问题(或者直接删掉 <code class="docutils literal notranslate"><span class="pre">p.join()</span></code>)。</p>
|
||
</div></blockquote>
|
||
<p>显式传递资源给子进程</p>
|
||
<blockquote>
|
||
<div><p>在Unix上,使用 <em>fork</em> 方式启动的子进程可以使用父进程中全局创建的共享资源。不过,最好是显式将资源对象通过参数的形式传递给子进程。</p>
|
||
<p>除了(部分原因)让代码兼容 Windows 以及其他的进程启动方式外,这种形式还保证了在子进程生命期这个对象是不会被父进程垃圾回收的。如果父进程中的某些对象被垃圾回收会导致资源释放,这就变得很重要。</p>
|
||
<p>所以对于实例:</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">multiprocessing</span> <span class="kn">import</span> <span class="n">Process</span><span class="p">,</span> <span class="n">Lock</span>
|
||
|
||
<span class="k">def</span> <span class="nf">f</span><span class="p">():</span>
|
||
<span class="o">...</span> <span class="n">do</span> <span class="n">something</span> <span class="n">using</span> <span class="s2">"lock"</span> <span class="o">...</span>
|
||
|
||
<span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s1">'__main__'</span><span class="p">:</span>
|
||
<span class="n">lock</span> <span class="o">=</span> <span class="n">Lock</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">Process</span><span class="p">(</span><span class="n">target</span><span class="o">=</span><span class="n">f</span><span class="p">)</span><span class="o">.</span><span class="n">start</span><span class="p">()</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>应当重写成这样:</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">multiprocessing</span> <span class="kn">import</span> <span class="n">Process</span><span class="p">,</span> <span class="n">Lock</span>
|
||
|
||
<span class="k">def</span> <span class="nf">f</span><span class="p">(</span><span class="n">l</span><span class="p">):</span>
|
||
<span class="o">...</span> <span class="n">do</span> <span class="n">something</span> <span class="n">using</span> <span class="s2">"l"</span> <span class="o">...</span>
|
||
|
||
<span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s1">'__main__'</span><span class="p">:</span>
|
||
<span class="n">lock</span> <span class="o">=</span> <span class="n">Lock</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">Process</span><span class="p">(</span><span class="n">target</span><span class="o">=</span><span class="n">f</span><span class="p">,</span> <span class="n">args</span><span class="o">=</span><span class="p">(</span><span class="n">lock</span><span class="p">,))</span><span class="o">.</span><span class="n">start</span><span class="p">()</span>
|
||
</pre></div>
|
||
</div>
|
||
</div></blockquote>
|
||
<p>谨防将 <a class="reference internal" href="sys.html#sys.stdin" title="sys.stdin"><code class="xref py py-data docutils literal notranslate"><span class="pre">sys.stdin</span></code></a> 数据替换为 “类似文件的对象”</p>
|
||
<blockquote>
|
||
<div><p><a class="reference internal" href="#module-multiprocessing" title="multiprocessing: Process-based parallelism."><code class="xref py py-mod docutils literal notranslate"><span class="pre">multiprocessing</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">sys</span><span class="o">.</span><span class="n">stdin</span><span class="o">.</span><span class="n">fileno</span><span class="p">())</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>在 <code class="xref py py-meth docutils literal notranslate"><span class="pre">multiprocessing.Process._bootstrap()</span></code> 方法中 —— 这会导致与"进程中的进程"相关的一些问题。这已经被修改成了:</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">sys</span><span class="o">.</span><span class="n">stdin</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
|
||
<span class="n">sys</span><span class="o">.</span><span class="n">stdin</span> <span class="o">=</span> <span class="nb">open</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">open</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">devnull</span><span class="p">,</span> <span class="n">os</span><span class="o">.</span><span class="n">O_RDONLY</span><span class="p">),</span> <span class="n">closefd</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>它解决了进程相互冲突导致文件描述符错误的根本问题,但是对使用带缓冲的“文件型对象”替换 <a class="reference internal" href="sys.html#sys.stdin" title="sys.stdin"><code class="xref py py-func docutils literal notranslate"><span class="pre">sys.stdin()</span></code></a> 作为输出的应用程序造成了潜在的危险。如果多个进程调用了此文件型对象的 <a class="reference internal" href="io.html#io.IOBase.close" title="io.IOBase.close"><code class="xref py py-meth docutils literal notranslate"><span class="pre">close()</span></code></a> 方法,会导致相同的数据多次刷写到此对象,损坏数据。</p>
|
||
<p>如果你写入文件型对象并实现了自己的缓存,可以在每次追加缓存数据时记录当前进程id,从而将其变成 fork 安全的,当发现进程id变化后舍弃之前的缓存,例如:</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="nd">@property</span>
|
||
<span class="k">def</span> <span class="nf">cache</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||
<span class="n">pid</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">getpid</span><span class="p">()</span>
|
||
<span class="k">if</span> <span class="n">pid</span> <span class="o">!=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_pid</span><span class="p">:</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">_pid</span> <span class="o">=</span> <span class="n">pid</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">_cache</span> <span class="o">=</span> <span class="p">[]</span>
|
||
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_cache</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>需要更多信息,请查看 <a class="reference external" href="https://bugs.python.org/issue?@action=redirect&bpo=5155">bpo-5155</a>, <a class="reference external" href="https://bugs.python.org/issue?@action=redirect&bpo=5313">bpo-5313</a> 以及 <a class="reference external" href="https://bugs.python.org/issue?@action=redirect&bpo=5331">bpo-5331</a></p>
|
||
</div></blockquote>
|
||
</section>
|
||
<section id="the-spawn-and-forkserver-start-methods">
|
||
<h3><em>spawn</em> 和 <em>forkserver</em> 启动方式<a class="headerlink" href="#the-spawn-and-forkserver-start-methods" title="永久链接至标题">¶</a></h3>
|
||
<p>相对于 <em>fork</em> 启动方式,有一些额外的限制。</p>
|
||
<p>更依赖序列化</p>
|
||
<blockquote>
|
||
<div><p><code class="xref py py-meth docutils literal notranslate"><span class="pre">Process.__init__()</span></code> 的所有参数都必须可序列化。同样的,当你继承 <a class="reference internal" href="#multiprocessing.Process" title="multiprocessing.Process"><code class="xref py py-class docutils literal notranslate"><span class="pre">Process</span></code></a> 时,需要保证当调用 <a class="reference internal" href="#multiprocessing.Process.start" title="multiprocessing.Process.start"><code class="xref py py-meth docutils literal notranslate"><span class="pre">Process.start</span></code></a> 方法时,实例可以被序列化。</p>
|
||
</div></blockquote>
|
||
<p>全局变量</p>
|
||
<blockquote>
|
||
<div><p>记住,如果子进程中的代码尝试访问一个全局变量,它所看到的值(如果有)可能和父进程中执行 <a class="reference internal" href="#multiprocessing.Process.start" title="multiprocessing.Process.start"><code class="xref py py-meth docutils literal notranslate"><span class="pre">Process.start</span></code></a> 那一刻的值不一样。</p>
|
||
<p>当全局变量只是模块级别的常量时,是不会有问题的。</p>
|
||
</div></blockquote>
|
||
<p>安全导入主模块</p>
|
||
<blockquote>
|
||
<div><p>确保主模块可以被新启动的Python解释器安全导入而不会引发什么副作用(比如又启动了一个子进程)</p>
|
||
<p>例如,使用 <em>spawn</em> 或 <em>forkserver</em> 启动方式执行下面的模块,会引发 <a class="reference internal" href="exceptions.html#RuntimeError" title="RuntimeError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">RuntimeError</span></code></a> 异常而失败。</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">multiprocessing</span> <span class="kn">import</span> <span class="n">Process</span>
|
||
|
||
<span class="k">def</span> <span class="nf">foo</span><span class="p">():</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="s1">'hello'</span><span class="p">)</span>
|
||
|
||
<span class="n">p</span> <span class="o">=</span> <span class="n">Process</span><span class="p">(</span><span class="n">target</span><span class="o">=</span><span class="n">foo</span><span class="p">)</span>
|
||
<span class="n">p</span><span class="o">.</span><span class="n">start</span><span class="p">()</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>应该通过下面的方法使用 <code class="docutils literal notranslate"><span class="pre">if</span> <span class="pre">__name__</span> <span class="pre">==</span> <span class="pre">'__main__':</span></code> ,从而保护程序"入口点":</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">multiprocessing</span> <span class="kn">import</span> <span class="n">Process</span><span class="p">,</span> <span class="n">freeze_support</span><span class="p">,</span> <span class="n">set_start_method</span>
|
||
|
||
<span class="k">def</span> <span class="nf">foo</span><span class="p">():</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="s1">'hello'</span><span class="p">)</span>
|
||
|
||
<span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s1">'__main__'</span><span class="p">:</span>
|
||
<span class="n">freeze_support</span><span class="p">()</span>
|
||
<span class="n">set_start_method</span><span class="p">(</span><span class="s1">'spawn'</span><span class="p">)</span>
|
||
<span class="n">p</span> <span class="o">=</span> <span class="n">Process</span><span class="p">(</span><span class="n">target</span><span class="o">=</span><span class="n">foo</span><span class="p">)</span>
|
||
<span class="n">p</span><span class="o">.</span><span class="n">start</span><span class="p">()</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>(如果程序将正常运行而不是冻结,则可以省略 <code class="docutils literal notranslate"><span class="pre">freeze_support()</span></code> 行)</p>
|
||
<p>这允许新启动的 Python 解释器安全导入模块然后运行模块中的 <code class="docutils literal notranslate"><span class="pre">foo()</span></code> 函数。</p>
|
||
<p>如果主模块中创建了进程池或者管理器,这个规则也适用。</p>
|
||
</div></blockquote>
|
||
</section>
|
||
</section>
|
||
<section id="examples">
|
||
<span id="multiprocessing-examples"></span><h2>例子<a class="headerlink" href="#examples" title="永久链接至标题">¶</a></h2>
|
||
<p>创建和使用自定义管理器、代理的示例:</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">multiprocessing</span> <span class="kn">import</span> <span class="n">freeze_support</span>
|
||
<span class="kn">from</span> <span class="nn">multiprocessing.managers</span> <span class="kn">import</span> <span class="n">BaseManager</span><span class="p">,</span> <span class="n">BaseProxy</span>
|
||
<span class="kn">import</span> <span class="nn">operator</span>
|
||
|
||
<span class="c1">##</span>
|
||
|
||
<span class="k">class</span> <span class="nc">Foo</span><span class="p">:</span>
|
||
<span class="k">def</span> <span class="nf">f</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="s1">'you called Foo.f()'</span><span class="p">)</span>
|
||
<span class="k">def</span> <span class="nf">g</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="s1">'you called Foo.g()'</span><span class="p">)</span>
|
||
<span class="k">def</span> <span class="nf">_h</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="s1">'you called Foo._h()'</span><span class="p">)</span>
|
||
|
||
<span class="c1"># A simple generator function</span>
|
||
<span class="k">def</span> <span class="nf">baz</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="k">yield</span> <span class="n">i</span><span class="o">*</span><span class="n">i</span>
|
||
|
||
<span class="c1"># Proxy type for generator objects</span>
|
||
<span class="k">class</span> <span class="nc">GeneratorProxy</span><span class="p">(</span><span class="n">BaseProxy</span><span class="p">):</span>
|
||
<span class="n">_exposed_</span> <span class="o">=</span> <span class="p">[</span><span class="s1">'__next__'</span><span class="p">]</span>
|
||
<span class="k">def</span> <span class="fm">__iter__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||
<span class="k">return</span> <span class="bp">self</span>
|
||
<span class="k">def</span> <span class="fm">__next__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_callmethod</span><span class="p">(</span><span class="s1">'__next__'</span><span class="p">)</span>
|
||
|
||
<span class="c1"># Function to return the operator module</span>
|
||
<span class="k">def</span> <span class="nf">get_operator_module</span><span class="p">():</span>
|
||
<span class="k">return</span> <span class="n">operator</span>
|
||
|
||
<span class="c1">##</span>
|
||
|
||
<span class="k">class</span> <span class="nc">MyManager</span><span class="p">(</span><span class="n">BaseManager</span><span class="p">):</span>
|
||
<span class="k">pass</span>
|
||
|
||
<span class="c1"># register the Foo class; make `f()` and `g()` accessible via proxy</span>
|
||
<span class="n">MyManager</span><span class="o">.</span><span class="n">register</span><span class="p">(</span><span class="s1">'Foo1'</span><span class="p">,</span> <span class="n">Foo</span><span class="p">)</span>
|
||
|
||
<span class="c1"># register the Foo class; make `g()` and `_h()` accessible via proxy</span>
|
||
<span class="n">MyManager</span><span class="o">.</span><span class="n">register</span><span class="p">(</span><span class="s1">'Foo2'</span><span class="p">,</span> <span class="n">Foo</span><span class="p">,</span> <span class="n">exposed</span><span class="o">=</span><span class="p">(</span><span class="s1">'g'</span><span class="p">,</span> <span class="s1">'_h'</span><span class="p">))</span>
|
||
|
||
<span class="c1"># register the generator function baz; use `GeneratorProxy` to make proxies</span>
|
||
<span class="n">MyManager</span><span class="o">.</span><span class="n">register</span><span class="p">(</span><span class="s1">'baz'</span><span class="p">,</span> <span class="n">baz</span><span class="p">,</span> <span class="n">proxytype</span><span class="o">=</span><span class="n">GeneratorProxy</span><span class="p">)</span>
|
||
|
||
<span class="c1"># register get_operator_module(); make public functions accessible via proxy</span>
|
||
<span class="n">MyManager</span><span class="o">.</span><span class="n">register</span><span class="p">(</span><span class="s1">'operator'</span><span class="p">,</span> <span class="n">get_operator_module</span><span class="p">)</span>
|
||
|
||
<span class="c1">##</span>
|
||
|
||
<span class="k">def</span> <span class="nf">test</span><span class="p">():</span>
|
||
<span class="n">manager</span> <span class="o">=</span> <span class="n">MyManager</span><span class="p">()</span>
|
||
<span class="n">manager</span><span class="o">.</span><span class="n">start</span><span class="p">()</span>
|
||
|
||
<span class="nb">print</span><span class="p">(</span><span class="s1">'-'</span> <span class="o">*</span> <span class="mi">20</span><span class="p">)</span>
|
||
|
||
<span class="n">f1</span> <span class="o">=</span> <span class="n">manager</span><span class="o">.</span><span class="n">Foo1</span><span class="p">()</span>
|
||
<span class="n">f1</span><span class="o">.</span><span class="n">f</span><span class="p">()</span>
|
||
<span class="n">f1</span><span class="o">.</span><span class="n">g</span><span class="p">()</span>
|
||
<span class="k">assert</span> <span class="ow">not</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">f1</span><span class="p">,</span> <span class="s1">'_h'</span><span class="p">)</span>
|
||
<span class="k">assert</span> <span class="nb">sorted</span><span class="p">(</span><span class="n">f1</span><span class="o">.</span><span class="n">_exposed_</span><span class="p">)</span> <span class="o">==</span> <span class="nb">sorted</span><span class="p">([</span><span class="s1">'f'</span><span class="p">,</span> <span class="s1">'g'</span><span class="p">])</span>
|
||
|
||
<span class="nb">print</span><span class="p">(</span><span class="s1">'-'</span> <span class="o">*</span> <span class="mi">20</span><span class="p">)</span>
|
||
|
||
<span class="n">f2</span> <span class="o">=</span> <span class="n">manager</span><span class="o">.</span><span class="n">Foo2</span><span class="p">()</span>
|
||
<span class="n">f2</span><span class="o">.</span><span class="n">g</span><span class="p">()</span>
|
||
<span class="n">f2</span><span class="o">.</span><span class="n">_h</span><span class="p">()</span>
|
||
<span class="k">assert</span> <span class="ow">not</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">f2</span><span class="p">,</span> <span class="s1">'f'</span><span class="p">)</span>
|
||
<span class="k">assert</span> <span class="nb">sorted</span><span class="p">(</span><span class="n">f2</span><span class="o">.</span><span class="n">_exposed_</span><span class="p">)</span> <span class="o">==</span> <span class="nb">sorted</span><span class="p">([</span><span class="s1">'g'</span><span class="p">,</span> <span class="s1">'_h'</span><span class="p">])</span>
|
||
|
||
<span class="nb">print</span><span class="p">(</span><span class="s1">'-'</span> <span class="o">*</span> <span class="mi">20</span><span class="p">)</span>
|
||
|
||
<span class="n">it</span> <span class="o">=</span> <span class="n">manager</span><span class="o">.</span><span class="n">baz</span><span class="p">()</span>
|
||
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">it</span><span class="p">:</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="s1">'<</span><span class="si">%d</span><span class="s1">>'</span> <span class="o">%</span> <span class="n">i</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="nb">print</span><span class="p">(</span><span class="s1">'-'</span> <span class="o">*</span> <span class="mi">20</span><span class="p">)</span>
|
||
|
||
<span class="n">op</span> <span class="o">=</span> <span class="n">manager</span><span class="o">.</span><span class="n">operator</span><span class="p">()</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="s1">'op.add(23, 45) ='</span><span class="p">,</span> <span class="n">op</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="mi">23</span><span class="p">,</span> <span class="mi">45</span><span class="p">))</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="s1">'op.pow(2, 94) ='</span><span class="p">,</span> <span class="n">op</span><span class="o">.</span><span class="n">pow</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="mi">94</span><span class="p">))</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="s1">'op._exposed_ ='</span><span class="p">,</span> <span class="n">op</span><span class="o">.</span><span class="n">_exposed_</span><span class="p">)</span>
|
||
|
||
<span class="c1">##</span>
|
||
|
||
<span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s1">'__main__'</span><span class="p">:</span>
|
||
<span class="n">freeze_support</span><span class="p">()</span>
|
||
<span class="n">test</span><span class="p">()</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>使用 <a class="reference internal" href="#multiprocessing.pool.Pool" title="multiprocessing.pool.Pool"><code class="xref py py-class docutils literal notranslate"><span class="pre">Pool</span></code></a>:</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">multiprocessing</span>
|
||
<span class="kn">import</span> <span class="nn">time</span>
|
||
<span class="kn">import</span> <span class="nn">random</span>
|
||
<span class="kn">import</span> <span class="nn">sys</span>
|
||
|
||
<span class="c1">#</span>
|
||
<span class="c1"># Functions used by test code</span>
|
||
<span class="c1">#</span>
|
||
|
||
<span class="k">def</span> <span class="nf">calculate</span><span class="p">(</span><span class="n">func</span><span class="p">,</span> <span class="n">args</span><span class="p">):</span>
|
||
<span class="n">result</span> <span class="o">=</span> <span class="n">func</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">)</span>
|
||
<span class="k">return</span> <span class="s1">'</span><span class="si">%s</span><span class="s1"> says that </span><span class="si">%s%s</span><span class="s1"> = </span><span class="si">%s</span><span class="s1">'</span> <span class="o">%</span> <span class="p">(</span>
|
||
<span class="n">multiprocessing</span><span class="o">.</span><span class="n">current_process</span><span class="p">()</span><span class="o">.</span><span class="n">name</span><span class="p">,</span>
|
||
<span class="n">func</span><span class="o">.</span><span class="vm">__name__</span><span class="p">,</span> <span class="n">args</span><span class="p">,</span> <span class="n">result</span>
|
||
<span class="p">)</span>
|
||
|
||
<span class="k">def</span> <span class="nf">calculatestar</span><span class="p">(</span><span class="n">args</span><span class="p">):</span>
|
||
<span class="k">return</span> <span class="n">calculate</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">)</span>
|
||
|
||
<span class="k">def</span> <span class="nf">mul</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</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="o">*</span> <span class="n">random</span><span class="o">.</span><span class="n">random</span><span class="p">())</span>
|
||
<span class="k">return</span> <span class="n">a</span> <span class="o">*</span> <span class="n">b</span>
|
||
|
||
<span class="k">def</span> <span class="nf">plus</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</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="o">*</span> <span class="n">random</span><span class="o">.</span><span class="n">random</span><span class="p">())</span>
|
||
<span class="k">return</span> <span class="n">a</span> <span class="o">+</span> <span class="n">b</span>
|
||
|
||
<span class="k">def</span> <span class="nf">f</span><span class="p">(</span><span class="n">x</span><span class="p">):</span>
|
||
<span class="k">return</span> <span class="mf">1.0</span> <span class="o">/</span> <span class="p">(</span><span class="n">x</span> <span class="o">-</span> <span class="mf">5.0</span><span class="p">)</span>
|
||
|
||
<span class="k">def</span> <span class="nf">pow3</span><span class="p">(</span><span class="n">x</span><span class="p">):</span>
|
||
<span class="k">return</span> <span class="n">x</span> <span class="o">**</span> <span class="mi">3</span>
|
||
|
||
<span class="k">def</span> <span class="nf">noop</span><span class="p">(</span><span class="n">x</span><span class="p">):</span>
|
||
<span class="k">pass</span>
|
||
|
||
<span class="c1">#</span>
|
||
<span class="c1"># Test code</span>
|
||
<span class="c1">#</span>
|
||
|
||
<span class="k">def</span> <span class="nf">test</span><span class="p">():</span>
|
||
<span class="n">PROCESSES</span> <span class="o">=</span> <span class="mi">4</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="s1">'Creating pool with </span><span class="si">%d</span><span class="s1"> processes</span><span class="se">\n</span><span class="s1">'</span> <span class="o">%</span> <span class="n">PROCESSES</span><span class="p">)</span>
|
||
|
||
<span class="k">with</span> <span class="n">multiprocessing</span><span class="o">.</span><span class="n">Pool</span><span class="p">(</span><span class="n">PROCESSES</span><span class="p">)</span> <span class="k">as</span> <span class="n">pool</span><span class="p">:</span>
|
||
<span class="c1">#</span>
|
||
<span class="c1"># Tests</span>
|
||
<span class="c1">#</span>
|
||
|
||
<span class="n">TASKS</span> <span class="o">=</span> <span class="p">[(</span><span class="n">mul</span><span class="p">,</span> <span class="p">(</span><span class="n">i</span><span class="p">,</span> <span class="mi">7</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="o">+</span> \
|
||
<span class="p">[(</span><span class="n">plus</span><span class="p">,</span> <span class="p">(</span><span class="n">i</span><span class="p">,</span> <span class="mi">8</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">results</span> <span class="o">=</span> <span class="p">[</span><span class="n">pool</span><span class="o">.</span><span class="n">apply_async</span><span class="p">(</span><span class="n">calculate</span><span class="p">,</span> <span class="n">t</span><span class="p">)</span> <span class="k">for</span> <span class="n">t</span> <span class="ow">in</span> <span class="n">TASKS</span><span class="p">]</span>
|
||
<span class="n">imap_it</span> <span class="o">=</span> <span class="n">pool</span><span class="o">.</span><span class="n">imap</span><span class="p">(</span><span class="n">calculatestar</span><span class="p">,</span> <span class="n">TASKS</span><span class="p">)</span>
|
||
<span class="n">imap_unordered_it</span> <span class="o">=</span> <span class="n">pool</span><span class="o">.</span><span class="n">imap_unordered</span><span class="p">(</span><span class="n">calculatestar</span><span class="p">,</span> <span class="n">TASKS</span><span class="p">)</span>
|
||
|
||
<span class="nb">print</span><span class="p">(</span><span class="s1">'Ordered results using pool.apply_async():'</span><span class="p">)</span>
|
||
<span class="k">for</span> <span class="n">r</span> <span class="ow">in</span> <span class="n">results</span><span class="p">:</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="s1">'</span><span class="se">\t</span><span class="s1">'</span><span class="p">,</span> <span class="n">r</span><span class="o">.</span><span class="n">get</span><span class="p">())</span>
|
||
<span class="nb">print</span><span class="p">()</span>
|
||
|
||
<span class="nb">print</span><span class="p">(</span><span class="s1">'Ordered results using pool.imap():'</span><span class="p">)</span>
|
||
<span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="n">imap_it</span><span class="p">:</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="s1">'</span><span class="se">\t</span><span class="s1">'</span><span class="p">,</span> <span class="n">x</span><span class="p">)</span>
|
||
<span class="nb">print</span><span class="p">()</span>
|
||
|
||
<span class="nb">print</span><span class="p">(</span><span class="s1">'Unordered results using pool.imap_unordered():'</span><span class="p">)</span>
|
||
<span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="n">imap_unordered_it</span><span class="p">:</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="s1">'</span><span class="se">\t</span><span class="s1">'</span><span class="p">,</span> <span class="n">x</span><span class="p">)</span>
|
||
<span class="nb">print</span><span class="p">()</span>
|
||
|
||
<span class="nb">print</span><span class="p">(</span><span class="s1">'Ordered results using pool.map() --- will block till complete:'</span><span class="p">)</span>
|
||
<span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="n">pool</span><span class="o">.</span><span class="n">map</span><span class="p">(</span><span class="n">calculatestar</span><span class="p">,</span> <span class="n">TASKS</span><span class="p">):</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="s1">'</span><span class="se">\t</span><span class="s1">'</span><span class="p">,</span> <span class="n">x</span><span class="p">)</span>
|
||
<span class="nb">print</span><span class="p">()</span>
|
||
|
||
<span class="c1">#</span>
|
||
<span class="c1"># Test error handling</span>
|
||
<span class="c1">#</span>
|
||
|
||
<span class="nb">print</span><span class="p">(</span><span class="s1">'Testing error handling:'</span><span class="p">)</span>
|
||
|
||
<span class="k">try</span><span class="p">:</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="n">pool</span><span class="o">.</span><span class="n">apply</span><span class="p">(</span><span class="n">f</span><span class="p">,</span> <span class="p">(</span><span class="mi">5</span><span class="p">,)))</span>
|
||
<span class="k">except</span> <span class="ne">ZeroDivisionError</span><span class="p">:</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="s1">'</span><span class="se">\t</span><span class="s1">Got ZeroDivisionError as expected from pool.apply()'</span><span class="p">)</span>
|
||
<span class="k">else</span><span class="p">:</span>
|
||
<span class="k">raise</span> <span class="ne">AssertionError</span><span class="p">(</span><span class="s1">'expected ZeroDivisionError'</span><span class="p">)</span>
|
||
|
||
<span class="k">try</span><span class="p">:</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="n">pool</span><span class="o">.</span><span class="n">map</span><span class="p">(</span><span class="n">f</span><span class="p">,</span> <span class="nb">list</span><span class="p">(</span><span class="nb">range</span><span class="p">(</span><span class="mi">10</span><span class="p">))))</span>
|
||
<span class="k">except</span> <span class="ne">ZeroDivisionError</span><span class="p">:</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="s1">'</span><span class="se">\t</span><span class="s1">Got ZeroDivisionError as expected from pool.map()'</span><span class="p">)</span>
|
||
<span class="k">else</span><span class="p">:</span>
|
||
<span class="k">raise</span> <span class="ne">AssertionError</span><span class="p">(</span><span class="s1">'expected ZeroDivisionError'</span><span class="p">)</span>
|
||
|
||
<span class="k">try</span><span class="p">:</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="nb">list</span><span class="p">(</span><span class="n">pool</span><span class="o">.</span><span class="n">imap</span><span class="p">(</span><span class="n">f</span><span class="p">,</span> <span class="nb">list</span><span class="p">(</span><span class="nb">range</span><span class="p">(</span><span class="mi">10</span><span class="p">)))))</span>
|
||
<span class="k">except</span> <span class="ne">ZeroDivisionError</span><span class="p">:</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="s1">'</span><span class="se">\t</span><span class="s1">Got ZeroDivisionError as expected from list(pool.imap())'</span><span class="p">)</span>
|
||
<span class="k">else</span><span class="p">:</span>
|
||
<span class="k">raise</span> <span class="ne">AssertionError</span><span class="p">(</span><span class="s1">'expected ZeroDivisionError'</span><span class="p">)</span>
|
||
|
||
<span class="n">it</span> <span class="o">=</span> <span class="n">pool</span><span class="o">.</span><span class="n">imap</span><span class="p">(</span><span class="n">f</span><span class="p">,</span> <span class="nb">list</span><span class="p">(</span><span class="nb">range</span><span class="p">(</span><span class="mi">10</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="k">try</span><span class="p">:</span>
|
||
<span class="n">x</span> <span class="o">=</span> <span class="nb">next</span><span class="p">(</span><span class="n">it</span><span class="p">)</span>
|
||
<span class="k">except</span> <span class="ne">ZeroDivisionError</span><span class="p">:</span>
|
||
<span class="k">if</span> <span class="n">i</span> <span class="o">==</span> <span class="mi">5</span><span class="p">:</span>
|
||
<span class="k">pass</span>
|
||
<span class="k">except</span> <span class="ne">StopIteration</span><span class="p">:</span>
|
||
<span class="k">break</span>
|
||
<span class="k">else</span><span class="p">:</span>
|
||
<span class="k">if</span> <span class="n">i</span> <span class="o">==</span> <span class="mi">5</span><span class="p">:</span>
|
||
<span class="k">raise</span> <span class="ne">AssertionError</span><span class="p">(</span><span class="s1">'expected ZeroDivisionError'</span><span class="p">)</span>
|
||
|
||
<span class="k">assert</span> <span class="n">i</span> <span class="o">==</span> <span class="mi">9</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="s1">'</span><span class="se">\t</span><span class="s1">Got ZeroDivisionError as expected from IMapIterator.next()'</span><span class="p">)</span>
|
||
<span class="nb">print</span><span class="p">()</span>
|
||
|
||
<span class="c1">#</span>
|
||
<span class="c1"># Testing timeouts</span>
|
||
<span class="c1">#</span>
|
||
|
||
<span class="nb">print</span><span class="p">(</span><span class="s1">'Testing ApplyResult.get() with timeout:'</span><span class="p">,</span> <span class="n">end</span><span class="o">=</span><span class="s1">' '</span><span class="p">)</span>
|
||
<span class="n">res</span> <span class="o">=</span> <span class="n">pool</span><span class="o">.</span><span class="n">apply_async</span><span class="p">(</span><span class="n">calculate</span><span class="p">,</span> <span class="n">TASKS</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>
|
||
<span class="k">while</span> <span class="mi">1</span><span class="p">:</span>
|
||
<span class="n">sys</span><span class="o">.</span><span class="n">stdout</span><span class="o">.</span><span class="n">flush</span><span class="p">()</span>
|
||
<span class="k">try</span><span class="p">:</span>
|
||
<span class="n">sys</span><span class="o">.</span><span class="n">stdout</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s1">'</span><span class="se">\n\t</span><span class="si">%s</span><span class="s1">'</span> <span class="o">%</span> <span class="n">res</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="mf">0.02</span><span class="p">))</span>
|
||
<span class="k">break</span>
|
||
<span class="k">except</span> <span class="n">multiprocessing</span><span class="o">.</span><span class="n">TimeoutError</span><span class="p">:</span>
|
||
<span class="n">sys</span><span class="o">.</span><span class="n">stdout</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s1">'.'</span><span class="p">)</span>
|
||
<span class="nb">print</span><span class="p">()</span>
|
||
<span class="nb">print</span><span class="p">()</span>
|
||
|
||
<span class="nb">print</span><span class="p">(</span><span class="s1">'Testing IMapIterator.next() with timeout:'</span><span class="p">,</span> <span class="n">end</span><span class="o">=</span><span class="s1">' '</span><span class="p">)</span>
|
||
<span class="n">it</span> <span class="o">=</span> <span class="n">pool</span><span class="o">.</span><span class="n">imap</span><span class="p">(</span><span class="n">calculatestar</span><span class="p">,</span> <span class="n">TASKS</span><span class="p">)</span>
|
||
<span class="k">while</span> <span class="mi">1</span><span class="p">:</span>
|
||
<span class="n">sys</span><span class="o">.</span><span class="n">stdout</span><span class="o">.</span><span class="n">flush</span><span class="p">()</span>
|
||
<span class="k">try</span><span class="p">:</span>
|
||
<span class="n">sys</span><span class="o">.</span><span class="n">stdout</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s1">'</span><span class="se">\n\t</span><span class="si">%s</span><span class="s1">'</span> <span class="o">%</span> <span class="n">it</span><span class="o">.</span><span class="n">next</span><span class="p">(</span><span class="mf">0.02</span><span class="p">))</span>
|
||
<span class="k">except</span> <span class="ne">StopIteration</span><span class="p">:</span>
|
||
<span class="k">break</span>
|
||
<span class="k">except</span> <span class="n">multiprocessing</span><span class="o">.</span><span class="n">TimeoutError</span><span class="p">:</span>
|
||
<span class="n">sys</span><span class="o">.</span><span class="n">stdout</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s1">'.'</span><span class="p">)</span>
|
||
<span class="nb">print</span><span class="p">()</span>
|
||
<span class="nb">print</span><span class="p">()</span>
|
||
|
||
|
||
<span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s1">'__main__'</span><span class="p">:</span>
|
||
<span class="n">multiprocessing</span><span class="o">.</span><span class="n">freeze_support</span><span class="p">()</span>
|
||
<span class="n">test</span><span class="p">()</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>一个演示如何使用队列来向一组工作进程提供任务并收集结果的例子:</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">time</span>
|
||
<span class="kn">import</span> <span class="nn">random</span>
|
||
|
||
<span class="kn">from</span> <span class="nn">multiprocessing</span> <span class="kn">import</span> <span class="n">Process</span><span class="p">,</span> <span class="n">Queue</span><span class="p">,</span> <span class="n">current_process</span><span class="p">,</span> <span class="n">freeze_support</span>
|
||
|
||
<span class="c1">#</span>
|
||
<span class="c1"># Function run by worker processes</span>
|
||
<span class="c1">#</span>
|
||
|
||
<span class="k">def</span> <span class="nf">worker</span><span class="p">(</span><span class="nb">input</span><span class="p">,</span> <span class="n">output</span><span class="p">):</span>
|
||
<span class="k">for</span> <span class="n">func</span><span class="p">,</span> <span class="n">args</span> <span class="ow">in</span> <span class="nb">iter</span><span class="p">(</span><span class="nb">input</span><span class="o">.</span><span class="n">get</span><span class="p">,</span> <span class="s1">'STOP'</span><span class="p">):</span>
|
||
<span class="n">result</span> <span class="o">=</span> <span class="n">calculate</span><span class="p">(</span><span class="n">func</span><span class="p">,</span> <span class="n">args</span><span class="p">)</span>
|
||
<span class="n">output</span><span class="o">.</span><span class="n">put</span><span class="p">(</span><span class="n">result</span><span class="p">)</span>
|
||
|
||
<span class="c1">#</span>
|
||
<span class="c1"># Function used to calculate result</span>
|
||
<span class="c1">#</span>
|
||
|
||
<span class="k">def</span> <span class="nf">calculate</span><span class="p">(</span><span class="n">func</span><span class="p">,</span> <span class="n">args</span><span class="p">):</span>
|
||
<span class="n">result</span> <span class="o">=</span> <span class="n">func</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">)</span>
|
||
<span class="k">return</span> <span class="s1">'</span><span class="si">%s</span><span class="s1"> says that </span><span class="si">%s%s</span><span class="s1"> = </span><span class="si">%s</span><span class="s1">'</span> <span class="o">%</span> \
|
||
<span class="p">(</span><span class="n">current_process</span><span class="p">()</span><span class="o">.</span><span class="n">name</span><span class="p">,</span> <span class="n">func</span><span class="o">.</span><span class="vm">__name__</span><span class="p">,</span> <span class="n">args</span><span class="p">,</span> <span class="n">result</span><span class="p">)</span>
|
||
|
||
<span class="c1">#</span>
|
||
<span class="c1"># Functions referenced by tasks</span>
|
||
<span class="c1">#</span>
|
||
|
||
<span class="k">def</span> <span class="nf">mul</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</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="o">*</span><span class="n">random</span><span class="o">.</span><span class="n">random</span><span class="p">())</span>
|
||
<span class="k">return</span> <span class="n">a</span> <span class="o">*</span> <span class="n">b</span>
|
||
|
||
<span class="k">def</span> <span class="nf">plus</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</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="o">*</span><span class="n">random</span><span class="o">.</span><span class="n">random</span><span class="p">())</span>
|
||
<span class="k">return</span> <span class="n">a</span> <span class="o">+</span> <span class="n">b</span>
|
||
|
||
<span class="c1">#</span>
|
||
<span class="c1">#</span>
|
||
<span class="c1">#</span>
|
||
|
||
<span class="k">def</span> <span class="nf">test</span><span class="p">():</span>
|
||
<span class="n">NUMBER_OF_PROCESSES</span> <span class="o">=</span> <span class="mi">4</span>
|
||
<span class="n">TASKS1</span> <span class="o">=</span> <span class="p">[(</span><span class="n">mul</span><span class="p">,</span> <span class="p">(</span><span class="n">i</span><span class="p">,</span> <span class="mi">7</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">20</span><span class="p">)]</span>
|
||
<span class="n">TASKS2</span> <span class="o">=</span> <span class="p">[(</span><span class="n">plus</span><span class="p">,</span> <span class="p">(</span><span class="n">i</span><span class="p">,</span> <span class="mi">8</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="c1"># Create queues</span>
|
||
<span class="n">task_queue</span> <span class="o">=</span> <span class="n">Queue</span><span class="p">()</span>
|
||
<span class="n">done_queue</span> <span class="o">=</span> <span class="n">Queue</span><span class="p">()</span>
|
||
|
||
<span class="c1"># Submit tasks</span>
|
||
<span class="k">for</span> <span class="n">task</span> <span class="ow">in</span> <span class="n">TASKS1</span><span class="p">:</span>
|
||
<span class="n">task_queue</span><span class="o">.</span><span class="n">put</span><span class="p">(</span><span class="n">task</span><span class="p">)</span>
|
||
|
||
<span class="c1"># Start worker processes</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">NUMBER_OF_PROCESSES</span><span class="p">):</span>
|
||
<span class="n">Process</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">args</span><span class="o">=</span><span class="p">(</span><span class="n">task_queue</span><span class="p">,</span> <span class="n">done_queue</span><span class="p">))</span><span class="o">.</span><span class="n">start</span><span class="p">()</span>
|
||
|
||
<span class="c1"># Get and print results</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="s1">'Unordered results:'</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="nb">len</span><span class="p">(</span><span class="n">TASKS1</span><span class="p">)):</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="s1">'</span><span class="se">\t</span><span class="s1">'</span><span class="p">,</span> <span class="n">done_queue</span><span class="o">.</span><span class="n">get</span><span class="p">())</span>
|
||
|
||
<span class="c1"># Add more tasks using `put()`</span>
|
||
<span class="k">for</span> <span class="n">task</span> <span class="ow">in</span> <span class="n">TASKS2</span><span class="p">:</span>
|
||
<span class="n">task_queue</span><span class="o">.</span><span class="n">put</span><span class="p">(</span><span class="n">task</span><span class="p">)</span>
|
||
|
||
<span class="c1"># Get and print some more results</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="nb">len</span><span class="p">(</span><span class="n">TASKS2</span><span class="p">)):</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="s1">'</span><span class="se">\t</span><span class="s1">'</span><span class="p">,</span> <span class="n">done_queue</span><span class="o">.</span><span class="n">get</span><span class="p">())</span>
|
||
|
||
<span class="c1"># Tell child processes to stop</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">NUMBER_OF_PROCESSES</span><span class="p">):</span>
|
||
<span class="n">task_queue</span><span class="o">.</span><span class="n">put</span><span class="p">(</span><span class="s1">'STOP'</span><span class="p">)</span>
|
||
|
||
|
||
<span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s1">'__main__'</span><span class="p">:</span>
|
||
<span class="n">freeze_support</span><span class="p">()</span>
|
||
<span class="n">test</span><span class="p">()</span>
|
||
</pre></div>
|
||
</div>
|
||
</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="#"><code class="xref py py-mod docutils literal notranslate"><span class="pre">multiprocessing</span></code> --- 基于进程的并行</a><ul>
|
||
<li><a class="reference internal" href="#introduction">概述</a><ul>
|
||
<li><a class="reference internal" href="#the-process-class"><code class="xref py py-class docutils literal notranslate"><span class="pre">Process</span></code> 类</a></li>
|
||
<li><a class="reference internal" href="#contexts-and-start-methods">上下文和启动方法</a></li>
|
||
<li><a class="reference internal" href="#exchanging-objects-between-processes">在进程之间交换对象</a></li>
|
||
<li><a class="reference internal" href="#synchronization-between-processes">进程间同步</a></li>
|
||
<li><a class="reference internal" href="#sharing-state-between-processes">进程间共享状态</a></li>
|
||
<li><a class="reference internal" href="#using-a-pool-of-workers">使用工作进程</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#reference">参考</a><ul>
|
||
<li><a class="reference internal" href="#process-and-exceptions"><code class="xref py py-class docutils literal notranslate"><span class="pre">Process</span></code> 和异常</a></li>
|
||
<li><a class="reference internal" href="#pipes-and-queues">管道和队列</a></li>
|
||
<li><a class="reference internal" href="#miscellaneous">杂项</a></li>
|
||
<li><a class="reference internal" href="#connection-objects">连接对象(Connection)</a></li>
|
||
<li><a class="reference internal" href="#synchronization-primitives">同步原语</a></li>
|
||
<li><a class="reference internal" href="#shared-ctypes-objects">共享 <code class="xref py py-mod docutils literal notranslate"><span class="pre">ctypes</span></code> 对象</a><ul>
|
||
<li><a class="reference internal" href="#module-multiprocessing.sharedctypes"><code class="xref py py-mod docutils literal notranslate"><span class="pre">multiprocessing.sharedctypes</span></code> 模块</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#managers">管理器</a><ul>
|
||
<li><a class="reference internal" href="#customized-managers">自定义管理器</a></li>
|
||
<li><a class="reference internal" href="#using-a-remote-manager">使用远程管理器</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#proxy-objects">代理对象</a><ul>
|
||
<li><a class="reference internal" href="#cleanup">清理</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#module-multiprocessing.pool">进程池</a></li>
|
||
<li><a class="reference internal" href="#module-multiprocessing.connection">监听器及客户端</a><ul>
|
||
<li><a class="reference internal" href="#address-formats">地址格式</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#authentication-keys">认证密码</a></li>
|
||
<li><a class="reference internal" href="#logging">日志记录</a></li>
|
||
<li><a class="reference internal" href="#module-multiprocessing.dummy"><code class="xref py py-mod docutils literal notranslate"><span class="pre">multiprocessing.dummy</span></code> 模块</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#programming-guidelines">编程指导</a><ul>
|
||
<li><a class="reference internal" href="#all-start-methods">所有start方法</a></li>
|
||
<li><a class="reference internal" href="#the-spawn-and-forkserver-start-methods"><em>spawn</em> 和 <em>forkserver</em> 启动方式</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#examples">例子</a></li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
|
||
<h4>上一个主题</h4>
|
||
<p class="topless"><a href="threading.html"
|
||
title="上一章"><code class="xref py py-mod docutils literal notranslate"><span class="pre">threading</span></code> --- 基于线程的并行</a></p>
|
||
<h4>下一个主题</h4>
|
||
<p class="topless"><a href="multiprocessing.shared_memory.html"
|
||
title="下一章"><code class="xref py py-mod docutils literal notranslate"><span class="pre">multiprocessing.shared_memory</span></code> --- 可从进程直接访问的共享内存</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/library/multiprocessing.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="multiprocessing.shared_memory.html" title="multiprocessing.shared_memory --- 可从进程直接访问的共享内存"
|
||
>下一页</a> |</li>
|
||
<li class="right" >
|
||
<a href="threading.html" title="threading --- 基于线程的并行"
|
||
>上一页</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="nav-item nav-item-2"><a href="concurrency.html" >并发执行</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> |