Python使用requests发送POST请求出现重复提交问题如何解决
问题根因排查
- 核心原因:按钮点击事件被重复绑定。你将myFunction绑定到按钮点击事件的逻辑被执行了多次,每执行一次就给同一个按钮新增一个回调触发入口,没有清理旧的绑定关系。最终第n次点击按钮时,会一次性触发之前所有绑定的n次myFunction回调,自然就会发出n次请求,和你观察到的“第一次点击运行1次、第二次点击运行2次”的现象完全吻合。
- 次要原因:你提供的代码片段里将
import requests写在了函数内部的try块中,虽然不会直接导致重复请求,但属于不规范写法,同时requests默认的隐式重试机制可能会放大重复请求的问题。 - 所谓的“缓存”请求只是错觉:前几次点击触发的多轮请求刚好因为网络等问题触发了异常分支,等到第4次点击时所有并发/串行发出的请求都请求成功,后端就会一次性收到多条记录。
解决方案
修复事件绑定逻辑,确保回调仅绑定一次
将按钮的事件绑定逻辑移到程序初始化阶段的一次性执行代码块中,不要放在弹窗加载、界面刷新这类会重复执行的逻辑里。如果无法避免重复执行绑定代码,每次绑定前先解绑旧的回调:- Tkinter 框架:先调用
button.unbind('<Button-1>')移除旧绑定,再执行bind操作 - PyQt/PySide 框架:先调用
button.clicked.disconnect(myFunction)断开旧连接,再执行connect操作 - 其他GUI/Web前端框架同理,保证同一个按钮的点击回调唯一。
- Tkinter 框架:先调用
优化请求代码,禁用隐式重试
将import语句移到文件头部,手动配置requests的重试策略,避免请求失败后无感知重试:
import requests import json from requests.adapters import HTTPAdapter, Retry # 全局初始化请求会话,配置重试规则 session = requests.Session() # 最多重试1次,你可以根据需求调整为0完全禁用重试 retry_strategy = Retry(total=1, backoff_factor=1, allowed_methods=["POST"]) adapter = HTTPAdapter(max_retries=retry_strategy) session.mount("http://", adapter) session.mount("https://", adapter) def myFunction(main_dict, data1, data2): # Send to server json_to_send = json.dumps(main_dict) try: r = session.post( "http://localhost/insert.php", data = {'data1': data1, "data2": data2}, headers = {'Cache-Control': 'no-cache'} ) if r.text == 'OK': print("Received by server") else: print("Server error. Try again") except requests.exceptions.RequestException as e: print("Error to send") return
- 后端增加幂等校验(可选,兜底避免重复数据)
给每个请求生成唯一的请求ID,和data1、data2一起传给后端,后端入库前先校验该ID是否已经处理过,已经处理过直接返回OK,彻底避免重复插入的问题。
内容的提问来源于stack exchange,提问作者Pedro Antônio
相关产品推荐
相关产品推荐

