如何减少 Python 脚本内存使用
Posted
技术标签:
【中文标题】如何减少 Python 脚本内存使用【英文标题】:How To Reduce Python Script Memory Usage 【发布时间】:2012-06-15 15:57:48 【问题描述】:我有一个非常大的 python 脚本,200K,我想使用尽可能少的内存。它看起来像:
# a lot of data structures
r = [34, 78, 43, 12, 99]
# a lot of functions that I use all the time
def func1(word):
return len(word) + 2
# a lot of functions that I rarely use
def func1(word):
return len(word) + 2
# my main loop
while 1:
# lots of code
# calls functions
如果我将我很少使用的函数放在一个模块中,并且仅在必要时动态导入它们,我将无法访问数据。就我所知。
我是 python 新手。
谁能让我走上正确的道路?我怎样才能分解这个大脚本,以便它使用更少的内存?是否值得将很少使用的代码放入模块中并仅在需要时调用它们?
【问题讨论】:
你确定它使用了太多内存吗? 记住“过早的优化是万恶之源”。 就您的函数问题而言,您是否检查过您的函数是否引用了全局变量?如果它们是(并且可能没有在该模块中定义数据),您可以: 1. 为每个函数添加一个参数以接收任何全局变量或 2. 在一个类并将全局变量传递给__init__
并重写函数以将全局变量调用为self.<variable name>
如果你的脚本文件那么大,那么听起来你要么在任何地方都使用了极其可变的名称并且代码中有很多 cmets,或者你更有可能做错了什么或者充其量是低效的。不幸的是,仅基于您对代码的模糊描述,是否有人能够为您提供很多帮助是值得怀疑的。是时候得到具体的(并接受一些答案)了!
【参考方案1】:
组织:
你的python脚本看起来确实很大,也许你应该考虑先重新组织你的代码,把它分成几个modules or packages。它可能会使代码分析和优化任务变得更容易。
你可能想看看那里:
Python Project Howto Python Packages SO: Organising my Python project还有可能:
SO: Python: What is the common header format? How do you organize Python modules? The Hitchiker's Guide to Packaging优化:
有很多事情可以用来优化你的代码......
例如,关于您的数据结构...如果您大量使用列表或列表推导式,您可以尝试找出您真正需要列表的位置,以及它们可能被不可变数据结构替换的位置,例如元组或“易失性”对象、“惰性”容器,如生成器表达式。
见:
SO: Are tuples more efficient than lists in Python? SO: Generator Expressions vs. List Comprehension PEP 255 - Simple Generators 和 PEP 289 - Generator Expressions在这些页面上,您可以找到一些有用的信息和提示:
http://wiki.python.org/moin/PythonSpeed http://wiki.python.org/moin/PythonSpeed/PerformanceTips http://wiki.python.org/moin/TimeComplexity http://scipy.org/PerformancePython另外,你应该研究你的做事方式,并想知道是否有一种方法可以减少贪婪,一种最好用 Python 来做的方法(你会在标签 pythonic 中找到一些提示)。 .. 在 Python 中尤其如此,因为在 Python 中,通常有一种“显而易见”的方式(而且只有一种)可以做比其他更好的事情(参见 The Zen of Python),据说是pythonic。它与您的代码的形状并没有特别的关系,但也 - 最重要的是 - 与性能有关。与许多提倡应该有多种方法来做任何事情的语言不同,Python 更喜欢只关注最好的方法。所以很明显,做某事有很多方法,但通常,有一种方法真的更好。
现在,您还应该验证您是否使用了最好的方法来做事,因为 Python 性不会为您安排算法。
但最后,它会根据您的代码而有所不同,如果没有看到它很难回答。
并且,请务必考虑eumiro 和Amr 制作的cmets。
【讨论】:
您知道确定某些 Python 代码的 sn-p 占用内存量的好方法吗?使用timeit
进行速度比较很容易,所以我正在寻找可以让我确定/表征内存消耗的东西。只是好奇是否有这么简单的东西。
memory_profiler 非常有用,易于使用以进行快速调试。现在您可以尝试meliae (step-by-step how-to) 或heapy 以获得更完整的解决方案。很好的讨论here 和一些有趣的估计方法here
不过,我认为您更多的是寻找像我提到的 memory_profiler 模块这样的东西。
感谢您的信息,我赞成这个问题,以便我可以回到它并跟进您提到的链接。非常感谢。【参考方案2】:
如果您正在利用 OOP 并且有一些对象,请说:
class foo:
def __init__(self, lorem, ipsum):
self.lorem = lorem
self.ipsum = ipsum
# some happy little methods
您可以通过以下方式让对象占用更少的内存:
__slots__ = ("lorem", "ipsum")
就在__init__
函数之前,如图:
class foo:
def __init__(self, lorem, ipsum):
self.lorem = lorem
self.ipsum = ipsum
# some happy little methods
当然,“过早的优化是万恶之源”。还要在添加之前和之后分析 mem 的使用情况,看看它是否真的做了什么。谨防破坏代码(令人震惊地),因为理解这可能最终无法正常工作。
【讨论】:
【参考方案3】:这个视频可能会给你一些好主意:http://pyvideo.org/video/451/pycon-2011---quot-dude--where--39-s-my-ram--quot-
【讨论】:
【参考方案4】:关于生成器表达式和使用模块的建议很好。过早的优化会导致问题,但在坐下来编写代码之前,您应该始终花几分钟时间思考您的设计。特别是如果该代码要被重用。
顺便说一句,您提到您在脚本顶部定义了很多数据结构,这意味着它们在开始时都已加载到内存中。如果这是一个非常大的数据集,请考虑将特定数据集移动到单独的文件中,并仅在需要时加载它。 (使用csv
模块,或numpy.loadtxt()
等)
除了使用更少的内存之外,还要研究更有效地使用内存的方法。例如,对于大量数值数据,numpy 数组是一种存储信息的方式,可以在计算中提供更好的性能。 http://wiki.python.org/moin/PythonSpeed/PerformanceTips 有一些稍微过时的建议
【讨论】:
【参考方案5】:移动函数不会改变您的内存使用情况。一旦您导入该其他模块,它将定义该模块中的所有功能。但是函数不会占用太多内存。它们是否非常重复,也许您可以通过重构函数来减少代码?
@eumiro 的问题是对的:你确定你的脚本占用了太多内存吗?它使用了多少内存,为什么会太多?
【讨论】:
以上是关于如何减少 Python 脚本内存使用的主要内容,如果未能解决你的问题,请参考以下文章