<p>正如评论中提到的,从Python生成UML已经在<a href="https://stackoverflow.com/questions/260165/whats-the-best-way-to-generate-a-uml-diagram-from-python-source-code">this answer</a>中讨论过了。(请记住,Python实际上并不一定非得是UML可表示的,但如果是的话,那就太好了。)</p>
<p>至于在运行时查看控制流,有几种方法可以做到这一点。一种是使用分析和/或调试工具。但是让我们看看最简单的方法来记录它,这就是您所要求的:</p>
<p>您可以随时“记录”任何东西,只需<code>print</code>到控制台。您必须从命令行运行应用程序,而不是启动它的GUI风格(在Mac上,这意味着您必须直接运行可执行文件/脚本,而不是任何由它构建的<code>.app</code>捆绑包),但是,如果您愿意,您可以使用shell(甚至是Windows<code>cmd</code>)将日志输出重定向到一个文件,以便以后浏览。如果这对您来说还不够好,请参阅标准库中内置的<a href="http://docs.python.org/library/logging.html" rel="nofollow noreferrer">^{<cd4>}</a>模块。在</p>
<p>如果您想知道从何处调用函数,可以在每次调用函数时记录堆栈跟踪。这有点难看,但它提供了您可能需要的所有信息,并且您始终可以编写一些代码来稍后解析输出。函数<a href="http://docs.python.org/library/traceback.html#traceback.print_stack" rel="nofollow noreferrer">traceback.print_stack</a>正是这样做的。(如果你想变得更花哨,可以使用其他函数来提取信息,如果你想格式化的话,可以按照你想要的方式进行记录。)</p>
<p>您可以通过向每个要跟踪的函数添加以下行来完成此操作:</p>
<pre><code>traceback.print_stack()
</code></pre>
<p>另一种方法是编写monkey patcher并将其应用于您关心的所有函数:</p>
^{pr2}$
<p>现在,在主脚本中,只需执行以下操作:</p>
<pre><code>InterestingClass.interestingMethod = tracify(InterestingClass.interestingMethod)
</code></pre>
<p>现在,每次兴趣类。兴趣方法调用时,它将打印出堆栈跟踪。您不必了解<code>tracify</code>是如何工作的。如果您想更改它对函数的作用,只需将<code>traceback.print_stack()</code>行替换为您想做的任何事情。在</p>
<p>那么,如果你想修补类中的每个“public”方法呢?在</p>
<pre><code>for attr in dir(InterestingClass):
if not attr.startswith('_'):
method = getattr(InterestingClass, attr)
if isinstance(method, instancemethod):
setattr(InterestingClass, tracify(method))
</code></pre>
<p>(这是针对python2的。Python3改变了事情,使复杂的情况简单得多,但琐碎的情况却没有那么简单。)</p>
<p>如果你想修补模块中每个类的每个公共方法和每个自由函数呢?你可以用同样的方法迭代一个模块,然后检查每件事情的类型,就像你对一个类一样。在</p>
<p>您还可以使用<a href="http://docs.python.org/library/inspect.html" rel="nofollow noreferrer">inspect</a>模块来为您完成硬任务。但是如果您只是学习Python,我认为复制和粘贴<code>dir</code>代码要比学习如何使用<code>inspect</code>简单得多。一旦你对这门语言比较熟悉,就回来玩<code>inspect</code>来弄清楚它为什么都有用。在</p>