一个隐秘在角度的bug

python之禅

共 2861字,需浏览 6分钟

 ·

2021-03-14 22:56

前几天一直被一个bug 困扰着, 代码是一段requests请求url读取html内容的代码,每次程序启动大约运行几十个小时后,就开始报错MemoryError。

把核心代码提出来就一行代码

r = requests.get('https://xxxx')

错误堆栈日志大概是这样的

  File "***.py", line 644in post
    r = s.post(url, data=content, params=params, files=files, headers=headers)
  File "/usr/local/lib/python3.7/dist-packages/requests/sessions.py", line 424in post
    return self.request('POST', url, data=data, **kwargs)
  File "/usr/local/lib/python3.7/dist-packages/requests_cache/core.py", line 110in request
    hooks, stream, verify, cert)
  File "/usr/local/lib/python3.7/dist-packages/requests/sessions.py", line 348in request
    prep = self.prepare_request(req)
  File "/usr/local/lib/python3.7/dist-packages/requests/sessions.py", line 286in prepare_request
    hooks=merge_hooks(request.hooks, self.hooks),
  File "/usr/local/lib/python3.7/dist-packages/requests/models.py", line 289in prepare
    self.prepare_body(data, files)
  File "/usr/local/lib/python32.7/dist-packages/requests/models.py", line 426in prepare_body
    (body, content_type) = self._encode_files(files, data)
  File "/usr/local/lib/python3.7/dist-packages/requests/models.py", line 144in _encode_files
    body, content_type = encode_multipart_formdata(new_fields)
  File "/usr/local/lib/python3.7/dist-packages/requests/packages/urllib3/filepost.py", line 101in encode_multipart_formdata
    return body.getvalue(), content_type
MemoryError

错误提示很明显,应该是内存不足导致的

平时很少会遇到这个问题,估计你们也不怎么会遇到,除非确实是处理超大文件

我的排查思路是这样的

首先确定是不是我的系统真的内存不足了,然后就跑过去查看任务管理器,16G的内存,才使用了60%多点,应该说内存还是非常充足的。


接着又去分析是不是请求返回的数据非常大导致的,验证后不存在这个问题,因为请求的最大数据最大也就几百KB。

然后又把程序稍微优化了一下,看看是不是每次请求完之后资源没释放

with requests.Session() as s:
    s.get('https://xxxx')

改成with上下文处理,请求结束后会自动关闭请求连接。

经过一段时间的观察,然而并没什么卵用,问题依然存在

这个时候用Google、StackOverflow也找到合适的答案。

按照武侠小说剧情发展的话,在你最孤独最无助时,主角就会有灵光乍现的时刻。

无意间发现系统安装的Python3.7 是32位,当初安装的时候也没注意太多。


32位系统使用32位地址线的最大寻址空间为2的32次方bytes,计算后即4294967296 Bytes,也就是我们常说的4096MB,32位地址线的寻址空间封顶即为4GB。虽然我的系统是64位,但是python这个程序安装的是32位,通常应用程序占用内存不能超过2GB以上,如果超过就会发生内存溢出现象。

最后把Python升级到64位问题完美解决,持续运行了几天依然没有报错。


总结:

很多时候,我们遇到某些看似像灵异事件的bug,其实都是我们在平时编码过程中的没注意细节埋下的坑,魔鬼在细节。


浏览 16
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报