“Python/docs/3.9/library/profile”的版本间差异

来自菜鸟教程
Python/docs/3.9/library/profile
跳转至:导航、​搜索
(autoload)
 
(Page commit)
 
第1行: 第1行:
 +
{{DISPLAYTITLE:Python 分析器 — Python 文档}}
 
<div id="the-python-profilers" class="section">
 
<div id="the-python-profilers" class="section">
  
 
<span id="profile"></span>
 
<span id="profile"></span>
= The Python Profilers =
+
= Python 分析器 =
  
'''Source code:''' [https://github.com/python/cpython/tree/3.9/Lib/profile.py Lib/profile.py] and [https://github.com/python/cpython/tree/3.9/Lib/pstats.py Lib/pstats.py]
+
'''源代码:''' [[#id1|<span id="id2" class="problematic">:source:`Lib/profile.py`</span>]] and [[#id3|<span id="id4" class="problematic">:source:`Lib/pstats.py`</span>]]
 +
 
 +
 
 +
-----
  
 
<div id="introduction-to-the-profilers" class="section">
 
<div id="introduction-to-the-profilers" class="section">
  
 
<span id="profiler-introduction"></span>
 
<span id="profiler-introduction"></span>
== Introduction to the profilers ==
+
== 分析器简介 ==
  
[[#module-cProfile|<code>cProfile</code>]] and [[#module-profile|<code>profile</code>]] provide ''deterministic profiling'' of
+
[[#module-cProfile|cProfile]] [[#module-profile|profile]] 提供 Python 程序的 ''确定性分析'' ''profile'' 是一组统计数据,描述了程序各个部分执行的频率和时间。 这些统计信息可以通过 [[#module-pstats|pstats]] 模块格式化为报告。
Python programs. A ''profile'' is a set of statistics that describes how
 
often and for how long various parts of the program executed. These statistics
 
can be formatted into reports via the [[#module-pstats|<code>pstats</code>]] module.
 
  
The Python standard library provides two different implementations of the same
+
Python 标准库提供了相同分析接口的两种不同实现:
profiling interface:
 
  
# [[#module-cProfile|<code>cProfile</code>]] is recommended for most users; it's a C extension with reasonable overhead that makes it suitable for profiling long-running programs. Based on <code>lsprof</code>, contributed by Brett Rosen and Ted Czotter.
+
# [[#module-cProfile|cProfile]] 推荐给大多数用户; 它是一个具有合理开销的 C 扩展,使其适用于分析长时间运行的程序。 基于 <code>lsprof</code>,由 Brett Rosen Ted Czotter 贡献。
# [[#module-profile|<code>profile</code>]], a pure Python module whose interface is imitated by [[#module-cProfile|<code>cProfile</code>]], but which adds significant overhead to profiled programs. If you're trying to extend the profiler in some way, the task might be easier with this module. Originally designed and written by Jim Roskind.
+
# [[#module-profile|profile]],一个纯 Python 模块,它的接口被 [[#module-cProfile|cProfile]] 模仿,但它为分析程序增加了显着的开销。 如果您尝试以某种方式扩展探查器,则使用此模块可能会更轻松地完成任务。 最初由 Jim Roskind 设计和编写。
  
 
<div class="admonition note">
 
<div class="admonition note">
  
注解
+
笔记
  
The profiler modules are designed to provide an execution profile for a given
+
分析器模块旨在为给定程序提供执行配置文件,而不是用于基准测试目的(为此,有 [[../timeit#module-timeit|timeit]] 以获得合理准确的结果)。 这尤其适用于针对 C 代码对 Python 代码进行基准测试:分析器引入了 Python 代码的开销,而不是 C 级函数的开销,因此 C 代码看起来比任何 Python 代码都快。
program, not for benchmarking purposes (for that, there is [[../timeit#module-timeit|<code>timeit</code>]] for
 
reasonably accurate results). This particularly applies to benchmarking
 
Python code against C code: the profilers introduce overhead for Python code,
 
but not for C-level functions, and so the C code would seem faster than any
 
Python one.
 
  
  
第40行: 第35行:
  
 
<span id="profile-instant"></span>
 
<span id="profile-instant"></span>
== Instant User's Manual ==
+
== 即时用户手册 ==
  
This section is provided for users that &quot;don't want to read the manual.&quot; It
+
本节是为“不想阅读手册”的用户提供的。 它提供了一个非常简短的概述,并允许用户快速对现有应用程序进行分析。
provides a very brief overview, and allows a user to rapidly perform profiling
 
on an existing application.
 
  
To profile a function that takes a single argument, you can do:
+
要分析采用单个参数的函数,您可以执行以下操作:
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第52行: 第45行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>import cProfile
+
<syntaxhighlight lang="python3">import cProfile
 
import re
 
import re
cProfile.run('re.compile(&quot;foo|bar&quot;)')</pre>
+
cProfile.run('re.compile("foo|bar")')</syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
(Use [[#module-profile|<code>profile</code>]] instead of [[#module-cProfile|<code>cProfile</code>]] if the latter is not available on
+
(如果后者在您的系统上不可用,请使用 [[#module-profile|profile]] 而不是 [[#module-cProfile|cProfile]]。)
your system.)
 
  
The above action would run [[../re#re|<code>re.compile()</code>]] and print profile results like
+
上述操作将运行 [[../re#re|re.compile()]] 并打印如下所示的配置文件结果:
the following:
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第69行: 第60行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>      197 function calls (192 primitive calls) in 0.002 seconds
+
<syntaxhighlight lang="python3">      197 function calls (192 primitive calls) in 0.002 seconds
  
 
Ordered by: standard name
 
Ordered by: standard name
  
 
ncalls  tottime  percall  cumtime  percall filename:lineno(function)
 
ncalls  tottime  percall  cumtime  percall filename:lineno(function)
     1    0.000    0.000    0.001    0.001 &lt;string&gt;:1(&lt;module&gt;)
+
     1    0.000    0.000    0.001    0.001 <string>:1(<module>)
 
     1    0.000    0.000    0.001    0.001 re.py:212(compile)
 
     1    0.000    0.000    0.001    0.001 re.py:212(compile)
 
     1    0.000    0.000    0.001    0.001 re.py:268(_compile)
 
     1    0.000    0.000    0.001    0.001 re.py:268(_compile)
第80行: 第71行:
 
     1    0.000    0.000    0.000    0.000 sre_compile.py:201(_optimize_charset)
 
     1    0.000    0.000    0.000    0.000 sre_compile.py:201(_optimize_charset)
 
     4    0.000    0.000    0.000    0.000 sre_compile.py:25(_identityfunction)
 
     4    0.000    0.000    0.000    0.000 sre_compile.py:25(_identityfunction)
   3/1    0.000    0.000    0.000    0.000 sre_compile.py:33(_compile)</pre>
+
   3/1    0.000    0.000    0.000    0.000 sre_compile.py:33(_compile)</syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
The first line indicates that 197 calls were monitored. Of those calls, 192
+
第一行表示监控了 197 个呼叫。 在这些调用中,192 个是 ''primitive'',这意味着调用不是通过递归引起的。 下一行:<code>Ordered by: standard name</code>,表示使用最右列中的文本字符串对输出进行排序。 列标题包括:
were ''primitive'', meaning that the call was not induced via recursion. The
 
next line: <code>Ordered by: standard name</code>, indicates that the text string in the
 
far right column was used to sort the output. The column headings include:
 
  
; ncalls
+
; 调用
: for the number of calls.
+
: 对于呼叫数量。
; tottime
+
; 时间
: for the total time spent in the given function (and excluding time made in calls to sub-functions)
+
: 在给定函数中花费的总时间(不包括调用子函数的时间)
; percall
+
; 每次通话
: is the quotient of <code>tottime</code> divided by <code>ncalls</code>
+
: <code>tottime</code> 除以 <code>ncalls</code> 的商
; cumtime
+
; 临时工
: is the cumulative time spent in this and all subfunctions (from invocation till exit). This figure is accurate ''even'' for recursive functions.
+
: 是在这个函数和所有子函数中花费的累积时间(从调用到退出)。 对于递归函数,这个数字是准确的 ''甚至''
; percall
+
; 每次通话
: is the quotient of <code>cumtime</code> divided by primitive calls
+
: <code>cumtime</code> 除以原始调用的商
; filename:lineno(function)
+
; 文件名:lineno(函数)
: provides the respective data of each function
+
: 提供每个函数的各自数据
  
When there are two numbers in the first column (for example <code>3/1</code>), it means
+
当第一列有两个数字时(例如<code>3/1</code>),表示函数递归了。 第二个值是原始调用的数量,前者是调用的总数。 注意函数不递归时,这两个值是一样的,只打印单个数字。
that the function recursed. The second value is the number of primitive calls
 
and the former is the total number of calls. Note that when the function does
 
not recurse, these two values are the same, and only the single figure is
 
printed.
 
  
Instead of printing the output at the end of the profile run, you can save the
+
您可以通过为 <code>run()</code> 函数指定文件名,而不是在配置文件运行结束时打印输出:
results to a file by specifying a filename to the <code>run()</code> function:
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第116行: 第99行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>import cProfile
+
<syntaxhighlight lang="python3">import cProfile
 
import re
 
import re
cProfile.run('re.compile(&quot;foo|bar&quot;)', 'restats')</pre>
+
cProfile.run('re.compile("foo|bar")', 'restats')</syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
The [[#pstats.Stats|<code>pstats.Stats</code>]] class reads profile results from a file and formats
+
[[#pstats.Stats|pstats.Stats]] 类从文件中读取配置文件结果并以各种方式对其进行格式化。
them in various ways.
 
  
The files [[#module-cProfile|<code>cProfile</code>]] and [[#module-profile|<code>profile</code>]] can also be invoked as a script to
+
文件 [[#module-cProfile|cProfile]] [[#module-profile|profile]] 也可以作为脚本调用来分析另一个脚本。 例如:
profile another script. For example:
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第133行: 第114行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>python -m cProfile [-o output_file] [-s sort_order] (-m module | myscript.py)</pre>
+
<syntaxhighlight lang="python3">python -m cProfile [-o output_file] [-s sort_order] (-m module | myscript.py)</syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
<code>-o</code> writes the profile results to a file instead of to stdout
+
<code>-o</code> 将配置文件结果写入文件而不是标准输出
  
<code>-s</code> specifies one of the [[#pstats.Stats.sort_stats|<code>sort_stats()</code>]] sort values to sort
+
<code>-s</code> 指定 [[#pstats.Stats.sort_stats|sort_stats()]] 排序值之一以对输出进行排序。 这仅适用于未提供 <code>-o</code> 的情况。
the output by. This only applies when <code>-o</code> is not supplied.
 
  
<code>-m</code> specifies that a module is being profiled instead of a script.
+
<code>-m</code> 指定正在分析模块而不是脚本。
  
 
<blockquote><div>
 
<blockquote><div>
第149行: 第129行:
 
<div class="versionadded">
 
<div class="versionadded">
  
<span class="versionmodified added">3.7 新版功能: </span>Added the <code>-m</code> option to [[#module-cProfile|<code>cProfile</code>]].
+
<span class="versionmodified added"> 3.7 新功能: </span> [[#module-cProfile|cProfile]] 中添加了 <code>-m</code> 选项。
  
  
第155行: 第135行:
 
<div class="versionadded">
 
<div class="versionadded">
  
<span class="versionmodified added">3.8 新版功能: </span>Added the <code>-m</code> option to [[#module-profile|<code>profile</code>]].
+
<span class="versionmodified added">3.8 新功能:</span>[[#module-profile|配置文件]]中增加了<code>-m</code>选项。
  
  
第161行: 第141行:
  
 
</div></blockquote>
 
</div></blockquote>
The [[#module-pstats|<code>pstats</code>]] module's [[#pstats.Stats|<code>Stats</code>]] class has a variety of methods
+
[[#module-pstats|pstats]] 模块的 [[#pstats.Stats|Stats]] 类有多种方法来操作和打印保存到配置文件结果文件中的数据:
for manipulating and printing the data saved into a profile results file:
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第168行: 第147行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>import pstats
+
<syntaxhighlight lang="python3">import pstats
 
from pstats import SortKey
 
from pstats import SortKey
 
p = pstats.Stats('restats')
 
p = pstats.Stats('restats')
p.strip_dirs().sort_stats(-1).print_stats()</pre>
+
p.strip_dirs().sort_stats(-1).print_stats()</syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
The [[#pstats.Stats.strip_dirs|<code>strip_dirs()</code>]] method removed the extraneous path from all
+
[[#pstats.Stats.strip_dirs|strip_dirs()]] 方法从所有模块名称中删除了无关的路径。 [[#pstats.Stats.sort_stats|sort_stats()]] 方法根据打印的标准模块//名称字符串对所有条目进行排序。 [[#pstats.Stats.print_stats|print_stats()]] 方法打印出所有的统计信息。 您可以尝试以下排序调用:
the module names. The [[#pstats.Stats.sort_stats|<code>sort_stats()</code>]] method sorted all the
 
entries according to the standard module/line/name string that is printed. The
 
[[#pstats.Stats.print_stats|<code>print_stats()</code>]] method printed out all the statistics. You
 
might try the following sort calls:
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第186行: 第161行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>p.sort_stats(SortKey.NAME)
+
<syntaxhighlight lang="python3">p.sort_stats(SortKey.NAME)
p.print_stats()</pre>
+
p.print_stats()</syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
The first call will actually sort the list by function name, and the second call
+
第一次调用实际上将按函数名称对列表进行排序,第二次调用将打印出统计信息。 以下是一些有趣的实验调用:
will print out the statistics. The following are some interesting calls to
 
experiment with:
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第200行: 第173行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>p.sort_stats(SortKey.CUMULATIVE).print_stats(10)</pre>
+
<syntaxhighlight lang="python3">p.sort_stats(SortKey.CUMULATIVE).print_stats(10)</syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
This sorts the profile by cumulative time in a function, and then only prints
+
这按函数中的累积时间对配置文件进行排序,然后只打印十个最重要的行。 如果你想了解什么算法需要时间,上面这行就是你会使用的。
the ten most significant lines. If you want to understand what algorithms are
 
taking time, the above line is what you would use.
 
  
If you were looking to see what functions were looping a lot, and taking a lot
+
如果您想查看哪些函数循环了很多并且花费了很多时间,您可以这样做:
of time, you would do:
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第216行: 第186行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>p.sort_stats(SortKey.TIME).print_stats(10)</pre>
+
<syntaxhighlight lang="python3">p.sort_stats(SortKey.TIME).print_stats(10)</syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
to sort according to time spent within each function, and then print the
+
根据每个函数花费的时间进行排序,然后打印前十个函数的统计信息。
statistics for the top ten functions.
 
  
You might also try:
+
您也可以尝试:
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第230行: 第199行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>p.sort_stats(SortKey.FILENAME).print_stats('__init__')</pre>
+
<syntaxhighlight lang="python3">p.sort_stats(SortKey.FILENAME).print_stats('__init__')</syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
This will sort all the statistics by file name, and then print out statistics
+
这将按文件名对所有统计信息进行排序,然后仅打印出类 init 方法的统计信息(因为它们在其中拼写为 <code>__init__</code>)。 作为最后一个示例,您可以尝试:
for only the class init methods (since they are spelled with <code>__init__</code> in
 
them). As one final example, you could try:
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第243行: 第210行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>p.sort_stats(SortKey.TIME, SortKey.CUMULATIVE).print_stats(.5, 'init')</pre>
+
<syntaxhighlight lang="python3">p.sort_stats(SortKey.TIME, SortKey.CUMULATIVE).print_stats(.5, 'init')</syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
This line sorts statistics with a primary key of time, and a secondary key of
+
这一行用时间的主键和累积时间的辅助键对统计信息进行排序,然后打印出一些统计信息。 具体来说,列表首先被剔除到其原始大小的 50% (re: <code>.5</code>),然后只保留包含 <code>init</code> 的行,并打印该子子列表.
cumulative time, and then prints out some of the statistics. To be specific, the
 
list is first culled down to 50% (re: <code>.5</code>) of its original size, then only
 
lines containing <code>init</code> are maintained, and that sub-sub-list is printed.
 
  
If you wondered what functions called the above functions, you could now (<code>p</code>
+
如果您想知道哪些函数调用了上述函数,您现在可以(<code>p</code> 仍然根据最后一个条件排序)执行以下操作:
is still sorted according to the last criteria) do:
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第260行: 第223行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>p.print_callers(.5, 'init')</pre>
+
<syntaxhighlight lang="python3">p.print_callers(.5, 'init')</syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
and you would get a list of callers for each of the listed functions.
+
并且您将获得列出的每个函数的调用者列表。
  
If you want more functionality, you're going to have to read the manual, or
+
如果您想要更多功能,您将不得不阅读手册,或者猜测以下功能的作用:
guess what the following functions do:
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第274行: 第236行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>p.print_callees()
+
<syntaxhighlight lang="python3">p.print_callees()
p.add('restats')</pre>
+
p.add('restats')</syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
Invoked as a script, the [[#module-pstats|<code>pstats</code>]] module is a statistics browser for
+
作为脚本调用,[[#module-pstats|pstats]] 模块是一个统计浏览器,用于读取和检查配置文件转储。 它有一个简单的面向行的界面(使用 [[../cmd#module-cmd|cmd]] 实现)和交互式帮助。
reading and examining profile dumps. It has a simple line-oriented interface
 
(implemented using [[../cmd#module-cmd|<code>cmd</code>]]) and interactive help.
 
  
  
第289行: 第249行:
  
 
<span id="profile-and-cprofile-module-reference"></span>
 
<span id="profile-and-cprofile-module-reference"></span>
== [[#module-profile|<code>profile</code>]] and [[#module-cProfile|<code>cProfile</code>]] Module Reference ==
+
== profile cProfile 模块参考 ==
  
 
<span id="module-profile" class="target"></span>
 
<span id="module-profile" class="target"></span>
Both the [[#module-profile|<code>profile</code>]] and [[#module-cProfile|<code>cProfile</code>]] modules provide the following
+
[[#module-profile|profile]] [[#module-cProfile|cProfile]] 模块都提供以下功能:
functions:
 
  
 
<dl>
 
<dl>
<dt><code>profile.</code><code>run</code><span class="sig-paren">(</span>''<span class="n">command</span>'', ''<span class="n">filename</span><span class="o">=</span><span class="default_value">None</span>'', ''<span class="n">sort</span><span class="o">=</span><span class="default_value">- 1</span>''<span class="sig-paren">)</span></dt>
+
<dt><span class="sig-prename descclassname"><span class="pre">profile.</span></span><span class="sig-name descname"><span class="pre">run</span></span><span class="sig-paren">(</span>''<span class="n"><span class="pre">command</span></span>'', ''<span class="n"><span class="pre">filename</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span>'', ''<span class="n"><span class="pre">sort</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">-</span> <span class="pre">1</span></span>''<span class="sig-paren">)</span></dt>
<dd><p>This function takes a single argument that can be passed to the [[../functions#exec|<code>exec()</code>]]
+
<dd><p>这个函数接受一个可以传递给 [[../functions#exec|exec()]] 函数的参数和一个可选的文件名。 在所有情况下,此例程都执行:</p>
function, and an optional file name. In all cases this routine executes:</p>
 
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
  
 
<div class="highlight">
 
<div class="highlight">
  
<pre>exec(command, __main__.__dict__, __main__.__dict__)</pre>
+
<syntaxhighlight lang="python3">exec(command, __main__.__dict__, __main__.__dict__)</syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
<p>and gathers profiling statistics from the execution. If no file name is
+
<p>并从执行中收集分析统计信息。 如果没有文件名,那么这个函数会自动创建一个 [[#pstats.Stats|Stats]] 实例并打印一个简单的分析报告。 如果指定了排序值,则将其传递给此 [[#pstats.Stats|Stats]] 实例以控制结果的排序方式。</p></dd></dl>
present, then this function automatically creates a [[#pstats.Stats|<code>Stats</code>]]
 
instance and prints a simple profiling report. If the sort value is specified,
 
it is passed to this [[#pstats.Stats|<code>Stats</code>]] instance to control how the
 
results are sorted.</p></dd></dl>
 
  
 
<dl>
 
<dl>
<dt><code>profile.</code><code>runctx</code><span class="sig-paren">(</span>''<span class="n">command</span>'', ''<span class="n">globals</span>'', ''<span class="n">locals</span>'', ''<span class="n">filename</span><span class="o">=</span><span class="default_value">None</span>'', ''<span class="n">sort</span><span class="o">=</span><span class="default_value">- 1</span>''<span class="sig-paren">)</span></dt>
+
<dt><span class="sig-prename descclassname"><span class="pre">profile.</span></span><span class="sig-name descname"><span class="pre">runctx</span></span><span class="sig-paren">(</span>''<span class="n"><span class="pre">command</span></span>'', ''<span class="n"><span class="pre">globals</span></span>'', ''<span class="n"><span class="pre">locals</span></span>'', ''<span class="n"><span class="pre">filename</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span>'', ''<span class="n"><span class="pre">sort</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">-</span> <span class="pre">1</span></span>''<span class="sig-paren">)</span></dt>
<dd><p>This function is similar to [[#profile.run|<code>run()</code>]], with added arguments to supply the
+
<dd><p>此函数类似于 [[#profile.run|run()]],添加了参数以提供 ''command'' 字符串的全局和局部字典。 该例程执行:</p>
globals and locals dictionaries for the ''command'' string. This routine
 
executes:</p>
 
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
  
 
<div class="highlight">
 
<div class="highlight">
  
<pre>exec(command, globals, locals)</pre>
+
<syntaxhighlight lang="python3">exec(command, globals, locals)</syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
<p>and gathers profiling statistics as in the [[#profile.run|<code>run()</code>]] function above.</p></dd></dl>
+
<p>并像上面的 [[#profile.run|run()]] 函数一样收集分析统计信息。</p></dd></dl>
  
 
<dl>
 
<dl>
<dt>''class'' <code>profile.</code><code>Profile</code><span class="sig-paren">(</span>''<span class="n">timer</span><span class="o">=</span><span class="default_value">None</span>'', ''<span class="n">timeunit</span><span class="o">=</span><span class="default_value">0.0</span>'', ''<span class="n">subcalls</span><span class="o">=</span><span class="default_value">True</span>'', ''<span class="n">builtins</span><span class="o">=</span><span class="default_value">True</span>''<span class="sig-paren">)</span></dt>
+
<dt>''<span class="pre">class</span>'' <span class="sig-prename descclassname"><span class="pre">profile.</span></span><span class="sig-name descname"><span class="pre">Profile</span></span><span class="sig-paren">(</span>''<span class="n"><span class="pre">timer</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span>'', ''<span class="n"><span class="pre">timeunit</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">0.0</span></span>'', ''<span class="n"><span class="pre">subcalls</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">True</span></span>'', ''<span class="n"><span class="pre">builtins</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">True</span></span>''<span class="sig-paren">)</span></dt>
<dd><p>This class is normally only used if more precise control over profiling is
+
<dd><p>此类通常仅在需要比 <code>cProfile.run()</code> 函数提供的更精确的分析控制时才使用。</p>
needed than what the <code>cProfile.run()</code> function provides.</p>
+
<p>可以提供自定义计时器,用于通过 ''timer'' 参数测量代码运行所需的时间。 这必须是一个返回表示当前时间的单个数字的函数。 如果数字是整数,则 ''timeunit'' 指定一个乘数,用于指定每个时间单位的持续时间。 例如,如果计时器返回以千秒为单位测量的时间,则时间单位将为 <code>.001</code></p>
<p>A custom timer can be supplied for measuring how long code takes to run via
+
<p>直接使用 [[#profile.Profile|Profile]] 类允许在不将配置文件数据写入文件的情况下格式化配置文件结果:</p>
the ''timer'' argument. This must be a function that returns a single number
 
representing the current time. If the number is an integer, the ''timeunit''
 
specifies a multiplier that specifies the duration of each unit of time. For
 
example, if the timer returns times measured in thousands of seconds, the
 
time unit would be <code>.001</code>.</p>
 
<p>Directly using the [[#profile.Profile|<code>Profile</code>]] class allows formatting profile results
 
without writing the profile data to a file:</p>
 
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
  
 
<div class="highlight">
 
<div class="highlight">
  
<pre>import cProfile, pstats, io
+
<syntaxhighlight lang="python3">import cProfile, pstats, io
 
from pstats import SortKey
 
from pstats import SortKey
 
pr = cProfile.Profile()
 
pr = cProfile.Profile()
第356行: 第301行:
 
ps = pstats.Stats(pr, stream=s).sort_stats(sortby)
 
ps = pstats.Stats(pr, stream=s).sort_stats(sortby)
 
ps.print_stats()
 
ps.print_stats()
print(s.getvalue())</pre>
+
print(s.getvalue())</syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
<p>The [[#profile.Profile|<code>Profile</code>]] class can also be used as a context manager (supported
+
<p>[[#profile.Profile|Profile]] 类也可以用作上下文管理器(仅在 [[#module-cProfile|cProfile]] 模块中受支持。 参见 [[../stdtypes#typecontextmanager|上下文管理器类型]] ):</p>
only in [[#module-cProfile|<code>cProfile</code>]] module. see [[../stdtypes#typecontextmanager|<span class="std std-ref">Context Manager Types</span>]]):</p>
 
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
  
 
<div class="highlight">
 
<div class="highlight">
  
<pre>import cProfile
+
<syntaxhighlight lang="python3">import cProfile
  
 
with cProfile.Profile() as pr:
 
with cProfile.Profile() as pr:
 
     # ... do something ...
 
     # ... do something ...
  
pr.print_stats()</pre>
+
pr.print_stats()</syntaxhighlight>
  
 
</div>
 
</div>
第379行: 第323行:
 
<div class="versionchanged">
 
<div class="versionchanged">
  
<p><span class="versionmodified changed">3.8 版更改: </span>Added context manager support.</p>
+
<p><span class="versionmodified changed"> 3.8 版更改: </span> 添加了上下文管理器支持。</p>
  
 
</div>
 
</div>
 
<dl>
 
<dl>
<dt><code>enable</code><span class="sig-paren">(</span><span class="sig-paren">)</span></dt>
+
<dt><span class="sig-name descname"><span class="pre">enable</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span></dt>
<dd><p>Start collecting profiling data. Only in [[#module-cProfile|<code>cProfile</code>]].</p></dd></dl>
+
<dd><p>开始收集分析数据。 仅在 [[#module-cProfile|cProfile]] 中。</p></dd></dl>
  
 
<dl>
 
<dl>
<dt><code>disable</code><span class="sig-paren">(</span><span class="sig-paren">)</span></dt>
+
<dt><span class="sig-name descname"><span class="pre">disable</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span></dt>
<dd><p>Stop collecting profiling data. Only in [[#module-cProfile|<code>cProfile</code>]].</p></dd></dl>
+
<dd><p>停止收集分析数据。 仅在 [[#module-cProfile|cProfile]] 中。</p></dd></dl>
  
 
<dl>
 
<dl>
<dt><code>create_stats</code><span class="sig-paren">(</span><span class="sig-paren">)</span></dt>
+
<dt><span class="sig-name descname"><span class="pre">create_stats</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span></dt>
<dd><p>Stop collecting profiling data and record the results internally
+
<dd><p>停止收集分析数据并在内部将结果记录为当前分析。</p></dd></dl>
as the current profile.</p></dd></dl>
 
  
 
<dl>
 
<dl>
<dt><code>print_stats</code><span class="sig-paren">(</span>''<span class="n">sort</span><span class="o">=</span><span class="default_value">- 1</span>''<span class="sig-paren">)</span></dt>
+
<dt><span class="sig-name descname"><span class="pre">print_stats</span></span><span class="sig-paren">(</span>''<span class="n"><span class="pre">sort</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">-</span> <span class="pre">1</span></span>''<span class="sig-paren">)</span></dt>
<dd><p>Create a [[#pstats.Stats|<code>Stats</code>]] object based on the current
+
<dd><p>根据当前配置文件创建一个 [[#pstats.Stats|Stats]] 对象并将结果打印到标准输出。</p></dd></dl>
profile and print the results to stdout.</p></dd></dl>
 
  
 
<dl>
 
<dl>
<dt><code>dump_stats</code><span class="sig-paren">(</span>''<span class="n">filename</span>''<span class="sig-paren">)</span></dt>
+
<dt><span class="sig-name descname"><span class="pre">dump_stats</span></span><span class="sig-paren">(</span>''<span class="n"><span class="pre">filename</span></span>''<span class="sig-paren">)</span></dt>
<dd><p>Write the results of the current profile to ''filename''.</p></dd></dl>
+
<dd><p>将当前配置文件的结果写入 ''filename''</p></dd></dl>
  
 
<dl>
 
<dl>
<dt><code>run</code><span class="sig-paren">(</span>''<span class="n">cmd</span>''<span class="sig-paren">)</span></dt>
+
<dt><span class="sig-name descname"><span class="pre">run</span></span><span class="sig-paren">(</span>''<span class="n"><span class="pre">cmd</span></span>''<span class="sig-paren">)</span></dt>
<dd><p>Profile the cmd via [[../functions#exec|<code>exec()</code>]].</p></dd></dl>
+
<dd><p>通过 [[../functions#exec|exec()]] 分析 cmd。</p></dd></dl>
  
 
<dl>
 
<dl>
<dt><code>runctx</code><span class="sig-paren">(</span>''<span class="n">cmd</span>'', ''<span class="n">globals</span>'', ''<span class="n">locals</span>''<span class="sig-paren">)</span></dt>
+
<dt><span class="sig-name descname"><span class="pre">runctx</span></span><span class="sig-paren">(</span>''<span class="n"><span class="pre">cmd</span></span>'', ''<span class="n"><span class="pre">globals</span></span>'', ''<span class="n"><span class="pre">locals</span></span>''<span class="sig-paren">)</span></dt>
<dd><p>Profile the cmd via [[../functions#exec|<code>exec()</code>]] with the specified global and
+
<dd><p>通过 [[../functions#exec|exec()]] 使用指定的全局和本地环境分析 cmd。</p></dd></dl>
local environment.</p></dd></dl>
 
  
 
<dl>
 
<dl>
<dt><code>runcall</code><span class="sig-paren">(</span>''<span class="n">func</span>'', ''<span class="o">/</span>'', ''<span class="o">*</span><span class="n">args</span>'', ''<span class="o">**</span><span class="n">kwargs</span>''<span class="sig-paren">)</span></dt>
+
<dt><span class="sig-name descname"><span class="pre">runcall</span></span><span class="sig-paren">(</span>''<span class="n"><span class="pre">func</span></span>'', ''<span class="o"><span class="pre">/</span></span>'', ''<span class="o"><span class="pre">*</span></span><span class="n"><span class="pre">args</span></span>'', ''<span class="o"><span class="pre">**</span></span><span class="n"><span class="pre">kwargs</span></span>''<span class="sig-paren">)</span></dt>
<dd><p>Profile <code>func(*args, **kwargs)</code></p></dd></dl>
+
<dd><p>型材 <code>func(*args, **kwargs)</code></p></dd></dl>
 
</dd></dl>
 
</dd></dl>
  
Note that profiling will only work if the called command/function actually
+
请注意,仅当被调用的命令/函数实际返回时,分析才会起作用。 如果解释器被终止(例如 在被调用的命令/函数执行期间通过 [[../sys#sys|sys.exit()]] 调用)不会打印分析结果。
returns. If the interpreter is terminated (e.g. via a [[../sys#sys|<code>sys.exit()</code>]] call
 
during the called command/function execution) no profiling results will be
 
printed.
 
  
  
第428行: 第366行:
  
 
<span id="profile-stats"></span>
 
<span id="profile-stats"></span>
== The <code>Stats</code> Class ==
+
== Stats ==
  
Analysis of the profiler data is done using the [[#pstats.Stats|<code>Stats</code>]] class.
+
分析器数据的分析是使用 [[#pstats.Stats|Stats]] 类完成的。
  
 
<span id="module-pstats" class="target"></span>
 
<span id="module-pstats" class="target"></span>
 
<dl>
 
<dl>
<dt>''class'' <code>pstats.</code><code>Stats</code><span class="sig-paren">(</span>''*filenames or profile'', ''stream=sys.stdout''<span class="sig-paren">)</span></dt>
+
<dt>''<span class="pre">class</span>'' <span class="sig-prename descclassname"><span class="pre">pstats.</span></span><span class="sig-name descname"><span class="pre">Stats</span></span><span class="sig-paren">(</span>''<span class="pre">*filenames</span> <span class="pre">or</span> <span class="pre">profile</span>'', ''<span class="pre">stream=sys.stdout</span>''<span class="sig-paren">)</span></dt>
<dd><p>This class constructor creates an instance of a &quot;statistics object&quot; from a
+
<dd><p>此类构造函数从 ''文件名'' (或文件名列表)或 <code>Profile</code> 实例创建“统计对象”的实例。 输出将打印到 ''stream'' 指定的流。</p>
''filename'' (or list of filenames) or from a <code>Profile</code> instance. Output
+
<p>上述构造函数选择的文件必须是由[[#module-profile|profile]][[#module-cProfile|cProfile]]对应版本创建的。 具体来说,''no'' 文件兼容性保证与此分析器的未来版本,并且与其他分析器生成的文件或在不同操作系统上运行的相同分析器不兼容。 如果提供多个文件,则将合并相同功能的所有统计信息,以便在单个报告中考虑多个流程的整体视图。 如果其他文件需要与现有 [[#pstats.Stats|Stats]] 对象中的数据合并,则可以使用 [[#pstats.Stats.add|add()]] 方法。</p>
will be printed to the stream specified by ''stream''.</p>
+
<p><code>cProfile.Profile</code> [[#profile.Profile|profile.Profile]] 对象可以用作配置文件数据源,而不是从文件中读取配置文件数据。</p>
<p>The file selected by the above constructor must have been created by the
+
<p>[[#pstats.Stats|Stats]] 对象有以下方法:</p>
corresponding version of [[#module-profile|<code>profile</code>]] or [[#module-cProfile|<code>cProfile</code>]]. To be specific,
 
there is ''no'' file compatibility guaranteed with future versions of this
 
profiler, and there is no compatibility with files produced by other
 
profilers, or the same profiler run on a different operating system. If
 
several files are provided, all the statistics for identical functions will
 
be coalesced, so that an overall view of several processes can be considered
 
in a single report. If additional files need to be combined with data in an
 
existing [[#pstats.Stats|<code>Stats</code>]] object, the [[#pstats.Stats.add|<code>add()</code>]] method
 
can be used.</p>
 
<p>Instead of reading the profile data from a file, a <code>cProfile.Profile</code>
 
or [[#profile.Profile|<code>profile.Profile</code>]] object can be used as the profile data source.</p>
 
<p>[[#pstats.Stats|<code>Stats</code>]] objects have the following methods:</p>
 
 
<dl>
 
<dl>
<dt><code>strip_dirs</code><span class="sig-paren">(</span><span class="sig-paren">)</span></dt>
+
<dt><span class="sig-name descname"><span class="pre">strip_dirs</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span></dt>
<dd><p>This method for the [[#pstats.Stats|<code>Stats</code>]] class removes all leading path
+
<dd><p>[[#pstats.Stats|Stats]] 类的此方法从文件名中删除所有前导路径信息。 这对于减小打印输出的大小以适应(接近)80 列非常有用。 该方法修改对象,剥离的信息丢失。 执行剥离操作后,该对象被认为具有“随机”顺序的条目,就像在对象初始化和加载之后一样。 如果 [[#pstats.Stats.strip_dirs|strip_dirs()]] 导致两个函数名无法区分(它们在同一个文件名的同一行,并且具有相同的函数名),则将这两个条目的统计信息累加到一个条目中.</p></dd></dl>
information from file names. It is very useful in reducing the size of
 
the printout to fit within (close to) 80 columns. This method modifies
 
the object, and the stripped information is lost. After performing a
 
strip operation, the object is considered to have its entries in a
 
&quot;random&quot; order, as it was just after object initialization and loading.
 
If [[#pstats.Stats.strip_dirs|<code>strip_dirs()</code>]] causes two function names to be
 
indistinguishable (they are on the same line of the same filename, and
 
have the same function name), then the statistics for these two entries
 
are accumulated into a single entry.</p></dd></dl>
 
  
 
<dl>
 
<dl>
<dt><code>add</code><span class="sig-paren">(</span>''<span class="o">*</span><span class="n">filenames</span>''<span class="sig-paren">)</span></dt>
+
<dt><span class="sig-name descname"><span class="pre">add</span></span><span class="sig-paren">(</span>''<span class="o"><span class="pre">*</span></span><span class="n"><span class="pre">filenames</span></span>''<span class="sig-paren">)</span></dt>
<dd><p>This method of the [[#pstats.Stats|<code>Stats</code>]] class accumulates additional profiling
+
<dd><p>[[#pstats.Stats|Stats]] 类的这个方法将额外的分析信息累积到当前分析对象中。 它的参数应该引用由 [[#profile.run|profile.run()]] <code>cProfile.run()</code> 的相应版本创建的文件名。 同名(re:文件、行、名称)函数的统计信息会自动累积到单个函数统计信息中。</p></dd></dl>
information into the current profiling object. Its arguments should refer
 
to filenames created by the corresponding version of [[#profile.run|<code>profile.run()</code>]]
 
or <code>cProfile.run()</code>. Statistics for identically named (re: file, line,
 
name) functions are automatically accumulated into single function
 
statistics.</p></dd></dl>
 
  
 
<dl>
 
<dl>
<dt><code>dump_stats</code><span class="sig-paren">(</span>''<span class="n">filename</span>''<span class="sig-paren">)</span></dt>
+
<dt><span class="sig-name descname"><span class="pre">dump_stats</span></span><span class="sig-paren">(</span>''<span class="n"><span class="pre">filename</span></span>''<span class="sig-paren">)</span></dt>
<dd><p>Save the data loaded into the [[#pstats.Stats|<code>Stats</code>]] object to a file named
+
<dd><p>将加载到 [[#pstats.Stats|Stats]] 对象中的数据保存到名为 ''filename'' 的文件中。 如果文件不存在,则创建该文件,如果已存在,则覆盖该文件。 这相当于 [[#profile.Profile|profile.Profile]] <code>cProfile.Profile</code> 类上的同名方法。</p></dd></dl>
''filename''. The file is created if it does not exist, and is overwritten
 
if it already exists. This is equivalent to the method of the same name
 
on the [[#profile.Profile|<code>profile.Profile</code>]] and <code>cProfile.Profile</code> classes.</p></dd></dl>
 
  
 
<dl>
 
<dl>
<dt><code>sort_stats</code><span class="sig-paren">(</span>''<span class="o">*</span><span class="n">keys</span>''<span class="sig-paren">)</span></dt>
+
<dt><span class="sig-name descname"><span class="pre">sort_stats</span></span><span class="sig-paren">(</span>''<span class="o"><span class="pre">*</span></span><span class="n"><span class="pre">keys</span></span>''<span class="sig-paren">)</span></dt>
<dd><p>This method modifies the [[#pstats.Stats|<code>Stats</code>]] object by sorting it according to
+
<dd><p>此方法通过根据提供的标准对其进行排序来修改 [[#pstats.Stats|Stats]] 对象。 参数可以是字符串或用于标识排序基础的 SortKey 枚举(例如:<code>'time'</code><code>'name'</code><code>SortKey.TIME</code> <code>SortKey.NAME</code>)。 SortKey 枚举参数优于字符串参数,因为它更健壮且不易出错。</p>
the supplied criteria. The argument can be either a string or a SortKey
+
<p>当提供了多个键时,如果在它们之前选择的所有键都相等,则附加键将用作次要条件。 例如,<code>sort_stats(SortKey.NAME, SortKey.FILE)</code> 将根据函数名对所有条目进行排序,并通过按文件名排序来解析所有关系(相同的函数名)。</p>
enum identifying the basis of a sort (example: <code>'time'</code>, <code>'name'</code>,
+
<p>对于字符串参数,任何键名都可以使用缩写,只要缩写是明确的。</p>
<code>SortKey.TIME</code> or <code>SortKey.NAME</code>). The SortKey enums argument have
+
<p>以下是有效的字符串和 SortKey:</p>
advantage over the string argument in that it is more robust and less
 
error prone.</p>
 
<p>When more than one key is provided, then additional keys are used as
 
secondary criteria when there is equality in all keys selected before
 
them. For example, <code>sort_stats(SortKey.NAME, SortKey.FILE)</code> will sort
 
all the entries according to their function name, and resolve all ties
 
(identical function names) by sorting by file name.</p>
 
<p>For the string argument, abbreviations can be used for any key names, as
 
long as the abbreviation is unambiguous.</p>
 
<p>The following are the valid string and SortKey:</p>
 
 
{|
 
{|
!width="30%"| <p>Valid String Arg</p>
+
!width="30%"| <p>有效字符串参数</p>
!width="34%"| <p>Valid enum Arg</p>
+
!width="34%"| <p>有效的枚举参数</p>
!width="36%"| <p>Meaning</p>
+
!width="36%"| <p>意义</p>
 
|-
 
|-
 
| <p><code>'calls'</code></p>
 
| <p><code>'calls'</code></p>
| <p>SortKey.CALLS</p>
+
| <p>排序键调用</p>
| <p>call count</p>
+
| <p>呼叫计数</p>
 
|-
 
|-
 
| <p><code>'cumulative'</code></p>
 
| <p><code>'cumulative'</code></p>
| <p>SortKey.CUMULATIVE</p>
+
| <p>排序键.累积</p>
| <p>cumulative time</p>
+
| <p>累计时间</p>
 
|-
 
|-
 
| <p><code>'cumtime'</code></p>
 
| <p><code>'cumtime'</code></p>
| <p>N/A</p>
+
| <p>不适用</p>
| <p>cumulative time</p>
+
| <p>累计时间</p>
 
|-
 
|-
 
| <p><code>'file'</code></p>
 
| <p><code>'file'</code></p>
| <p>N/A</p>
+
| <p>不适用</p>
| <p>file name</p>
+
| <p>文件名</p>
 
|-
 
|-
 
| <p><code>'filename'</code></p>
 
| <p><code>'filename'</code></p>
 
| <p>SortKey.FILENAME</p>
 
| <p>SortKey.FILENAME</p>
| <p>file name</p>
+
| <p>文件名</p>
 
|-
 
|-
 
| <p><code>'module'</code></p>
 
| <p><code>'module'</code></p>
| <p>N/A</p>
+
| <p>不适用</p>
| <p>file name</p>
+
| <p>文件名</p>
 
|-
 
|-
 
| <p><code>'ncalls'</code></p>
 
| <p><code>'ncalls'</code></p>
| <p>N/A</p>
+
| <p>不适用</p>
| <p>call count</p>
+
| <p>呼叫计数</p>
 
|-
 
|-
 
| <p><code>'pcalls'</code></p>
 
| <p><code>'pcalls'</code></p>
| <p>SortKey.PCALLS</p>
+
| <p>排序键.PCALLS</p>
| <p>primitive call count</p>
+
| <p>原始调用计数</p>
 
|-
 
|-
 
| <p><code>'line'</code></p>
 
| <p><code>'line'</code></p>
| <p>SortKey.LINE</p>
+
| <p>排序键.LINE</p>
| <p>line number</p>
+
| <p>电话号码</p>
 
|-
 
|-
 
| <p><code>'name'</code></p>
 
| <p><code>'name'</code></p>
| <p>SortKey.NAME</p>
+
| <p>排序键.NAME</p>
| <p>function name</p>
+
| <p>函数名</p>
 
|-
 
|-
 
| <p><code>'nfl'</code></p>
 
| <p><code>'nfl'</code></p>
| <p>SortKey.NFL</p>
+
| <p>排序键.NFL</p>
| <p>name/file/line</p>
+
| <p>名称/文件/</p>
 
|-
 
|-
 
| <p><code>'stdname'</code></p>
 
| <p><code>'stdname'</code></p>
 
| <p>SortKey.STDNAME</p>
 
| <p>SortKey.STDNAME</p>
| <p>standard name</p>
+
| <p>标准名称</p>
 
|-
 
|-
 
| <p><code>'time'</code></p>
 
| <p><code>'time'</code></p>
| <p>SortKey.TIME</p>
+
| <p>排序键.TIME</p>
| <p>internal time</p>
+
| <p>内部时间</p>
 
|-
 
|-
 
| <p><code>'tottime'</code></p>
 
| <p><code>'tottime'</code></p>
| <p>N/A</p>
+
| <p>不适用</p>
| <p>internal time</p>
+
| <p>内部时间</p>
 
|}
 
|}
  
<p>Note that all sorts on statistics are in descending order (placing most
+
<p>请注意,统计信息的所有排序均按降序排列(将最耗时的项目放在最前面),其中名称、文件和行号搜索按升序排列(按字母顺序)。 <code>SortKey.NFL</code> <code>SortKey.STDNAME</code> 之间的细微区别在于标准名称是一种打印名称,这意味着嵌入的行号以一种奇怪的方式进行比较。 例如,第 3、20 和 40 行(如果文件名相同)将以字符串顺序 20、3 和 40 出现。 相比之下, <code>SortKey.NFL</code> 对行号进行数字比较。 实际上,<code>sort_stats(SortKey.NFL)</code> <code>sort_stats(SortKey.NAME, SortKey.FILENAME, SortKey.LINE)</code> 是一样的。</p>
time consuming items first), where as name, file, and line number searches
+
<p>出于向后兼容性的原因,允许使用数字参数 <code>-1</code><code>0</code><code>1</code> <code>2</code>。 它们分别被解释为 <code>'stdname'</code><code>'calls'</code><code>'time'</code> <code>'cumulative'</code>。 如果使用这种旧样式格式(数字),则只会使用一个排序键(数字键),并且其他参数将被静默忽略。</p>
are in ascending order (alphabetical). The subtle distinction between
 
<code>SortKey.NFL</code> and <code>SortKey.STDNAME</code> is that the standard name is a
 
sort of the name as printed, which means that the embedded line numbers
 
get compared in an odd way. For example, lines 3, 20, and 40 would (if
 
the file names were the same) appear in the string order 20, 3 and 40.
 
In contrast, <code>SortKey.NFL</code> does a numeric compare of the line numbers.
 
In fact, <code>sort_stats(SortKey.NFL)</code> is the same as
 
<code>sort_stats(SortKey.NAME, SortKey.FILENAME, SortKey.LINE)</code>.</p>
 
<p>For backward-compatibility reasons, the numeric arguments <code>-1</code>, <code>0</code>,
 
<code>1</code>, and <code>2</code> are permitted. They are interpreted as <code>'stdname'</code>,
 
<code>'calls'</code>, <code>'time'</code>, and <code>'cumulative'</code> respectively. If this old
 
style format (numeric) is used, only one sort key (the numeric key) will
 
be used, and additional arguments will be silently ignored.</p>
 
 
<div class="versionadded">
 
<div class="versionadded">
  
<p><span class="versionmodified added">3.7 新版功能: </span>Added the SortKey enum.</p>
+
<p><span class="versionmodified added"> 3.7 新功能: </span> 增加了 SortKey 枚举。</p>
  
 
</div></dd></dl>
 
</div></dd></dl>
  
 
<dl>
 
<dl>
<dt><code>reverse_order</code><span class="sig-paren">(</span><span class="sig-paren">)</span></dt>
+
<dt><span class="sig-name descname"><span class="pre">reverse_order</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span></dt>
<dd><p>This method for the [[#pstats.Stats|<code>Stats</code>]] class reverses the ordering of the
+
<dd><p>[[#pstats.Stats|Stats]] 类的此方法颠倒了对象内基本列表的顺序。 请注意,默认情况下,根据选择的排序键正确选择升序与降序。</p></dd></dl>
basic list within the object. Note that by default ascending vs
 
descending order is properly selected based on the sort key of choice.</p></dd></dl>
 
  
 
<dl>
 
<dl>
<dt><code>print_stats</code><span class="sig-paren">(</span>''<span class="o">*</span><span class="n">restrictions</span>''<span class="sig-paren">)</span></dt>
+
<dt><span class="sig-name descname"><span class="pre">print_stats</span></span><span class="sig-paren">(</span>''<span class="o"><span class="pre">*</span></span><span class="n"><span class="pre">restrictions</span></span>''<span class="sig-paren">)</span></dt>
<dd><p>This method for the [[#pstats.Stats|<code>Stats</code>]] class prints out a report as described
+
<dd><p>[[#pstats.Stats|Stats]] 类的这个方法打印出一个报告,如 [[#profile.run|profile.run()]] 定义中所述。</p>
in the [[#profile.run|<code>profile.run()</code>]] definition.</p>
+
<p>打印顺序基于对对象执行的最后一次 [[#pstats.Stats.sort_stats|sort_stats()]] 操作(受 [[#pstats.Stats.add|add()]] [[#pstats.Stats.strip_dirs|strip_dirs()]] 中的警告影响)。</p>
<p>The order of the printing is based on the last
+
<p>提供的参数(如果有)可用于将列表限制为重要条目。 最初,该列表被视为完整的分析函数集。 每个限制要么是一个整数(选择行数),要么是介于 0.0 1.0 之间的小数(包括行数),或者是一个将解释为正则表达式的字符串(以模式匹配标准名称)打印出来的)。 如果提供了多个限制,则它们将按顺序应用。 例如:</p>
[[#pstats.Stats.sort_stats|<code>sort_stats()</code>]] operation done on the object (subject to
 
caveats in [[#pstats.Stats.add|<code>add()</code>]] and
 
[[#pstats.Stats.strip_dirs|<code>strip_dirs()</code>]]).</p>
 
<p>The arguments provided (if any) can be used to limit the list down to the
 
significant entries. Initially, the list is taken to be the complete set
 
of profiled functions. Each restriction is either an integer (to select a
 
count of lines), or a decimal fraction between 0.0 and 1.0 inclusive (to
 
select a percentage of lines), or a string that will interpreted as a
 
regular expression (to pattern match the standard name that is printed).
 
If several restrictions are provided, then they are applied sequentially.
 
For example:</p>
 
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
  
 
<div class="highlight">
 
<div class="highlight">
  
<pre>print_stats(.1, 'foo:')</pre>
+
<syntaxhighlight lang="python3">print_stats(.1, 'foo:')</syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
<p>would first limit the printing to first 10% of list, and then only print
+
<p>将首先限制打印到第一个 10% of 列表,然后只打印属于文件名 <code>.*foo:</code> 的函数。 相比之下,命令:</p>
functions that were part of filename <code>.*foo:</code>. In contrast, the
 
command:</p>
 
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
  
 
<div class="highlight">
 
<div class="highlight">
  
<pre>print_stats('foo:', .1)</pre>
+
<syntaxhighlight lang="python3">print_stats('foo:', .1)</syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
<p>would limit the list to all functions having file names <code>.*foo:</code>,
+
<p>会将列表限制为具有文件名 <code>.*foo:</code> 的所有函数,然后继续仅打印前 10% of 个函数。</p></dd></dl>
and then proceed to only print the first 10% of them.</p></dd></dl>
 
  
 
<dl>
 
<dl>
<dt><code>print_callers</code><span class="sig-paren">(</span>''<span class="o">*</span><span class="n">restrictions</span>''<span class="sig-paren">)</span></dt>
+
<dt><span class="sig-name descname"><span class="pre">print_callers</span></span><span class="sig-paren">(</span>''<span class="o"><span class="pre">*</span></span><span class="n"><span class="pre">restrictions</span></span>''<span class="sig-paren">)</span></dt>
<dd><p>This method for the [[#pstats.Stats|<code>Stats</code>]] class prints a list of all functions
+
<dd><p>[[#pstats.Stats|Stats]] 类的这个方法打印了所有函数的列表,这些函数调用了分析数据库中的每个函数。 顺序与 [[#pstats.Stats.print_stats|print_stats()]] 提供的相同,并且限制参数的定义也相同。 每个呼叫者都在自己的线路上报告。 根据生成统计信息的分析器,格式略有不同:</p>
that called each function in the profiled database. The ordering is
 
identical to that provided by [[#pstats.Stats.print_stats|<code>print_stats()</code>]], and the
 
definition of the restricting argument is also identical. Each caller is
 
reported on its own line. The format differs slightly depending on the
 
profiler that produced the stats:</p>
 
 
<ul>
 
<ul>
<li><p>With [[#module-profile|<code>profile</code>]], a number is shown in parentheses after each caller
+
<li><p>对于 [[#module-profile|profile]],每个呼叫者后面的括号中会显示一个数字,以显示进行了该特定呼叫的次数。 为方便起见,第二个无括号的数字重复在右侧函数中花费的累积时间。</p></li>
to show how many times this specific call was made. For convenience, a
+
<li><p>使用 [[#module-cProfile|cProfile]],每个调用者前面都有三个数字:进行此特定调用的次数,以及在此特定调用者调用当前函数时在当前函数中花费的总时间和累计时间。</p></li></ul>
second non-parenthesized number repeats the cumulative time spent in the
 
function at the right.</p></li>
 
<li><p>With [[#module-cProfile|<code>cProfile</code>]], each caller is preceded by three numbers: the
 
number of times this specific call was made, and the total and
 
cumulative times spent in the current function while it was invoked by
 
this specific caller.</p></li></ul>
 
 
</dd></dl>
 
</dd></dl>
  
 
<dl>
 
<dl>
<dt><code>print_callees</code><span class="sig-paren">(</span>''<span class="o">*</span><span class="n">restrictions</span>''<span class="sig-paren">)</span></dt>
+
<dt><span class="sig-name descname"><span class="pre">print_callees</span></span><span class="sig-paren">(</span>''<span class="o"><span class="pre">*</span></span><span class="n"><span class="pre">restrictions</span></span>''<span class="sig-paren">)</span></dt>
<dd><blockquote><div>
+
<dd><p>[[#pstats.Stats|Stats]] 类的此方法打印指定函数调用的所有函数的列表。 除了调用方向的这种反转(重新:被调用与被调用),参数和顺序与 [[#pstats.Stats.print_callers|print_callers()]] 方法相同。</p></dd></dl>
 
 
<p>This method for the [[#pstats.Stats|<code>Stats</code>]] class prints a list of all function
 
that were called by the indicated function. Aside from this reversal of
 
direction of calls (re: called vs was called by), the arguments and
 
ordering are identical to the [[#pstats.Stats.print_callers|<code>print_callers()</code>]] method.</p>
 
  
</div></blockquote>
 
 
<dl>
 
<dl>
<dt><code>get_stats_profile</code><span class="sig-paren">(</span><span class="sig-paren">)</span></dt>
+
<dt><span class="sig-name descname"><span class="pre">get_stats_profile</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span></dt>
<dd><p>This method returns an instance of StatsProfile, which contains a mapping
+
<dd><p>此方法返回 StatsProfile 的实例,其中包含函数名称到 FunctionProfile 实例的映射。 每个 FunctionProfile 实例都包含与函数配置文件相关的信息,例如函数运行的时间、调用的次数等……</p>
of function names to instances of FunctionProfile. Each FunctionProfile
 
instance holds information related to the function's profile such as how
 
long the function took to run, how many times it was called, etc...</p>
 
<blockquote><div>
 
 
 
 
<div class="versionadded">
 
<div class="versionadded">
  
<p><span class="versionmodified added">3.9 新版功能: </span>Added the following dataclasses: StatsProfile, FunctionProfile.
+
<p><span class="versionmodified added"> 3.9 新功能: </span> 添加以下数据类:StatsProfile、FunctionProfile。 添加了以下函数:get_stats_profile。</p>
Added the following function: get_stats_profile.</p>
 
  
</div>
+
</div></dd></dl>
 
 
</div></blockquote></dd></dl>
 
</dd></dl>
 
 
</dd></dl>
 
</dd></dl>
  
第678行: 第522行:
  
 
<span id="deterministic-profiling"></span>
 
<span id="deterministic-profiling"></span>
== What Is Deterministic Profiling? ==
+
== 什么是确定性分析? ==
  
''Deterministic profiling'' is meant to reflect the fact that all ''function
+
''确定性分析''旨在反映以下事实:所有''函数调用''''函数返回''''异常''事件都受到监控,并且精确计时为这些事件之间的间隔(在这段时间内用户的代码正在执行)。 相比之下,''statistical profiling''(不是由这个模块完成的)随机采样有效指令指针,并推断出时间花费在哪里。 后一种技术传统上涉及较少的开销(因为不需要检测代码),但仅提供时间花在何处的相对指示。
call'', ''function return'', and ''exception'' events are monitored, and precise
 
timings are made for the intervals between these events (during which time the
 
user's code is executing). In contrast, ''statistical profiling'' (which is
 
not done by this module) randomly samples the effective instruction pointer, and
 
deduces where time is being spent. The latter technique traditionally involves
 
less overhead (as the code does not need to be instrumented), but provides only
 
relative indications of where time is being spent.
 
  
In Python, since there is an interpreter active during execution, the presence
+
Python 中,由于在执行期间有一个解释器处于活动状态,因此不需要存在检测代码来进行确定性分析。 Python 自动为每个事件提供一个 ''hook''(可选回调)。 此外,Python 的解释性质往往会给执行增加如此多的开销,以至于确定性分析往往只会在典型应用程序中增加很小的处理开销。 结果是确定性分析并不那么昂贵,但提供了有关 Python 程序执行的大量运行时统计信息。
of instrumented code is not required in order to do deterministic profiling.
 
Python automatically provides a ''hook'' (optional callback) for each event.
 
In addition, the interpreted nature of Python tends to add so much overhead to
 
execution, that deterministic profiling tends to only add small processing
 
overhead in typical applications. The result is that deterministic profiling is
 
not that expensive, yet provides extensive run time statistics about the
 
execution of a Python program.
 
  
Call count statistics can be used to identify bugs in code (surprising counts),
+
调用计数统计可用于识别代码中的错误(令人惊讶的计数),并识别可能的内联扩展点(高调用计数)。 内部时间统计可用于识别应仔细优化的“热循环”。 应使用累积时间统计来识别算法选择中的高级错误。 请注意,此分析器中对累积时间的异常处理允许将算法的递归实现的统计信息直接与迭代实现进行比较。
and to identify possible inline-expansion points (high call counts). Internal
 
time statistics can be used to identify &quot;hot loops&quot; that should be carefully
 
optimized. Cumulative time statistics should be used to identify high level
 
errors in the selection of algorithms. Note that the unusual handling of
 
cumulative times in this profiler allows statistics for recursive
 
implementations of algorithms to be directly compared to iterative
 
implementations.
 
  
  
第712行: 第535行:
  
 
<span id="profile-limitations"></span>
 
<span id="profile-limitations"></span>
== Limitations ==
+
== 限制 ==
  
One limitation has to do with accuracy of timing information. There is a
+
一个限制与计时信息的准确性有关。 确定性分析器存在一个涉及准确性的基本问题。 最明显的限制是底层“时钟”仅以大约 0.001 秒的速率(通常)滴答作响。 因此,没有任何测量会比基础时钟更准确。 如果进行了足够的测量,那么“误差”将趋于平均。 不幸的是,消除第一个错误会导致第二个错误源。
fundamental problem with deterministic profilers involving accuracy. The most
 
obvious restriction is that the underlying &quot;clock&quot; is only ticking at a rate
 
(typically) of about .001 seconds. Hence no measurements will be more accurate
 
than the underlying clock. If enough measurements are taken, then the &quot;error&quot;
 
will tend to average out. Unfortunately, removing this first error induces a
 
second source of error.
 
  
The second problem is that it &quot;takes a while&quot; from when an event is dispatched
+
第二个问题是从调度事件到分析器调用获取时间实际上 ''获取'' 时钟状态“需要一段时间”。 类似地,从获取时钟值(然后撤回)到用户代码再次执行,退出分析器事件处理程序也有一定的延迟。 因此,多次调用或调用许多函数的函数通常会累积此错误。 以这种方式累积的误差通常小于时钟的精度(小于一个时钟滴答),但它 ''可以'' 累积并变得非常重要。
until the profiler's call to get the time actually ''gets'' the state of the
 
clock. Similarly, there is a certain lag when exiting the profiler event
 
handler from the time that the clock's value was obtained (and then squirreled
 
away), until the user's code is once again executing. As a result, functions
 
that are called many times, or call many functions, will typically accumulate
 
this error. The error that accumulates in this fashion is typically less than
 
the accuracy of the clock (less than one clock tick), but it ''can'' accumulate
 
and become very significant.
 
  
The problem is more important with [[#module-profile|<code>profile</code>]] than with the lower-overhead
+
[[#module-profile|profile]] 的问题比开销较低的 [[#module-cProfile|cProfile]] 更重要。 出于这个原因,[[#module-profile|profile]] 提供了一种针对给定平台校准自身的方法,以便可以概率地(平均地)消除此错误。 分析器校准后,它会更准确(在最小二乘意义上),但有时会产生负数(当调用计数异常低时,概率之神对你不利:-)。 ) 不要''不要''被配置文件中的负数吓到。 如果您已经校准了分析器,它们应该 ''only'' 出现,并且结果实际上比没有校准要好。
[[#module-cProfile|<code>cProfile</code>]]. For this reason, [[#module-profile|<code>profile</code>]] provides a means of
 
calibrating itself for a given platform so that this error can be
 
probabilistically (on the average) removed. After the profiler is calibrated, it
 
will be more accurate (in a least square sense), but it will sometimes produce
 
negative numbers (when call counts are exceptionally low, and the gods of
 
probability work against you :-). ) Do ''not'' be alarmed by negative numbers in
 
the profile. They should ''only'' appear if you have calibrated your profiler,
 
and the results are actually better than without calibration.
 
  
  
第747行: 第548行:
  
 
<span id="profile-calibration"></span>
 
<span id="profile-calibration"></span>
== Calibration ==
+
== 校准 ==
  
The profiler of the [[#module-profile|<code>profile</code>]] module subtracts a constant from each event
+
[[#module-profile|profile]] 模块的分析器从每个事件处理时间中减去一个常量,以补偿调用 time 函数和存储结果的开销。 默认情况下,常量为 0。 以下过程可用于为给定平台获得更好的常数(请参阅 [[#profile-limitations|限制]] )。
handling time to compensate for the overhead of calling the time function, and
 
socking away the results. By default, the constant is 0. The following
 
procedure can be used to obtain a better constant for a given platform (see
 
[[#profile-limitations|<span class="std std-ref">Limitations</span>]]).
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第759行: 第556行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>import profile
+
<syntaxhighlight lang="python3">import profile
 
pr = profile.Profile()
 
pr = profile.Profile()
 
for i in range(5):
 
for i in range(5):
     print(pr.calibrate(10000))</pre>
+
     print(pr.calibrate(10000))</syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
The method executes the number of Python calls given by the argument, directly
+
该方法直接在探查器下执行参数给出的 Python 调用次数,并测量两者的时间。 然后计算每个分析器事件的隐藏开销,并将其作为浮点数返回。 例如,在运行 macOS 的 1.8Ghz Intel Core i5 上,使用 Python time.process_time() 作为计时器,神奇数字约为 4.04e-6。
and again under the profiler, measuring the time for both. It then computes the
 
hidden overhead per profiler event, and returns that as a float. For example,
 
on a 1.8Ghz Intel Core i5 running Mac OS X, and using Python's time.process_time() as
 
the timer, the magical number is about 4.04e-6.
 
  
The object of this exercise is to get a fairly consistent result. If your
+
这个练习的目的是获得一个相当一致的结果。 如果您的计算机 ''非常'' 快,或者您的计时器功能分辨率不佳,您可能需要通过 100000,甚至 1000000,才能获得一致的结果。
computer is ''very'' fast, or your timer function has poor resolution, you might
 
have to pass 100000, or even 1000000, to get consistent results.
 
  
When you have a consistent answer, there are three ways you can use it:
+
当你有一个一致的答案时,你可以通过三种方式使用它:
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第783行: 第574行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>import profile
+
<syntaxhighlight lang="python3">import profile
  
 
# 1. Apply computed bias to all Profile instances created hereafter.
 
# 1. Apply computed bias to all Profile instances created hereafter.
第793行: 第584行:
  
 
# 3. Specify computed bias in instance constructor.
 
# 3. Specify computed bias in instance constructor.
pr = profile.Profile(bias=your_computed_bias)</pre>
+
pr = profile.Profile(bias=your_computed_bias)</syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
If you have a choice, you are better off choosing a smaller constant, and then
+
如果您有选择,您最好选择一个较小的常数,这样您的结果将“较少”在配置文件统计中显示为负数。
your results will &quot;less often&quot; show up as negative in profile statistics.
 
  
  
第806行: 第596行:
  
 
<span id="profile-timers"></span>
 
<span id="profile-timers"></span>
== Using a custom timer ==
+
== 使用自定义计时器 ==
  
If you want to change how current time is determined (for example, to force use
+
如果要更改确定当前时间的方式(例如,强制使用挂钟时间或经过的处理时间),请将所需的计时函数传递给 <code>Profile</code> 类构造函数:
of wall-clock time or elapsed process time), pass the timing function you want
 
to the <code>Profile</code> class constructor:
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第816行: 第604行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>pr = profile.Profile(your_time_func)</pre>
+
<syntaxhighlight lang="python3">pr = profile.Profile(your_time_func)</syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
The resulting profiler will then call <code>your_time_func</code>. Depending on whether
+
然后生成的分析器将调用 <code>your_time_func</code>。 根据您使用的是 [[#profile.Profile|profile.Profile]] 还是 <code>cProfile.Profile</code><code>your_time_func</code> 的返回值将有不同的解释:
you are using [[#profile.Profile|<code>profile.Profile</code>]] or <code>cProfile.Profile</code>,
 
<code>your_time_func</code>'s return value will be interpreted differently:
 
  
 
<dl>
 
<dl>
 
<dt>[[#profile.Profile|<code>profile.Profile</code>]]</dt>
 
<dt>[[#profile.Profile|<code>profile.Profile</code>]]</dt>
<dd><p><code>your_time_func</code> should return a single number, or a list of numbers whose
+
<dd><p><code>your_time_func</code> 应该返回一个数字,或者一个数字列表,其总和是当前时间(就像 [[../os#os|os.times()]] 返回的)。 如果函数返回单个时间数字,或者返回数字列表的长度为 2,那么您将获得调度例程的特别快速版本。</p>
sum is the current time (like what [[../os#os|<code>os.times()</code>]] returns). If the
+
<p>请注意,您应该为您选择的计时器函数校准分析器类(请参阅 [[#profile-calibration|Calibration]])。 对于大多数机器,返回一个单独的整数值的计时器将在分析期间提供低开销方面的最佳结果。 ([[../os#os|os.times()]] ''pretty'' 不好,因为它返回一个浮点值元组)。 如果您想以最简洁的方式替换更好的计时器,请派生一个类并硬连接一个最能处理您的计时器调用的替换调度方法,以及适当的校准常量。</p></dd>
function returns a single time number, or the list of returned numbers has
 
length 2, then you will get an especially fast version of the dispatch
 
routine.</p>
 
<p>Be warned that you should calibrate the profiler class for the timer function
 
that you choose (see [[#profile-calibration|<span class="std std-ref">Calibration</span>]]). For most machines, a timer
 
that returns a lone integer value will provide the best results in terms of
 
low overhead during profiling. ([[../os#os|<code>os.times()</code>]] is ''pretty'' bad, as it
 
returns a tuple of floating point values). If you want to substitute a
 
better timer in the cleanest fashion, derive a class and hardwire a
 
replacement dispatch method that best handles your timer call, along with the
 
appropriate calibration constant.</p></dd>
 
 
<dt><code>cProfile.Profile</code></dt>
 
<dt><code>cProfile.Profile</code></dt>
<dd><p><code>your_time_func</code> should return a single number. If it returns integers,
+
<dd><p><code>your_time_func</code> 应该返回一个数字。 如果它返回整数,您还可以使用指定一个单位时间的实际持续时间的第二个参数调用类构造函数。 例如,如果 <code>your_integer_time_func</code> 返回以千秒为单位测量的时间,您将按如下方式构造 <code>Profile</code> 实例:</p>
you can also invoke the class constructor with a second argument specifying
 
the real duration of one unit of time. For example, if
 
<code>your_integer_time_func</code> returns times measured in thousands of seconds,
 
you would construct the <code>Profile</code> instance as follows:</p>
 
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
  
 
<div class="highlight">
 
<div class="highlight">
  
<pre>pr = cProfile.Profile(your_integer_time_func, 0.001)</pre>
+
<syntaxhighlight lang="python3">pr = cProfile.Profile(your_integer_time_func, 0.001)</syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
<p>As the <code>cProfile.Profile</code> class cannot be calibrated, custom timer
+
<p>由于 <code>cProfile.Profile</code> 类无法校准,因此应谨慎使用自定义定时器功能,并应尽可能快。 为了使用自定义计时器获得最佳结果,可能需要在内部 <code>_lsprof</code> 模块的 C 源代码中对其进行硬编码。</p></dd></dl>
functions should be used with care and should be as fast as possible. For
 
the best results with a custom timer, it might be necessary to hard-code it
 
in the C source of the internal <code>_lsprof</code> module.</p></dd></dl>
 
  
Python 3.3 adds several new functions in [[../time#module-time|<code>time</code>]] that can be used to make
+
Python 3.3 [[../time#module-time|time]] 中添加了几个新函数,可用于精确测量进程或挂钟时间。 例如,参见 [[../time#time|time.perf_counter()]]
precise measurements of process or wall-clock time. For example, see
 
[[../time#time|<code>time.perf_counter()</code>]].
 
  
  
 
</div>
 
</div>
 +
 +
</div>
 +
<div class="clearer">
 +
 +
  
 
</div>
 
</div>
  
[[Category:Python 3.9 中文文档]]
+
[[Category:Python 3.9 文档]]

2021年10月31日 (日) 04:53的最新版本

Python 分析器

源代码: :source:`Lib/profile.py` and :source:`Lib/pstats.py`



分析器简介

cProfileprofile 提供 Python 程序的 确定性分析profile 是一组统计数据,描述了程序各个部分执行的频率和时间。 这些统计信息可以通过 pstats 模块格式化为报告。

Python 标准库提供了相同分析接口的两种不同实现:

  1. cProfile 推荐给大多数用户; 它是一个具有合理开销的 C 扩展,使其适用于分析长时间运行的程序。 基于 lsprof,由 Brett Rosen 和 Ted Czotter 贡献。
  2. profile,一个纯 Python 模块,它的接口被 cProfile 模仿,但它为分析程序增加了显着的开销。 如果您尝试以某种方式扩展探查器,则使用此模块可能会更轻松地完成任务。 最初由 Jim Roskind 设计和编写。

笔记

分析器模块旨在为给定程序提供执行配置文件,而不是用于基准测试目的(为此,有 timeit 以获得合理准确的结果)。 这尤其适用于针对 C 代码对 Python 代码进行基准测试:分析器引入了 Python 代码的开销,而不是 C 级函数的开销,因此 C 代码看起来比任何 Python 代码都快。


即时用户手册

本节是为“不想阅读手册”的用户提供的。 它提供了一个非常简短的概述,并允许用户快速对现有应用程序进行分析。

要分析采用单个参数的函数,您可以执行以下操作:

import cProfile
import re
cProfile.run('re.compile("foo|bar")')

(如果后者在您的系统上不可用,请使用 profile 而不是 cProfile。)

上述操作将运行 re.compile() 并打印如下所示的配置文件结果:

      197 function calls (192 primitive calls) in 0.002 seconds

Ordered by: standard name

ncalls  tottime  percall  cumtime  percall filename:lineno(function)
     1    0.000    0.000    0.001    0.001 <string>:1(<module>)
     1    0.000    0.000    0.001    0.001 re.py:212(compile)
     1    0.000    0.000    0.001    0.001 re.py:268(_compile)
     1    0.000    0.000    0.000    0.000 sre_compile.py:172(_compile_charset)
     1    0.000    0.000    0.000    0.000 sre_compile.py:201(_optimize_charset)
     4    0.000    0.000    0.000    0.000 sre_compile.py:25(_identityfunction)
   3/1    0.000    0.000    0.000    0.000 sre_compile.py:33(_compile)

第一行表示监控了 197 个呼叫。 在这些调用中,192 个是 primitive,这意味着调用不是通过递归引起的。 下一行:Ordered by: standard name,表示使用最右列中的文本字符串对输出进行排序。 列标题包括:

调用
对于呼叫数量。
时间
在给定函数中花费的总时间(不包括调用子函数的时间)
每次通话
tottime 除以 ncalls 的商
临时工
是在这个函数和所有子函数中花费的累积时间(从调用到退出)。 对于递归函数,这个数字是准确的 甚至
每次通话
cumtime 除以原始调用的商
文件名:lineno(函数)
提供每个函数的各自数据

当第一列有两个数字时(例如3/1),表示函数递归了。 第二个值是原始调用的数量,前者是调用的总数。 注意函数不递归时,这两个值是一样的,只打印单个数字。

您可以通过为 run() 函数指定文件名,而不是在配置文件运行结束时打印输出:

import cProfile
import re
cProfile.run('re.compile("foo|bar")', 'restats')

pstats.Stats 类从文件中读取配置文件结果并以各种方式对其进行格式化。

文件 cProfileprofile 也可以作为脚本调用来分析另一个脚本。 例如:

python -m cProfile [-o output_file] [-s sort_order] (-m module | myscript.py)

-o 将配置文件结果写入文件而不是标准输出

-s 指定 sort_stats() 排序值之一以对输出进行排序。 这仅适用于未提供 -o 的情况。

-m 指定正在分析模块而不是脚本。

3.7 新功能: cProfile 中添加了 -m 选项。


3.8 新功能:配置文件中增加了-m选项。


pstats 模块的 Stats 类有多种方法来操作和打印保存到配置文件结果文件中的数据:

import pstats
from pstats import SortKey
p = pstats.Stats('restats')
p.strip_dirs().sort_stats(-1).print_stats()

strip_dirs() 方法从所有模块名称中删除了无关的路径。 sort_stats() 方法根据打印的标准模块/行/名称字符串对所有条目进行排序。 print_stats() 方法打印出所有的统计信息。 您可以尝试以下排序调用:

p.sort_stats(SortKey.NAME)
p.print_stats()

第一次调用实际上将按函数名称对列表进行排序,第二次调用将打印出统计信息。 以下是一些有趣的实验调用:

p.sort_stats(SortKey.CUMULATIVE).print_stats(10)

这按函数中的累积时间对配置文件进行排序,然后只打印十个最重要的行。 如果你想了解什么算法需要时间,上面这行就是你会使用的。

如果您想查看哪些函数循环了很多并且花费了很多时间,您可以这样做:

p.sort_stats(SortKey.TIME).print_stats(10)

根据每个函数花费的时间进行排序,然后打印前十个函数的统计信息。

您也可以尝试:

p.sort_stats(SortKey.FILENAME).print_stats('__init__')

这将按文件名对所有统计信息进行排序,然后仅打印出类 init 方法的统计信息(因为它们在其中拼写为 __init__)。 作为最后一个示例,您可以尝试:

p.sort_stats(SortKey.TIME, SortKey.CUMULATIVE).print_stats(.5, 'init')

这一行用时间的主键和累积时间的辅助键对统计信息进行排序,然后打印出一些统计信息。 具体来说,列表首先被剔除到其原始大小的 50% (re: .5),然后只保留包含 init 的行,并打印该子子列表.

如果您想知道哪些函数调用了上述函数,您现在可以(p 仍然根据最后一个条件排序)执行以下操作:

p.print_callers(.5, 'init')

并且您将获得列出的每个函数的调用者列表。

如果您想要更多功能,您将不得不阅读手册,或者猜测以下功能的作用:

p.print_callees()
p.add('restats')

作为脚本调用,pstats 模块是一个统计浏览器,用于读取和检查配置文件转储。 它有一个简单的面向行的界面(使用 cmd 实现)和交互式帮助。


profile 和 cProfile 模块参考

profilecProfile 模块都提供以下功能:

profile.run(command, filename=None, sort=- 1)

这个函数接受一个可以传递给 exec() 函数的参数和一个可选的文件名。 在所有情况下,此例程都执行:

exec(command, __main__.__dict__, __main__.__dict__)

并从执行中收集分析统计信息。 如果没有文件名,那么这个函数会自动创建一个 Stats 实例并打印一个简单的分析报告。 如果指定了排序值,则将其传递给此 Stats 实例以控制结果的排序方式。

profile.runctx(command, globals, locals, filename=None, sort=- 1)

此函数类似于 run(),添加了参数以提供 command 字符串的全局和局部字典。 该例程执行:

exec(command, globals, locals)

并像上面的 run() 函数一样收集分析统计信息。

class profile.Profile(timer=None, timeunit=0.0, subcalls=True, builtins=True)

此类通常仅在需要比 cProfile.run() 函数提供的更精确的分析控制时才使用。

可以提供自定义计时器,用于通过 timer 参数测量代码运行所需的时间。 这必须是一个返回表示当前时间的单个数字的函数。 如果数字是整数,则 timeunit 指定一个乘数,用于指定每个时间单位的持续时间。 例如,如果计时器返回以千秒为单位测量的时间,则时间单位将为 .001

直接使用 Profile 类允许在不将配置文件数据写入文件的情况下格式化配置文件结果:

import cProfile, pstats, io
from pstats import SortKey
pr = cProfile.Profile()
pr.enable()
# ... do something ...
pr.disable()
s = io.StringIO()
sortby = SortKey.CUMULATIVE
ps = pstats.Stats(pr, stream=s).sort_stats(sortby)
ps.print_stats()
print(s.getvalue())

Profile 类也可以用作上下文管理器(仅在 cProfile 模块中受支持。 参见 上下文管理器类型 ):

import cProfile

with cProfile.Profile() as pr:
    # ... do something ...

pr.print_stats()

3.8 版更改: 添加了上下文管理器支持。

enable()

开始收集分析数据。 仅在 cProfile 中。

disable()

停止收集分析数据。 仅在 cProfile 中。

create_stats()

停止收集分析数据并在内部将结果记录为当前分析。

print_stats(sort=- 1)

根据当前配置文件创建一个 Stats 对象并将结果打印到标准输出。

dump_stats(filename)

将当前配置文件的结果写入 filename

run(cmd)

通过 exec() 分析 cmd。

runctx(cmd, globals, locals)

通过 exec() 使用指定的全局和本地环境分析 cmd。

runcall(func, /, *args, **kwargs)

型材 func(*args, **kwargs)

请注意,仅当被调用的命令/函数实际返回时,分析才会起作用。 如果解释器被终止(例如 在被调用的命令/函数执行期间通过 sys.exit() 调用)不会打印分析结果。


Stats 类

分析器数据的分析是使用 Stats 类完成的。

class pstats.Stats(*filenames or profile, stream=sys.stdout)

此类构造函数从 文件名 (或文件名列表)或 Profile 实例创建“统计对象”的实例。 输出将打印到 stream 指定的流。

上述构造函数选择的文件必须是由profilecProfile对应版本创建的。 具体来说,no 文件兼容性保证与此分析器的未来版本,并且与其他分析器生成的文件或在不同操作系统上运行的相同分析器不兼容。 如果提供多个文件,则将合并相同功能的所有统计信息,以便在单个报告中考虑多个流程的整体视图。 如果其他文件需要与现有 Stats 对象中的数据合并,则可以使用 add() 方法。

cProfile.Profileprofile.Profile 对象可以用作配置文件数据源,而不是从文件中读取配置文件数据。

Stats 对象有以下方法:

strip_dirs()

Stats 类的此方法从文件名中删除所有前导路径信息。 这对于减小打印输出的大小以适应(接近)80 列非常有用。 该方法修改对象,剥离的信息丢失。 执行剥离操作后,该对象被认为具有“随机”顺序的条目,就像在对象初始化和加载之后一样。 如果 strip_dirs() 导致两个函数名无法区分(它们在同一个文件名的同一行,并且具有相同的函数名),则将这两个条目的统计信息累加到一个条目中.

add(*filenames)

Stats 类的这个方法将额外的分析信息累积到当前分析对象中。 它的参数应该引用由 profile.run()cProfile.run() 的相应版本创建的文件名。 同名(re:文件、行、名称)函数的统计信息会自动累积到单个函数统计信息中。

dump_stats(filename)

将加载到 Stats 对象中的数据保存到名为 filename 的文件中。 如果文件不存在,则创建该文件,如果已存在,则覆盖该文件。 这相当于 profile.ProfilecProfile.Profile 类上的同名方法。

sort_stats(*keys)

此方法通过根据提供的标准对其进行排序来修改 Stats 对象。 参数可以是字符串或用于标识排序基础的 SortKey 枚举(例如:'time''name'SortKey.TIMESortKey.NAME)。 SortKey 枚举参数优于字符串参数,因为它更健壮且不易出错。

当提供了多个键时,如果在它们之前选择的所有键都相等,则附加键将用作次要条件。 例如,sort_stats(SortKey.NAME, SortKey.FILE) 将根据函数名对所有条目进行排序,并通过按文件名排序来解析所有关系(相同的函数名)。

对于字符串参数,任何键名都可以使用缩写,只要缩写是明确的。

以下是有效的字符串和 SortKey:

有效字符串参数

有效的枚举参数

意义

'calls'

排序键调用

呼叫计数

'cumulative'

排序键.累积

累计时间

'cumtime'

不适用

累计时间

'file'

不适用

文件名

'filename'

SortKey.FILENAME

文件名

'module'

不适用

文件名

'ncalls'

不适用

呼叫计数

'pcalls'

排序键.PCALLS

原始调用计数

'line'

排序键.LINE

电话号码

'name'

排序键.NAME

函数名

'nfl'

排序键.NFL

名称/文件/行

'stdname'

SortKey.STDNAME

标准名称

'time'

排序键.TIME

内部时间

'tottime'

不适用

内部时间

请注意,统计信息的所有排序均按降序排列(将最耗时的项目放在最前面),其中名称、文件和行号搜索按升序排列(按字母顺序)。 SortKey.NFLSortKey.STDNAME 之间的细微区别在于标准名称是一种打印名称,这意味着嵌入的行号以一种奇怪的方式进行比较。 例如,第 3、20 和 40 行(如果文件名相同)将以字符串顺序 20、3 和 40 出现。 相比之下, SortKey.NFL 对行号进行数字比较。 实际上,sort_stats(SortKey.NFL)sort_stats(SortKey.NAME, SortKey.FILENAME, SortKey.LINE) 是一样的。

出于向后兼容性的原因,允许使用数字参数 -1012。 它们分别被解释为 'stdname''calls''time''cumulative'。 如果使用这种旧样式格式(数字),则只会使用一个排序键(数字键),并且其他参数将被静默忽略。

3.7 新功能: 增加了 SortKey 枚举。

reverse_order()

Stats 类的此方法颠倒了对象内基本列表的顺序。 请注意,默认情况下,根据选择的排序键正确选择升序与降序。

print_stats(*restrictions)

Stats 类的这个方法打印出一个报告,如 profile.run() 定义中所述。

打印顺序基于对对象执行的最后一次 sort_stats() 操作(受 add()strip_dirs() 中的警告影响)。

提供的参数(如果有)可用于将列表限制为重要条目。 最初,该列表被视为完整的分析函数集。 每个限制要么是一个整数(选择行数),要么是介于 0.0 和 1.0 之间的小数(包括行数),或者是一个将解释为正则表达式的字符串(以模式匹配标准名称)打印出来的)。 如果提供了多个限制,则它们将按顺序应用。 例如:

print_stats(.1, 'foo:')

将首先限制打印到第一个 10% of 列表,然后只打印属于文件名 .*foo: 的函数。 相比之下,命令:

print_stats('foo:', .1)

会将列表限制为具有文件名 .*foo: 的所有函数,然后继续仅打印前 10% of 个函数。

print_callers(*restrictions)

Stats 类的这个方法打印了所有函数的列表,这些函数调用了分析数据库中的每个函数。 顺序与 print_stats() 提供的相同,并且限制参数的定义也相同。 每个呼叫者都在自己的线路上报告。 根据生成统计信息的分析器,格式略有不同:

  • 对于 profile,每个呼叫者后面的括号中会显示一个数字,以显示进行了该特定呼叫的次数。 为方便起见,第二个无括号的数字重复在右侧函数中花费的累积时间。

  • 使用 cProfile,每个调用者前面都有三个数字:进行此特定调用的次数,以及在此特定调用者调用当前函数时在当前函数中花费的总时间和累计时间。

print_callees(*restrictions)

Stats 类的此方法打印指定函数调用的所有函数的列表。 除了调用方向的这种反转(重新:被调用与被调用),参数和顺序与 print_callers() 方法相同。

get_stats_profile()

此方法返回 StatsProfile 的实例,其中包含函数名称到 FunctionProfile 实例的映射。 每个 FunctionProfile 实例都包含与函数配置文件相关的信息,例如函数运行的时间、调用的次数等……

3.9 新功能: 添加以下数据类:StatsProfile、FunctionProfile。 添加了以下函数:get_stats_profile。


什么是确定性分析?

确定性分析旨在反映以下事实:所有函数调用函数返回异常事件都受到监控,并且精确计时为这些事件之间的间隔(在这段时间内用户的代码正在执行)。 相比之下,statistical profiling(不是由这个模块完成的)随机采样有效指令指针,并推断出时间花费在哪里。 后一种技术传统上涉及较少的开销(因为不需要检测代码),但仅提供时间花在何处的相对指示。

在 Python 中,由于在执行期间有一个解释器处于活动状态,因此不需要存在检测代码来进行确定性分析。 Python 自动为每个事件提供一个 hook(可选回调)。 此外,Python 的解释性质往往会给执行增加如此多的开销,以至于确定性分析往往只会在典型应用程序中增加很小的处理开销。 结果是确定性分析并不那么昂贵,但提供了有关 Python 程序执行的大量运行时统计信息。

调用计数统计可用于识别代码中的错误(令人惊讶的计数),并识别可能的内联扩展点(高调用计数)。 内部时间统计可用于识别应仔细优化的“热循环”。 应使用累积时间统计来识别算法选择中的高级错误。 请注意,此分析器中对累积时间的异常处理允许将算法的递归实现的统计信息直接与迭代实现进行比较。


限制

一个限制与计时信息的准确性有关。 确定性分析器存在一个涉及准确性的基本问题。 最明显的限制是底层“时钟”仅以大约 0.001 秒的速率(通常)滴答作响。 因此,没有任何测量会比基础时钟更准确。 如果进行了足够的测量,那么“误差”将趋于平均。 不幸的是,消除第一个错误会导致第二个错误源。

第二个问题是从调度事件到分析器调用获取时间实际上 获取 时钟状态“需要一段时间”。 类似地,从获取时钟值(然后撤回)到用户代码再次执行,退出分析器事件处理程序也有一定的延迟。 因此,多次调用或调用许多函数的函数通常会累积此错误。 以这种方式累积的误差通常小于时钟的精度(小于一个时钟滴答),但它 可以 累积并变得非常重要。

profile 的问题比开销较低的 cProfile 更重要。 出于这个原因,profile 提供了一种针对给定平台校准自身的方法,以便可以概率地(平均地)消除此错误。 分析器校准后,它会更准确(在最小二乘意义上),但有时会产生负数(当调用计数异常低时,概率之神对你不利:-)。 ) 不要不要被配置文件中的负数吓到。 如果您已经校准了分析器,它们应该 only 出现,并且结果实际上比没有校准要好。


校准

profile 模块的分析器从每个事件处理时间中减去一个常量,以补偿调用 time 函数和存储结果的开销。 默认情况下,常量为 0。 以下过程可用于为给定平台获得更好的常数(请参阅 限制 )。

import profile
pr = profile.Profile()
for i in range(5):
    print(pr.calibrate(10000))

该方法直接在探查器下执行参数给出的 Python 调用次数,并测量两者的时间。 然后计算每个分析器事件的隐藏开销,并将其作为浮点数返回。 例如,在运行 macOS 的 1.8Ghz Intel Core i5 上,使用 Python 的 time.process_time() 作为计时器,神奇数字约为 4.04e-6。

这个练习的目的是获得一个相当一致的结果。 如果您的计算机 非常 快,或者您的计时器功能分辨率不佳,您可能需要通过 100000,甚至 1000000,才能获得一致的结果。

当你有一个一致的答案时,你可以通过三种方式使用它:

import profile

# 1. Apply computed bias to all Profile instances created hereafter.
profile.Profile.bias = your_computed_bias

# 2. Apply computed bias to a specific Profile instance.
pr = profile.Profile()
pr.bias = your_computed_bias

# 3. Specify computed bias in instance constructor.
pr = profile.Profile(bias=your_computed_bias)

如果您有选择,您最好选择一个较小的常数,这样您的结果将“较少”在配置文件统计中显示为负数。


使用自定义计时器

如果要更改确定当前时间的方式(例如,强制使用挂钟时间或经过的处理时间),请将所需的计时函数传递给 Profile 类构造函数:

pr = profile.Profile(your_time_func)

然后生成的分析器将调用 your_time_func。 根据您使用的是 profile.Profile 还是 cProfile.Profileyour_time_func 的返回值将有不同的解释:

profile.Profile

your_time_func 应该返回一个数字,或者一个数字列表,其总和是当前时间(就像 os.times() 返回的)。 如果函数返回单个时间数字,或者返回数字列表的长度为 2,那么您将获得调度例程的特别快速版本。

请注意,您应该为您选择的计时器函数校准分析器类(请参阅 Calibration)。 对于大多数机器,返回一个单独的整数值的计时器将在分析期间提供低开销方面的最佳结果。 (os.times()pretty 不好,因为它返回一个浮点值元组)。 如果您想以最简洁的方式替换更好的计时器,请派生一个类并硬连接一个最能处理您的计时器调用的替换调度方法,以及适当的校准常量。

cProfile.Profile

your_time_func 应该返回一个数字。 如果它返回整数,您还可以使用指定一个单位时间的实际持续时间的第二个参数调用类构造函数。 例如,如果 your_integer_time_func 返回以千秒为单位测量的时间,您将按如下方式构造 Profile 实例:

pr = cProfile.Profile(your_integer_time_func, 0.001)

由于 cProfile.Profile 类无法校准,因此应谨慎使用自定义定时器功能,并应尽可能快。 为了使用自定义计时器获得最佳结果,可能需要在内部 _lsprof 模块的 C 源代码中对其进行硬编码。

Python 3.3 在 time 中添加了几个新函数,可用于精确测量进程或挂钟时间。 例如,参见 time.perf_counter()