从Flask切换到Gunicorn后数据库返回图片路径转为bytearray格式导致链接失效的问题
从Flask切换到Gunicorn后数据库返回图片路径转为bytearray格式导致链接失效的问题
我之前也碰到过类似的坑——同一个Flask应用在开发服务器上跑一切正常,换成Gunicorn就出现数据库返回的字符串变成bytearray格式的情况,简直头大。咱们来拆解下问题和解决办法:
问题根源
这种差异大概率是数据库驱动在多进程环境下的行为变化导致的:
- Flask自带的开发服务器是单进程单线程模式,数据库连接的初始化和数据读取全程在同一个进程里,驱动会正常把数据库里的字符串字段返回为Python的
str类型。 - 而Gunicorn默认采用多进程(fork模式)启动,fork出来的子进程复用了父进程的数据库连接,这时候部分数据库驱动(比如mysql-connector-python)会把字符串字段返回成
bytearray类型,直接渲染到模板里就会出现bytearray(b'xxx.jpg')这种畸形路径。
解决方案(按推荐优先级排序)
1. 后端查询结果中统一转换bytearray为字符串
在拿到数据库查询结果后,遍历每条数据,把bytearray类型的字段解码成字符串,这样模板可以直接使用:
@app.route("/inventory") def inventory(): global ITEM_IMAGE_DIR # ... 原有查询代码 ... cursor.execute(inv_query,(limit,offset)) result = cursor.fetchall() cursor.close() # 新增:转换结果中的bytearray为字符串 def convert_byte_fields(row): converted = [] for value in row: if isinstance(value, bytearray): # 按你的数据库编码调整,一般是utf-8 converted.append(value.decode('utf-8')) else: converted.append(value) return tuple(converted) item_list = [convert_byte_fields(row) for row in result] # ... 原有视图逻辑 ...
2. 调整数据库连接配置
直接让数据库驱动返回字符串类型,避免后续转换。以mysql-connector-python为例,在建立连接时添加use_unicode=True和charset参数:
import mysql.connector mydb = mysql.connector.connect( host="你的数据库地址", user="用户名", password="密码", database="数据库名", use_unicode=True, charset='utf8mb4' # 推荐用utf8mb4兼容所有字符 )
如果用的是MySQLdb(pymysql),连接时指定charset='utf8mb4'也能解决类似问题。
3. 模板中临时兼容(不推荐)
如果赶时间可以临时在模板里做转换,但不建议长期这么用——模板应该专注于渲染,尽量不要处理数据逻辑:
<img src="{{ ITEM_IMAGE_DIR }}{{ item_pic.decode('utf-8') if isinstance(item_pic, bytearray) else item_pic }}" class="thumbnail" alt="item image" style="display:inline-block; max-width:230px; max-height:50px; width: auto; height: auto;">
总结
优先调整数据库连接配置或者在后端处理数据转换,这样能从根源上解决问题,也符合MVC的分层逻辑。多进程环境下数据库连接的复用经常会出现这类隐性问题,排查的时候可以先关注驱动的进程安全特性~
内容来源于stack exchange
相关产品推荐
相关产品推荐

