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

<channel>
	<title>Python Prompt Toolkit &#8211; 天地一沙鸥</title>
	<atom:link href="https://haoluobo.com/tag/python-prompt-toolkit/feed/" rel="self" type="application/rss+xml" />
	<link>https://haoluobo.com</link>
	<description>to be continue....</description>
	<lastBuildDate>Tue, 22 Nov 2022 08:01:14 +0000</lastBuildDate>
	<language>zh-Hans</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.8.2</generator>
	<item>
		<title>Python内存泄漏原因及问题排查</title>
		<link>https://haoluobo.com/2022/11/python-memory-leak/</link>
		
		<dc:creator><![CDATA[vicalloy]]></dc:creator>
		<pubDate>Tue, 15 Nov 2022 07:15:47 +0000</pubDate>
				<category><![CDATA[编程]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[Python Prompt Toolkit]]></category>
		<guid isPermaLink="false">https://haoluobo.com/?p=12323</guid>

					<description><![CDATA[Python 会自动回收内存，一般情况下不用关心内存的申请和释放问题。事实上我也一直没怎么关心过Python的 [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>Python 会自动回收内存，一般情况下不用关心内存的申请和释放问题。事实上我也一直没怎么关心过Python的内存管理问题，直到我用了 <a rel="noreferrer noopener" href="https://github.com/prompt-toolkit/python-prompt-toolkit" target="_blank">Python Prompt Toolkit</a> 。这是一个 Python 的CLI组件库，使用简单，效果很好。只是性能用点差，另外就是它居然有内存泄漏。</p>



<h2 class="wp-block-heading">内存问题产生原因</h2>



<p>Python里内存管理主要基于引用计数实现，另外会辅以全图遍历以解决循环引用问题。一般内存问题都是对象被全局变量直接或间接持有导致。出现内存泄漏后关键是找到问题对象到底被谁给持有了。</p>



<h2 class="wp-block-heading">确认内存泄漏的对象</h2>



<p>如果一个程序内存一直异常增长，那多半是存在内存泄漏。接下来就是定位问题了。Python内存分析的工具和手段主要有下面几个：</p>



<ol class="wp-block-list">
<li><a rel="noreferrer noopener" href="https://github.com/mgedmin/objgraph" target="_blank">objgraph</a> 可用现实对象的增长情况。还可以根据对象的引用关系生成图像。
<ul class="wp-block-list">
<li>可以根据对象生成引用关系树以及被引用关系树。第一感觉功能很强，实际用下来效果一般。对于复杂一些的项目，生成的关系树是在太过复杂。你以为对象都是通过属性持有，实际上各类的闭包，函数指针等都会持有对象。</li>
</ul>
</li>



<li><a rel="noreferrer noopener" href="https://github.com/pympler/pympler" target="_blank">pympler</a> 感觉和objgraph差不多，不支持生成图像。</li>



<li><code>gc.get_referents()</code>/<code>gc.get_referents()</code>/<code>gc.*</code> 获取对象的引用计数及指向该对象的对象，以及其它分析函数。
<ul class="wp-block-list">
<li>其它内存分析的库应当都是基于Python的gc模块实现。</li>
</ul>
</li>



<li><code>print('PromptSession count: ', len([o for o in obj if isinstance(o, PromptSession)]))</code> 打印对象数量，确认是否被释放。</li>
</ol>



<h2 class="wp-block-heading">解决内存泄漏问题</h2>



<p>要解决内存问题，关键还是找到存在内存泄漏的问题被谁给持有里，然后在需要销毁对象时释放该持有。如果想该对象持有不影响对象的生命周期（比如缓存），可以使用 <a rel="noreferrer noopener" href="https://docs.python.org/zh-cn/3/library/weakref.html" target="_blank">weakref</a> 库来创建弱引用。</p>



<h2 class="wp-block-heading">Python Prompt Toolkit 的内存问题</h2>



<p>出于性能等考虑 <code>Python Prompt Toolkit</code> 添加来大量的缓存。其中一些看似简单的缓存对象持有了其它对象的函数（函数指针），从而间接持有了其它对象，最终导致大量的对象未被释放。一般情况下一个程序只有一个 <code>PromptSession</code> 对象，该对象贯穿程序的整个生命周期，因此问题不容易察觉。但我的应用时一个服务端程序，需要反复创建和销毁 <code>PromptSession</code> 对象，问题将出现了。</p>



<p>我尝试用 <code>weakref.WeakValueDictionary</code> 改写它的缓存实现，实际过程中发现key和value都会持有对象。</p>



<p>目前的做法是用户断开服务器连接时进行一次缓存的清理。</p>
]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
