Python:MemoryError vs OverflowerError vs instantsystemfreez

2024-05-06 02:17:31 发布

您现在位置:Python中文网/ 问答频道 /正文

上一天,解决另一个Project Euler我在管理一个大的for i in range(n)循环时遇到了麻烦。你知道吗

我观察到python会抛出不同的错误,这取决于x变量的大小。你知道吗

下面是一个mcve示例:

for i in range(x):
    pass

其中:

  • 如果x = 10**20我得到了一个OverflowError, 准确地说:OverflowError: range() result has too many items

  • 否则如果x = 10**15我得到了一个MemoryError

  • 否则,如果x = 10**9我得到了一个instant-system-freeze我必须硬重置我的电脑。很少,我的电脑不是冻结,而是填满大约5GB的交换空间,变得非常慢。

我试图理解pythonbuilt-in exception的含义:

  • ^{}

    Raised when the result of an arithmetic operation is too large to be represented. This cannot occur for long integers [...] and for most operations with plain integers, which return a long integer instead. [...]

    这意味着整数不应该抛出这个异常;这个异常的原因是range()有太多的项,所以我想10**15也会抛出相同的异常,但是我得到了一个不同的异常。。。

  • ^{}

    Raised when an operation runs out of memory but the situation may still be rescued (by deleting some objects). [...]

    我应该删除哪个对象来挽救这种情况?它只是简单的退出,所以情况无法挽救。。。你知道吗

    如果它觉得有太多的ram使用,为什么它会用10**9冻结我的电脑?


最后,我的问题是:

为什么我得到3个不同的结果,仅仅取决于x变量中存储的值?


注意:

  • 我知道^{}的存在,这没有这个问题,但我的问题是关于^{}。你知道吗
  • 我认为用于抛出异常的值可能会改变,这取决于您的硬件。你知道吗
  • 我的Python版本:2.7.6。你知道吗

Tags: oftheinanforrangeberesult
2条回答

range(x)将首先创建一个大小为x的列表,然后用整数填充它。影响包括:

  • x = 10**20OverflowError,因为列表只能容纳^{}(对于32位和64位构建,通常分别是2**31 - 12**63 - 1)项。你知道吗
  • x = 10**15MemoryError,因为内存不足,无法分配大小为x的(未初始化)列表
  • x = 10**9:将创建一个大小为x的列表;然后对于everyintegeri < x,将创建一个新的int对象并将其写入磁盘;每个int对象都需要内存分配。(这最终可能会导致内存错误,也可能不会导致内存错误。)这会给CPU和内存带来很大的负载,从而降低机器的速度。你知道吗

总之,对于前两种情况,对于python来说,任务显然无法完成,它引发了一个异常。在第三种情况下,它认为它可能能够完成任务,尽管速度很慢。你知道吗

嗯,range试图构建一个完整的列表,其中包含尽可能多的项x。你知道吗

对于死亡的即时交换,假设64位和一个固定的8字节整数,x = 10**9大约值8go。因此,如果您没有超过这一点(考虑到已经使用的RAM),您可以看到为什么系统交换。你知道吗

再往下看,如果函数不能分配足够大的块来保存结果(在10**15的情况下,这个块看起来相当大),那么MemoryError可能会被引发。你知道吗

我不知道range的实现细节,但它可能使用OverflowError来确保元素的绝对最大数量(可能是为了防止MemoryError,基于实际可用内存)。
正如@ShadowRanger在注释中提到的,如果结果的长度不能放入size_t变量(2**31(32位)或2**63(64位))中,则会引发OverflowError,因为它无法初始化这样的列表。你知道吗

正如您所提到的,xrange没有这个问题,因为它不会生成整个列表,而是在每次迭代时生成一个值。这就是迭代器/生成器具有内存效率的原因。你知道吗


所以我快速看了一下,你可以看到为什么它抛出一个OverflowError。你知道吗

相关问题 更多 >