FLASK页面打开时如何定时运行Python函数更新Folium地图?
最优实现方案
推荐优先使用「后端拆分独立接口 + 前端定时AJAX调用」的方式,比模拟点击逻辑更清晰、可维护性更高,实现步骤如下:
步骤1:修改Flask后端代码
首先拆分地图更新逻辑为独立接口,将用户首次提交的凭证存入Session避免重复传输:
from flask import session, jsonify import base64 import hermesMapGen # 注意需要先配置Flask的SECRET_KEY才能使用Session app.config['SECRET_KEY'] = '替换为你自己的随机密钥' @app.route('/hermesmap', methods=['GET','POST']) def hermesMap(): if request.method == "POST": userName = request.form['username'] password = request.form['password'] server = request.form['server'] server = server[8:-1] ascii_pass = base64.urlsafe_b64encode(password.encode("ASCII")) sshpass = str(ascii_pass).replace("b","").replace("\'","") # 凭证存入Session session['hermes_auth'] = { 'username': userName, 'sshpass': sshpass, 'server': server } # 首次调用更新 hermesMapGen.mapUpdate(userName,sshpass,server) return render_template("hermesMap.html") # 新增独立的地图更新接口 @app.route('/update_hermes_map', methods=['GET']) def update_hermes_map(): # 校验Session中是否有凭证 if not session.get('hermes_auth'): return jsonify({'status': 'error', 'msg': '未授权'}), 401 auth = session['hermes_auth'] try: hermesMapGen.mapUpdate(auth['username'], auth['sshpass'], auth['server']) return jsonify({'status': 'success'}) except Exception as e: return jsonify({'status': 'error', 'msg': str(e)}), 500
步骤2:修改前端hermesMap.html的JS逻辑
移除模拟点击代码,直接定时调用更新接口,成功后再刷新iframe:
<!DOCTYPE html> <html> {%block content%} <div class="custom-height-map" style="position:relative;padding-top:42.25%;border-style:solid;border-width:6px;"> <iframe src="{{url_for('static',filename='sfMarketMap.html')}}" id='hermesmap' frameborder="0" allowfullscreen style="position:absolute;top:0;left:0;width:100%;height:100%;"></iframe> </div> <script> // 每5分钟执行一次更新 window.setInterval(async function() { try { const res = await fetch('/update_hermes_map') if (res.ok) { // 更新成功后再刷新iframe reloadIFrame() console.log('地图更新成功') } else { console.error('地图更新失败,请重新登录') } } catch (e) { console.error('请求异常', e) } }, 300000); function reloadIFrame() { console.log('reloading map..'); // 加时间戳避免浏览器缓存旧地图 const iframe = document.getElementById('hermesmap'); iframe.src = iframe.src.split('?')[0] + '?t=' + new Date().getTime(); } </script> {%endblock%} </html>
可选优化方案
如果你的地图是所有用户共用、不需要按用户生成的场景,可以直接在后端用APScheduler定时执行mapUpdate,不需要前端触发:
from apscheduler.schedulers.background import BackgroundScheduler import hermesMapGen # 应用启动时开启定时任务,每5分钟更新一次地图 scheduler = BackgroundScheduler() scheduler.add_job(func=lambda: hermesMapGen.mapUpdate('固定用户名', '固定密码', '固定服务器地址'), trigger="interval", minutes=5) scheduler.start() # 应用关闭时停止调度器 @app.teardown_appcontext def shutdown_scheduler(exception=None): scheduler.shutdown()
注意:Flask开发模式下默认会启动两个进程,会导致定时任务执行两次,生产环境部署时正常,开发环境可以配置debug=False或者use_reloader=False避免。
注意事项
- 如果是多用户使用场景,建议生成的Folium地图文件名按用户ID区分,避免不同用户的地图互相覆盖
- 不要在前端明文传输、存储账号密码,Session存储的方案比前端存本地更安全
内容的提问来源于stack exchange,提问作者Ashot Avetisyan
相关产品推荐
相关产品推荐

