加载“太大”的数据或没有足够的资源CPU或内存时,python的行为是什么?

问题描述

我正在开发一个程序,该程序有时在列表上有一个for循环,其中有些很小,有些很大(500k +元素)。 当应用程序运行一段时间后,系统上就意味着它在此循环中失败了,而在之前的迭代中并没有失败,列表更小。

要进行调试,并使用pickle模块,我在进入函数之前转储了列表。 当应用程序失败时,刚转储的列表在系统上将是一个很大的列表(500k +个元素)。 获得的文件大于或等于70MB(二进制模式)。

我知道我有备用RAM(使用htop,我在2GB的可用空间中大约使用了400MB)。 但是CPU经常处于较高的活动百分比(超过60%,有时达到100%)。

当我从文件中加载列表时,(应用程序已停止)我可以运行for迭代而不会遇到麻烦。该列表似乎没有损坏。

因此,我完全不知道可能出什么问题,除非CPU活动很高。如果确实Python没有足够的资源来工作,它有什么办法告诉我?我该如何检查?它的行为是什么?程序可能停止而没有任何错误消息吗?

编辑-代码示例

请在此处找到该应用冻结的代码下方。 代码本身可以正常执行。 执行的上下文似乎使代码冻结。

我可以确定该应用程序在名为“百慕大三角”的for循环开始时冻结。 我可以使用pickle模块打印数据,但是无法在for循环中进行打印。 真正奇怪的是我得到了应该打印的文件,但是该文件(dump_loop.txt)是空的。 我觉得这很奇怪,因为我应该有0个文件(在循环开始时注意os.remove,这意味着我在每次迭代中都将其删除),或者如果我有一个,则应该在其中写入一些内容。>

我确认当应用运行时(即“正常”,它不会冻结),这两个文件已正确更新。

感谢您的帮助! 最好的

import os
import json
import pickle
from collections import defaultdict

data = [('1599324732926-0',{'data': '{"timestamp":1599324732.767,\
                "receipt_timestamp":1599324732.9256856,\
                "delta":true,\
                "bid":{"338.9":0.06482,"338.67":3.95535},\
                "ask":{"339.12":2.47578,"339.13":6.43172} \
               }'
         }),('1599324732926-1',"339.13":6.43172} \
               }'
         })]

         
def book_flatten(book: dict,timestamp: float,receipt_timestamp: float,delta: str) -> dict:
    """
    Takes book and returns a list of dict,where each element in the list
    is a dictionary with a single row of book data.

    """
    ret = []
    for side in ('bid','ask'):
        for price,data in book[side].items():
            ret.append({'side': side,'price': price,'size': data,'timestamp': timestamp,'receipt_timestamp': receipt_timestamp,'delta': delta})
    return ret
         
def read(data,dtype='l2_book',pair='AAPL-USD'):       
    key = f'{dtype}-{pair}'
    if len(data) == 0:
        return []
    print("{!s}: Read {!s} messages from Redis".format(key,len(data)))
    ret = []
    ids=dict()
    last_id=defaultdict(list)

    # 1/Start - Lines added for debug
    # Retrieve the last data before the app freezes
    dump_list='./dump_list.data'
    try:
        os.remove(dump_list)
    except OSError:
        pass
    with open(dump_list,'wb') as filehandle:
        # store the data as binary data stream
        pickle.dump(data,filehandle)
    dump_loop = './dump_loop.txt'
    total_number = len(data)
    counter=1
    # 1/End

    # The mysterious loop aka Bermuda Triangle
    for update_id,update in data:
        #2/Start - Lines added for debug
        try:
            os.remove(dump_loop)
        except OSError:
            pass
        with open(dump_loop,'w') as filehandle:
            filehandle.write('Starting new loop for item {!s} over {!s}.\n'.format(counter,total_number))
        #2/End
        if dtype in {'l2_book'}:
            update = json.loads(update['data'])
            update = book_flatten(update,update['timestamp'],update['receipt_timestamp'],update['delta'])
            for u in update:
                for k in ('size','amount','price','timestamp','receipt_timestamp'):
                    if k in u:
                        u[k] = float(u[k])
            ret.extend(update)
        elif dtype in {'trades'}:
            for k in ('size','receipt_timestamp','bid','ask'):
                if k in update:
                    update[k] = float(update[k])
            ret.append(update)
        ids[key] = update_id
        #3/Start - Lines added for debug
        with open(dump_loop,'a') as filehandle:
            filehandle.write('Loop finished.\n')  
        counter+=1
        #3/End

    last_id[key] = ids[key][-1]
    return ids,last_id,ret

解决方法

好吧, 因此,建议我查看syslog(是一个新手,我对此一无所知)和'voilà'! 经过新的测试后,应用my_app在17:45崩溃。 这是syslog在17:45所说的话:

Sep  6 17:45:12 cs1 kernel: [67093.681124] oom-kill:constraint=CONSTRAINT_NONE,nodemask=(null),cpuset=/,mems_allowed=0,global_oom,task_memcg=/user.slice/user-0.slice/session-32.scope,task=cryp>
Sep  6 17:45:12 cs1 kernel: [67093.681180] Out of memory: Killed process 15754 (my_app) total-vm:1752588kB,anon-rss:1332040kB,file-rss:32kB,shmem-rss:0kB,UID:0 pgtables:3144kB oom_sco>
Sep  6 17:45:12 cs1 kernel: [67093.764851] oom_reaper: reaped process 15754 (my_app),now anon-rss:0kB,file-rss:0kB,shmem-rss:0kB

所以难怪python没有告诉我任何东西,它的进程被杀死了……

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...