Python循环中的MemoryError

Python循环中的MemoryError,python,out-of-memory,python-3.7,Python,Out Of Memory,Python 3.7,我的一个脚本中有一个嵌套循环,运行时会导致MemoryError。它看起来像这样: jobRange = range(605) a = [] for i in jobRange: for k in jobRange: for j in jobRange: if i != k and k != j: a.append((i, k, j)) 我试图通过使用排列替换可怕的嵌套循环来优化它: a = [] for p in

我的一个脚本中有一个嵌套循环,运行时会导致
MemoryError
。它看起来像这样:

jobRange = range(605)
a = []
for i in jobRange:
    for k in jobRange:
        for j in jobRange:
            if i != k and k != j:
                a.append((i, k, j))
我试图通过使用排列替换可怕的嵌套循环来优化它:

a = []
for p in permutations(jobRange, 3):
    i, k, j = p[0], p[1], p[2]
    a.append((i, k, j))
然而,这并不能解决问题。我仍然得到:

回溯(最近一次呼叫最后一次):
文件“C:/Users/Vejdanpa/PycharmProjects/myProject/Models/test.py”,第10行,在
a、 附加((i,k,j))
记忆者
我还尝试了以下超慢代码,只是为了找出这段代码使用了多少内存,从而导致
MemoryError

from itertools import permutations
import tracemalloc

tracemalloc.start()
jobRange = range(605)

a = []
for p in permutations(jobRange, 3):
    i, k, j = p[0], p[1], p[2]
    a.append((i, k, j))
    current, peak = tracemalloc.get_traced_memory()
    print(f"Current memory usage: {current / 10 ** 6}MB; Peak: {peak / 10 ** 6}MB")

tracemalloc.stop()
抛出错误之前的最后两行输出是:

当前内存使用量:1022.68617MB;峰值:1022.686298MB
当前内存使用量:1022.68621MB;峰值:1022.686338MB
当前内存使用量:1022.68625MB;峰值:1022.686378MB
当前内存使用量:1022.68629MB;峰值:1022.686418MB
当前内存使用量:1022.68633MB;峰值:1022.686458MB
当前内存使用量:1022.68637MB;峰值:1022.686498MB
当前内存使用量:1022.68641MB;峰值:1022.686538MB
当前内存使用量:1022.68645MB;峰值:1022.686578MB
当前内存使用量:1022.68649MB;峰值:1022.686618MB
当前内存使用量:1022.68653MB;峰值:1022.686658MB
回溯(最近一次呼叫最后一次):
文件“C:/Users/Vejdanpa/PycharmProjects/myProject/Models/test.py”,第10行,在
a、 附加((i,k,j))
记忆者
进程已完成,退出代码为1
据我所知,这表明阈值以某种方式设置为~1GB,我的程序内存不足,因为它需要更多的1GB。我检查了我的机器的规格: . 这表明我有16GB的ram,据我所知,Python并没有以任何方式限制内存的使用,应该一直运行到内存耗尽为止

我目前正在PyCharm中运行Python3.7中的代码,但在命令行上进行一次简单的尝试就得到了相同的结果


有人能帮我理解我的python脚本如何/为什么会消耗1GB的内存限制,以及可能如何增加这种限制吗?

我想在@juanpa.arrivillaga的评论中加上一句话。
如果你只是想把东西列入清单,你可以选择:
列表(排列(jobRange,3))
但这可能不是一个好主意,这是有原因的

警告这是反手计算,可能与系统有关

我查找了文档,函数返回的结果数是
n!/(右),在您的情况下使其成为
605/(605-3)!,简化为
605x604x603

我假设每个int至少是
28字节
,我是通过在我的系统上运行
sys.getsizeof(1)
得到这个数字的——原因:

您正在添加一个列表,该列表会随着程序的运行时间而增长。 因此,列表的最终大小,或者更确切地说,列表本身大小的下限(忽略所有其他内容)将是:

605 x 604 x 603 x 28 x 3 ~= 18 509 MB ~= 18.5 GB
这可能会超出你的记忆,这只是列表的大小


这可能不是一个完全准确的下限估计值,我发现Python中的任何内存使用估计值都非常困难。

如果您在Fil memory profiler()下运行该程序,它将使用一种启发式方法在内存耗尽之前转储内存配置文件报告,以便您可以看到使用了多少内存。请参见此处的示例:

您是否使用64位python进程?还是32位?一个32位进程将被限制在1G左右,这是一个很好的分析,但OP似乎不会超过1GB@LemurPwned您忘记考虑包含整数的3元组,即64字节(~14GB)。此外,整数的平均成本略低于28字节,因为CPython为256(含256)以下的整数提供了一个小的整数缓存。这表示使用的整数约占43%,因此,对于此特定工作负载,整数的平均成本为16字节(28*.57)。通过将
jobRange
a
list
改为,然后每次重复使用相同的整数,而不是在每次迭代中重新创建它们的
范围
对象:对于一个基本不相关的10kB,只需要分配~350个整数。@masklin,这是一个公平的观点!我完全错过了这个aspectNote,列表将使用(至少)len(mylist)*word_length
字节来存储PyObject指针的实际数组。因此,对于64位系统上长度为100的列表,这是100*8字节