RecursionError: maximum recursion depth exceeded while calling a Python object
File "/root/miniconda3/envs/devops/lib/python3.8/site-packages/urllib3/connectionpool.py", line 699, in urlopen
httplib_response = self._make_request(
File "/root/miniconda3/envs/devops/lib/python3.8/site-packages/urllib3/connectionpool.py", line 382, in _make_request
self._validate_conn(conn)
File "/root/miniconda3/envs/devops/lib/python3.8/site-packages/urllib3/connectionpool.py", line 1010, in _validate_conn
conn.connect()
File "/root/miniconda3/envs/devops/lib/python3.8/site-packages/urllib3/connection.py", line 392, in connect
self.ssl_context = create_urllib3_context(
File "/root/miniconda3/envs/devops/lib/python3.8/site-packages/urllib3/util/ssl_.py", line 312, in create_urllib3_context
context.options |= options
File "/root/miniconda3/envs/devops/lib/python3.8/ssl.py", line 602, in options
super(SSLContext, SSLContext).options.__set__(self, value)
File "/root/miniconda3/envs/devops/lib/python3.8/ssl.py", line 602, in options
super(SSLContext, SSLContext).options.__set__(self, value)
File "/root/miniconda3/envs/devops/lib/python3.8/ssl.py", line 602, in options
super(SSLContext, SSLContext).options.__set__(self, value)
[Previous line repeated 468 more times]
RecursionError: maximum recursion depth exceeded while calling a Python object
注意看上面特殊颜色标注的内容,表示超过了468的深度。
1)代码问题,逻辑编写错误导致了递归溢出,比如代码小白,写个递归死循环了。这种情况不适用本篇文章。
2) 代码太庞大了,调用深度太深!
问题翻译解释: 超过最大递归深度,当然这个只是字面意思。其实是可以复现这个问题的
python有调用深度控制,默认是1000,我们可以通过sys.setrecursionlimit(N)来设置调用深度为N;报错的意思虽然是说递归深度超过限制,但不要局限于递归问题,其实也是调用堆栈的问题,涉及到C的一些基础....
比如以下代码,设置递归深度为20时,会报错RecursionError,然后改成21便可以正常结束。这里如果不调用traceback函数,其实只需要设置成8就足够了。
import sys
#使用内置的包traceback可以获得堆栈信息
import traceback
#改成21的深度就可以正常,
sys.setrecursionlimit(20)
def a():
index = 0
#到这个函数只需要8层就足够了,但是下面的traceback.format_stack里面还有,超出了当前运行的py设置的深度,一样会报错
#不要这段for循环,上面setrecursionlimit(8)就可以了
for line in traceback.format_stack():
index +=1
print("当前位置调用深度:%s,详细堆栈:%s" % (index, line.strip()))
return "调用结束"
def b():
return a()
def c():
return b()
def d():
return c()
def e():
return d()
def f():
return e()
print(f())
运行结果如下:
正常的输出结果如下:
调用深度:1,详细堆栈:File "D:/my_code/pycde/testtss.py", line 21, in
print(f())
调用深度:2,详细堆栈:File "D:/my_code/pycde/testtss.py", line 19, in f
return e()
调用深度:3,详细堆栈:File "D:/my_code/pycde/testtss.py", line 17, in e
return d()
调用深度:4,详细堆栈:File "D:/my_code/pycde/testtss.py", line 15, in d
return c()
调用深度:5,详细堆栈:File "D:/my_code/pycde/testtss.py", line 13, in c
return b()
调用深度:6,详细堆栈:File "D:/my_code/pycde/testtss.py", line 11, in b
return a()
调用深度:7,详细堆栈:File "D:/my_code/pycde/testtss.py", line 6, in a
for line in traceback.format_stack():
调用结束
如果看懂了解析,就明白了为什么会报错RecursionError,一般用开源的项目,或者项目架构的过深,就会导致层层套娃。
#设置递归深度为很大很大,比如设置成10000。正常的程序架构都不会调用深度超过10000
不要设置太大!这个机制是为了避免真的出现代码逻辑问题时,无限的递归死循环导致OOM系统崩溃。内存CPU打爆=>会出现什么结果? 嗯,很卡,然后你logout一下就登不进去了,然后就哦豁挂了,,,
import sys
print(sys.getrecursionlimit())
sys.setrecursionlimit(10000)
django项目只需要在manage.py的上面设置这个就可以了
至于网上说这个是临时解决的方案,其实就是永久方案.,大部分文章是抄袭之后知其然不知其所以然,所以觉得没有永久解决问题。
与https有关的模块,真的很深.... boto3 玩转 amazon 就几百层。然后钉钉关联的模块,但凡用到https的,很多会调用到ssl模块,也很深