PIL.Image 默认无法直接获取 GPS 数据,因 GPSInfo(Tag 34853)藏于 EXIF 嵌套结构中,需二次解析;piexif 更可靠,能自动处理 Rational 类型与非标准写入,并建议配合异常捕获、格式筛选及有效性验证使用。

用 PIL.Image 读取 EXIF 但拿不到 GPS 数据?
PIL.Image(即 Pillow)默认能读出 EXIF 字典,但 GPS 信息通常藏在子目录里,不是顶层键。直接 img._getexif() 返回的字典里大概率没有 GPSInfo,或者有但值是空元组、None——这不是图片没数据,而是没正确解析嵌套结构。
实操要点:
-
img._getexif()返回的是原始 TAG 映射(如271表示制造商),需用PIL.ExifTags.GPS或手动查表定位 GPS 区域 - 真正 GPS 坐标存在
ExifTag 34853(即GPSInfo)对应的值中,该值本身是个字典,需二次解包 - 务必检查
img.getexif() is not None且34853 in exif,再进 GPS 子字典,否则会KeyError或AttributeError
piexif 比 PIL 更稳地提取 GPS 坐标
原生 PIL 对 GPS 格式兼容性差,尤其遇到 Canon/Nikon 的非标准写入或含 Rational 类型经纬度时容易崩。推荐改用 piexif——它专为 EXIF 设计,自动处理类型转换和嵌套层级。
示例流程:
立即学习“Python免费学习笔记(深入)”;
仅使用 Python 将 Claw Code 虚拟化框架与 OpenClaw 集成,提供 184 种工具和 200 多条命令,用于安全分析和代码质量...
import piexif
from fractions import Fraction
<p>def get_gps_coords(img_path):
try:
exif_dict = piexif.load(img_path)
gps_ifd = exif_dict.get("GPS", {})
if not gps_ifd:
return None</p><h1>提取纬度:(deg, min, sec) 三元组,类型为 Fraction</h1><pre class='brush:python;toolbar:false;'> lat_ref = gps_ifd.get(1, b"N")
lat = gps_ifd.get(2)
lon_ref = gps_ifd.get(3, b"E")
lon = gps_ifd.get(4)
if not (lat and lon):
return None
# 转 decimal:Fraction → float → 度分秒转十进制度
def to_deg(value):
d, m, s = value
return float(d) + float(m)/60 + float(s)/3600
lat_dec = to_deg(lat) * (-1 if lat_ref == b"S" else 1)
lon_dec = to_deg(lon) * (-1 if lon_ref == b"W" else 1)
return {"lat": lat_dec, "lon": lon_dec}
except Exception as e:
print(f"{img_path}: {e}")
return None</pre>批量处理多图时,别忽略文件编码和权限问题
循环读图看似简单,但实际常卡在:UnicodeDecodeError(路径含中文)、PermissionError(缩略图或只读文件)、OSError: cannot identify image file(非图/损坏/HEIC 格式)。这些错误会让整个批量中断,必须单独捕获。
关键建议:
- 用
pathlib.Path处理路径,避免字符串拼接导致的编码歧义 - 对每个文件加
try/except OSError和except ValueError(piexif解析失败) - 跳过非主流格式:先用
imghdr.what(path)初筛jpeg/tiff,不碰heic、webp(除非装pyheif或webp扩展) - 结果建议存成 CSV,字段含
filename、lat、lon、error,方便后续排查哪张图没坐标
EXIF 地理位置其实经常“有记录但无效”
拿到 {"lat": 0.0, "lon": 0.0} 或 {"lat": 39.9042, "lon": 116.4074}(北京天安门)这种固定值,大概率是手机系统伪造的占位符,不是真实拍摄点。iOS 14+ 和部分安卓相册 App 默认关闭精确位置,只写「已启用定位服务」而非真实坐标。
验证方式:
- 用系统自带照片应用查看「详细信息」,比对是否显示「精确位置」字样
- 命令行快速验证:
exiftool -GPSLatitude -GPSLongitude your.jpg(需装exiftool) - 若所有图返回同一经纬度,或
GPSDateStamp是 1970:01:01,基本可判定未开启拍照时定位授权
真正在野外采集的 GPS 数据,GPSAltitude、GPSTimeStamp 通常也非空;纯零值组合,八成是摆设。

















