Windows系统下Flask导出CSV时阿拉伯文显示为Latin-9的解决方法
解决Flask导出CSV中阿拉伯文在Windows下显示为Latin-9乱码的问题
这个问题在Windows系统处理非英文CSV时特别常见——核心原因是Windows下多数CSV阅读器(比如Excel)默认不会自动识别无BOM的UTF-8编码,会改用系统默认的Latin-9(Windows-1252)编码解析内容;而记事本现在已经支持自动检测UTF-8,所以能正常显示阿拉伯文。
要解决这个问题,只需要给导出的CSV文件加上UTF-8 BOM(字节顺序标记),让Windows系统明确知道文件使用UTF-8编码。下面是两种简单的修改方式:
方案一:使用utf-8-sig编码(最简便)
Python的encode('utf-8-sig')会自动在字节流开头添加UTF-8 BOM标记,无需手动处理。只需要修改代码中写入BytesIO的那一行:
# 原代码 mem.write(si.getvalue().encode()) # 修改为 mem.write(si.getvalue().encode('utf-8-sig'))
方案二:手动写入UTF-8 BOM(更直观)
如果你希望明确控制BOM的写入流程,可以先手动写入BOM字节,再写入编码后的内容:
mem = BytesIO() # 先写入UTF-8 BOM标记 mem.write(b'\xef\xbb\xbf') # 再写入UTF-8编码的CSV内容 mem.write(si.getvalue().encode('utf-8')) mem.seek(0)
修改后的完整代码
这里给出用方案一修改后的完整代码,确保阿拉伯文能在Windows下的Excel、WPS等软件中正常显示:
import csv from io import BytesIO, StringIO from flask import Flask, send_file from flask_sqlalchemy import SQLAlchemy app = Flask(__name__, instance_relative_config=True) app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///app.sqlite3" db = SQLAlchemy(app) class Device(db.Model): __tablename__ = "device" id = db.Column(db.Integer, primary_key=True) serial = db.Column(db.String(255), nullable=True) city = db.Column(db.String(255), nullable=True) office = db.Column(db.String(255), nullable=True) def __repr__(self): return f"<Device {self.serial!r}, {self.city!r}, {self.office!r}>" with app.app_context(): db.create_all() device1 = Device(serial="ASDF4321", city="مصر", office="مصر") device2 = Device(serial="FDSA1234", city="السعودية", office="السعودية") db.session.add(device1) db.session.add(device2) db.session.commit() @app.route("/", methods=["GET"]) def index(): return "Home" @app.route("/export", methods=["GET", "POST"]) def export(): si = StringIO() devices = Device.query.all() csvwriter = csv.writer(si, delimiter=",", quotechar='"', quoting=csv.QUOTE_MINIMAL) csvwriter.writerow(["ID", "Serial", "City", "Office"]) for i, device in enumerate(devices, start=1): csvwriter.writerow([i, device.serial, device.city, device.office]) mem = BytesIO() # 关键修改:使用utf-8-sig编码自动添加BOM mem.write(si.getvalue().encode('utf-8-sig')) mem.seek(0) si.close() return send_file( mem, mimetype="text/csv", download_name="Export-File.csv", as_attachment=True ) if __name__ == "__main__": app.run(debug=True)
为什么这样能解决问题?
- UTF-8 BOM(
\xef\xbb\xbf)是一个特殊的字节序列,Windows系统的应用程序会识别这个标记,从而用UTF-8编码读取文件,而不是默认的Latin-9。 - 记事本之所以能正常显示,是因为它现在支持自动检测无BOM的UTF-8编码,但Excel等办公软件还需要明确的BOM标记才能正确识别非英文内容。
内容的提问来源于stack exchange,提问作者Tes3awy
相关产品推荐
相关产品推荐

