一个隐秘在角度的bug
共 2861字,需浏览 6分钟
·
2021-03-14 22:56
前几天一直被一个bug 困扰着, 代码是一段requests请求url读取html内容的代码,每次程序启动大约运行几十个小时后,就开始报错MemoryError。
把核心代码提出来就一行代码
r = requests.get('https://xxxx')
错误堆栈日志大概是这样的
File "***.py", line 644, in 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 424, in post
return self.request('POST', url, data=data, **kwargs)
File "/usr/local/lib/python3.7/dist-packages/requests_cache/core.py", line 110, in request
hooks, stream, verify, cert)
File "/usr/local/lib/python3.7/dist-packages/requests/sessions.py", line 348, in request
prep = self.prepare_request(req)
File "/usr/local/lib/python3.7/dist-packages/requests/sessions.py", line 286, in prepare_request
hooks=merge_hooks(request.hooks, self.hooks),
File "/usr/local/lib/python3.7/dist-packages/requests/models.py", line 289, in prepare
self.prepare_body(data, files)
File "/usr/local/lib/python32.7/dist-packages/requests/models.py", line 426, in prepare_body
(body, content_type) = self._encode_files(files, data)
File "/usr/local/lib/python3.7/dist-packages/requests/models.py", line 144, in _encode_files
body, content_type = encode_multipart_formdata(new_fields)
File "/usr/local/lib/python3.7/dist-packages/requests/packages/urllib3/filepost.py", line 101, in 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,其实都是我们在平时编码过程中的没注意细节埋下的坑,魔鬼在细节。