geoip2报“permission denied”主因是路径错误或文件无读权限,需用绝对路径并chmod +r;addressnotfounderror因免费库覆盖不全,应过滤私有ip并设fallback;django限流须透传真实ip并缓存reader实例。

GeoIP2 库安装后 geoip2.database.Reader 报错 “Permission denied”
常见于用 pip install geoip2 装完,但直接读取下载的 GeoLite2-Country.mmdb 文件时权限被拒。根本原因不是 Python 权限问题,而是文件路径没给对,或者文件本身没读权限(尤其 macOS/Linux 下从浏览器下载后默认无读标志)。
- 确认文件路径是绝对路径,
Reader不支持相对路径或 URL - 运行
ls -l /path/to/GeoLite2-Country.mmdb,确保当前用户有r权限;没有就执行chmod +r /path/to/GeoLite2-Country.mmdb - 别把
.tar.gz压缩包当数据库用——必须解压出.mmdb文件,Reader只认这个二进制格式 - Windows 用户注意反斜杠转义:用原始字符串
r"C:\data\GeoLite2-Country.mmdb"或正斜杠"C:/data/GeoLite2-Country.mmdb"
用 geoip2.database.Reader 查 IP 时返回 AddressNotFoundError
这不是代码写错了,而是 GeoIP2 数据库本身不包含该 IP 的地理信息。免费版 GeoLite2 本身就有覆盖缺口,尤其对内网、新分配段、云厂商私有 IP(如 AWS 100.64.0.0/10)、Docker 网桥地址(172.17.0.0/16)基本不收录。
- 先用
ipaddress.ip_address("192.168.1.100").is_private过滤掉私有地址,避免无效查询 - 对公网 IP 查询失败时,建议 fallback 到默认区域(比如
"unknown"或"global"),别让整个请求崩掉 - 别依赖
country.iso_code一定存在——有些 IP 只能定位到大陆(continent.code == "NA"),country 层可能为None - 测试时别只用
127.0.0.1或本地局域网 IP,它必然查不到;用已知公网 IP 如"8.8.8.8"验证流程
Django 中基于 GeoIP2 做地理位置限流,get_client_ip() 拿到的是代理 IP
真实场景中,用户请求往往经过 Nginx、CDN 或云 WAF,request.META.get("REMOTE_ADDR") 拿到的是最后一跳代理的 IP,不是用户真实出口 IP。直接拿它查 GeoIP2,限流规则就全歪了。
ECTouch是上海商创网络科技有限公司推出的一套基于 PHP 和 MySQL 数据库构建的开源且易于使用的移动商城网店系统!应用于各种服务器平台的高效、快速和易于管理的网店解决方案,采用稳定的MVC框架开发,完美对接ecshop系统与模板堂众多模板,为中小企业提供最佳的移动电商解决方案。ECTouch程序源代码完全无加密。安装时只需将已集成的文件夹放进指定位置,通过浏览器访问一键安装,无需对已有
- 必须配置 Nginx 透传真实 IP:
proxy_set_header X-Real-IP $remote_addr;,然后在 Django 里用request.META.get("HTTP_X_REAL_IP") - 如果用了 Cloudflare,优先读
HTTP_CF_CONNECTING_IP;阿里云 SLB 是HTTP_X_FORWARDED_FOR最左非私有 IP - 别硬编码解析逻辑——用
django-ipware库的get_client_ip(request),它内置了多层 header 解析和私有网段过滤 - 拿到 IP 后,再查
geoip2前加一层缓存(比如functools.lru_cache(maxsize=1000)),避免高频重复查同一个国家
用 geoip2.database.Reader 在高并发下卡顿或内存暴涨
Reader 实例本身是线程安全的,但每次 new 一个新实例(比如在视图里 Reader("/path/mmdb"))会重新 mmap 整个文件,开销极大。Python 进程里多个线程共用一个 Reader 实例即可,不用锁。
立即学习“Python免费学习笔记(深入)”;
- 全局单例初始化:在 Django 的
apps.py或模块顶层创建一次reader = geoip2.database.Reader("/path/GeoLite2-Country.mmdb") - 别在函数内反复 open/close ——
Reader不需要手动 close,进程退出时自动释放 mmap - 如果用 Gunicorn 多 worker,每个 worker 进程都得有自己的
Reader实例(不能跨进程共享 mmap),所以初始化要放在 worker 启动后(比如gunicorn.conf.py的post_fork钩子) - 注意 mmdb 文件大小:GeoLite2-Country 约 40MB,mmap 后实际占用虚拟内存远大于此,但 RSS 增长可控;若用 City 版本(>150MB),需评估内存余量









