网站监控脚本触发RecursionError问题求助
解决Python网站监控脚本的递归深度超限问题
问题重现
用户编写的网站监控脚本运行时抛出错误:
RecursionError: maximum recursion depth exceeded while calling a Python object
原脚本代码:
import requests import datetime import time from discord_webhook import DiscordWebhook, DiscordEmbed s = requests.Session() headers = {} # 需补充实际请求头 def login(userName, passWord): data = { 'loginID': userName, 'password': passWord, 'btnallgo': 'SUBMIT', } print(f'[{datetime.now()}] | Posting Login => [asp]') response = s.post('http://bcps.browardschools.com/virtualcounselor/bsvc/loginstudent.asp', headers=headers, data=data, verify=False) login('#yourusername','#yourpassword') def monitor(): params = { 'markper': '1', } print(f'[{datetime.now()}] | Checking Content => [get/asp]') response = s.get('https://bcps.browardschools.com/VirtualCounselor/bsvc/studentsched.asp', params=params, headers=headers) print(f'[{datetime.now()}] | Page Response => [{response.content}]') if response.content == (b'<P align=center><font color=red size=3><b>Your class schedule is currently unavailable.<br><br><br> Thank You</b></P>'): print(f'[{datetime.now()}] | Schedule unavailable, retrying') time.sleep(2.4) monitor() elif response.content == (b'\r\n\r\n\r\n<HTML>\r\n<HEAD>\r\n<TITLE>APPLICATION TIMEOUT</TITLE></HEAD>\r\n<BODY BGCOLOR=WHITE LINK=RED ALINK=RED VLINK=RED>\r\n<P ALIGN=CENTER><BR><BR><FONT COLOR=RED SIZE=5>- APPLICATION HAS TIMED OUT -</FONT><BR><BR>FOR SECURITY MEASURES YOUR SESSION HAS TIMED OUT<BR>AFTER 15 MINUTES OF INACTIVITY OR WHEN YOU LOGGED OFF.<BR>PLEASE <A HREF="https://bcps.browardschools.com/virtualcounselor" TARGET="_parent">CLICK HERE</A> TO RELOGIN.</P>\r\n</BODY>\r\n</HTML> \r\n\r\n'): print(f'Generating new session{response.status_code}') login() else: print(f'[{datetime.now()}] | Page Updated => {response.content}') webhook = DiscordWebhook(url='#yourwebhookhere') embed = DiscordEmbed(title='Page Update', description=f'{response.text}', color='03b2f8') embed.set_timestamp() webhook.add_embed(embed) response = webhook.execute() if response.status_code == 200: print(f'Sent webhook[status:{response.status_code}]') else: print(f'Error sending webhook[status:{response.status_code}]') refresh = monitor()
问题原因
脚本中monitor函数在检测到日程不可用时,通过递归调用自身实现循环重试。Python默认递归深度限制为1000左右,当重试次数超过这个限制时,就会触发RecursionError。此外,超时分支中login()调用未传入用户名和密码参数,也会导致后续运行报错。
解决方案
方案1:用while循环替代递归(推荐)
将递归逻辑改为无限循环,彻底避免递归深度限制问题,同时修复login调用的参数问题:
import requests import datetime import time from discord_webhook import DiscordWebhook, DiscordEmbed s = requests.Session() headers = {} # 补充实际请求头 USERNAME = '#yourusername' PASSWORD = '#yourpassword' WEBHOOK_URL = '#yourwebhookhere' def login(userName, passWord): data = { 'loginID': userName, 'password': passWord, 'btnallgo': 'SUBMIT', } print(f'[{datetime.now()}] | Posting Login => [asp]') response = s.post('http://bcps.browardschools.com/virtualcounselor/bsvc/loginstudent.asp', headers=headers, data=data, verify=False) def monitor(): login(USERNAME, PASSWORD) while True: params = { 'markper': '1', } print(f'[{datetime.now()}] | Checking Content => [get/asp]') try: response = s.get('https://bcps.browardschools.com/VirtualCounselor/bsvc/studentsched.asp', params=params, headers=headers) print(f'[{datetime.now()}] | Page Response => [{response.content[:100]}...]') # 截断输出避免过长 except Exception as e: print(f'[{datetime.now()}] | Request failed: {str(e)}') time.sleep(5) continue unavailable_msg = b'<P align=center><font color=red size=3><b>Your class schedule is currently unavailable.<br><br><br> Thank You</b></P>' timeout_msg = b'\r\n\r\n\r\n<HTML>\r\n<HEAD>\r\n<TITLE>APPLICATION TIMEOUT</TITLE></HEAD>\r\n<BODY BGCOLOR=WHITE LINK=RED ALINK=RED VLINK=RED>\r\n<P ALIGN=CENTER><BR><BR><FONT COLOR=RED SIZE=5>- APPLICATION HAS TIMED OUT -</FONT><BR><BR>FOR SECURITY MEASURES YOUR SESSION HAS TIMED OUT<BR>AFTER 15 MINUTES OF INACTIVITY OR WHEN YOU LOGGED OFF.<BR>PLEASE <A HREF="https://bcps.browardschools.com/virtualcounselor" TARGET="_parent">CLICK HERE</A> TO RELOGIN.</P>\r\n</BODY>\r\n</HTML> \r\n\r\n' if response.content == unavailable_msg: print(f'[{datetime.now()}] | Schedule unavailable, retrying') time.sleep(2.4) elif response.content == timeout_msg: print(f'[{datetime.now()}] | Session timed out, re-logging in') login(USERNAME, PASSWORD) time.sleep(1) else: print(f'[{datetime.now()}] | Page Updated => {response.content[:100]}...') try: webhook = DiscordWebhook(url=WEBHOOK_URL) embed = DiscordEmbed(title='Page Update', description=f'{response.text[:500]}...', color='03b2f8') embed.set_timestamp() webhook.add_embed(embed) webhook_response = webhook.execute() if webhook_response.status_code == 200: print(f'Sent webhook[status:{webhook_response.status_code}]') else: print(f'Error sending webhook[status:{webhook_response.status_code}]') except Exception as e: print(f'[{datetime.now()}] | Webhook failed: {str(e)}') # 发送通知后可选择退出或继续监控,这里设置继续 time.sleep(60) # 更新后延迟再监控 if __name__ == '__main__': monitor()
关键改进点:
- 用
while True无限循环替代递归调用,彻底摆脱递归深度限制 - 将用户名、密码、Webhook URL抽成全局常量,避免重复硬编码
- 修复超时分支中
login()的参数缺失问题 - 添加异常捕获,处理请求或Webhook发送失败的情况
- 截断过长的输出内容,避免控制台刷屏
方案2:调整递归深度限制(不推荐)
如果坚持使用递归,可以通过sys.setrecursionlimit提高递归深度,但这只是临时解决方案,仍存在栈溢出风险,且无法真正实现无限运行:
import sys sys.setrecursionlimit(10000) # 提高递归深度限制
同时需要修复超时分支的login()参数问题:login(USERNAME, PASSWORD)。但这种方法本质上还是依赖递归,长期运行仍可能触发错误,因此不推荐。
内容的提问来源于stack exchange,提问作者user19422024
相关产品推荐
相关产品推荐

