Flask中如何将Python函数输出转为合法JSON并传递给HTML内嵌JS
解决Flask串口数据转JSON并在前端展示的问题
问题根源
/loaddata路由返回Python集合{output2},Flask无法将集合序列化为合法JSON,且响应头未设置为application/json,导致前端response.json()解析失败。- 前端
document.write(data)存在作用域错误:data是fetch回调内的局部变量,页面初始化时无法访问;同时document.write会覆盖页面内容,不适合动态更新数据。 - 每次请求都重新打开串口,易引发资源占用、连接异常等问题。
解决方案
1. 修复/loaddata路由,返回合法JSON
修改路由代码,返回包含数据的字典(Flask会自动将字典序列化为JSON并设置正确响应头),用with语句管理串口连接避免资源泄漏,添加异常处理:
import serial import time from flask import Flask, jsonify # 假设app已完成初始化 @app.route('/loaddata', methods=['GET']) def loaddata(): try: # with语句自动管理串口连接,请求结束后自动关闭 with serial.Serial( port='/dev/ttyACM0', baudrate=57600, timeout=1 ) as ser: ser.reset_input_buffer() output2 = "" for x in range(8): line = ser.readline().decode('utf-8').rstrip() print(line) output2 += line + "\n" # 添加换行符,让每行数据在前端更易读 time.sleep(0.01) print("connected to: " + ser.portstr) # 返回包含数据的字典,Flask自动转JSON并设置响应头 return jsonify({"sensor_data": output2}) except Exception as e: # 捕获异常并返回错误信息,方便排查问题 return jsonify({"error": str(e)}), 500
2. 修复前端代码,正确接收并展示数据
修改sensor路由的HTML部分,添加数据展示容器,并在fetch回调中更新DOM:
@app.route('/sensor', methods=['GET', 'POST']) def sensor(): output = '''<!DOCTYPE html> <html lang="en"> <head> <meta name="viewport" content="width=device-width, initial-scale=1"> <style> body{ background: #005E60; background-size: 100% 100%; height: 100vh; /* 保留原有样式 */ } #sensor-data { color: white; font-size: 18px; margin-top: 20px; white-space: pre-wrap; /* 保留换行符,让数据格式更清晰 */ } </style> </head> <body> <div class="Box"> <div class="flex-box"> <p><a href='http://172.23.2.132:5000/camera' style='width: 210px; height:80px;color:white; font-size: 23px; '>Click here to get back</a></p> <!-- 添加专门的容器用于展示传感器数据 --> <div id="sensor-data"></div> </div> </div> <script type="text/javascript"> function loop(){ fetch('/loaddata') .then(response => { if (!response.ok) { throw new Error('Network response was not ok'); } return response.json(); }) .then(data => { console.log('Data received:', data); const dataContainer = document.getElementById('sensor-data'); // 处理正常数据和错误情况 if (data.error) { dataContainer.textContent = "Error: " + data.error; } else { dataContainer.textContent = data.sensor_data; } }) .catch(error => { console.error('There was a problem with the fetch operation:', error); document.getElementById('sensor-data').textContent = "Fetch error: " + error.message; }); } var intervalId = window.setInterval(loop, 1000); </script> </body> </html>''' return output
关键说明
- 使用
jsonify返回响应:Flask的jsonify函数会自动处理JSON序列化,并设置Content-Type: application/json响应头,确保前端能正确解析。 - 串口连接优化:
with语句自动关闭串口,避免多次请求导致的串口占用问题。 - 前端DOM更新:通过指定容器的
textContent更新数据,避免document.write的副作用,同时处理错误情况提升体验。
内容的提问来源于stack exchange,提问作者Kevin Keller
相关产品推荐
相关产品推荐

