读取GEOSGeometry对象时触发DjangoUnicodeDecodeError的解决求助
解决Django GIS读取含非拉丁语系UTF-8字符串Shapefile的Unicode解码错误
你遇到的问题核心是GDAL自动检测的Shapefile编码与实际编码不匹配——处理波斯语这类非拉丁语系字符时,GDAL经常会误判.dbf文件的编码,导致Django的force_text方法用错误编码解码字节,触发DjangoUnicodeDecodeError。下面给你几个可行的解决方案,按推荐程度排序:
1. 手动指定Shapefile的编码读取
这是最直接的解决方案,先确认你的Shapefile实际使用的编码(波斯语常用Windows-1256,也可能是UTF-8但GDAL未正确识别),然后在初始化DataSource时显式指定编码:
from django.contrib.gis.gdal import DataSource # 替换为你Shapefile的实际编码,比如Windows-1256 ds = DataSource(shp_file_path, encoding='Windows-1256') lyr = ds[0] for feat in lyr: geom_t = feat.geom.transform(wgs84, clone=True) name = feat.get('name') # 现在能正确解码字段内容
如果你不确定编码,可以用GDAL的ogrinfo命令检测:
ogrinfo -so your_shapefile.shp
也可以尝试波斯语常见编码(Windows-1256、UTF-8)逐个测试。
2. 手动解码原始字节数据
如果指定编码仍无效,你可以绕过Django的自动解码逻辑,直接获取字段的原始字节,再用正确编码解码:
for feat in lyr: geom_t = feat.geom.transform(wgs84, clone=True) # 加上raw=True获取原始字节,避免Django自动解码出错 name_raw = feat.get('name', raw=True) # 用实际编码解码,比如Windows-1256 name = name_raw.decode('Windows-1256') # 若不确定编码,可临时用错误忽略模式应急(不推荐长期使用) # name = name_raw.decode('utf-8', errors='replace')
3. 临时修补Django的GDAL字段处理逻辑(不推荐)
如果前两种方法都无法解决,你可以临时修改Django源码(注意:升级Django后该改动会失效):
找到报错文件D:\Python\Python36\lib\site-packages\django\contrib\gis\gdal\field.py,修改as_string方法:
将原代码:
return force_text(string, encoding=self._feat.encoding, strings_only=True)
替换为:
# 强制指定正确编码,比如Windows-1256,同时增加错误处理 return force_text(string, encoding='Windows-1256', errors='replace', strings_only=True)
此方法仅作为临时应急方案,不推荐长期依赖,建议优先使用前两种方法从根源解决问题。
内容的提问来源于stack exchange,提问作者Majid Hojati
相关产品推荐
相关产品推荐

