django默认使用sqlite数据库,而使用sqlite是通过python来支持的,因为python本身内置sqlite支持,那么django——SQLite——python三者之间就有一个版本的对应关系,如果版本不配套,就可能报以下错误:
File "/xxxxxx/venv/lib/python3.9/site-packages/django/db/backends/sqlite3/base.py", line 68, in check_sqlite_version
raise ImproperlyConfigured(
django.core.exceptions.ImproperlyConfigured: SQLite 3.9.0 or later is required (found 3.7.17).
django3.2.9要求SQLite3.9.0以上的数据库,而目前我机器安装是3.7.17
事情的起因是把一台较新的系统上的依赖迁移到了相对较老的系统上,所以出现了版本不配套的问题。
那么怎么解决呢,要么升级SQLite,要么降低django的版本,我选择降低django的版本重新迁移依赖,因为都已经是迁移依赖了,目标机器根本没有网络,安装任何软件都会很麻烦。。
那么我要降低django到哪个版本才会适配SQLite3.7.17呢,去源码里看一看,django/db/backends/sqlite3/base.py的check_sqlite_version函数:
def check_sqlite_version():
if Database.sqlite_version_info < (3, 9, 0):
raise ImproperlyConfigured(
'SQLite 3.9.0 or later is required (found %s).' % Database.sqlite_version
)
非常一目了然,直接写死到代码里了,各个django版本与SQLite数据库的版本对应关系梳理如下:
django版本 | SQLite版本 |
---|---|
4.0.X | 3.9.0 |
3.2.X | 3.9.0 |
3.1.X | 3.8.3 |
3.0.X | 3.8.3 |
2.2.X | 3.8.3 |
2.1.X | 没找了,应该在其他的地方 |
之后降级django失败了,只能升级SQLite,升级SQLite用源码编译安装,之后还有一个坑,就是系统的SQLite升级,但是现有python使用的SQLite版本不升级。。。这块猜测可能python在编译安装的时候已经固定了,最后无奈又安装了一遍python。。。
查看python使用的SQLite版本方法:
import sqlite3
print(sqlite3.version_info) #显示sqlite3版本信息
print(sqlite3.sqlite_version) #显示SQLite版本信息
查看系统sqlite版本直接执行:
sqlite3
然而重装python也没有解决,最后是通过这个解决的:
export LD_LIBRARY_PATH="/usr/local/lib"
所以python使用的sqlite版本其实是导入时确定的。。。并不是在python中固定的,以上是一派胡言。。。
那为什么我在系统直接执行sqlite3就可以使用新版本的sqlite呢,应该是因为PATH的原因,系统会先找到/usr/local/bin下的sqlite3:
> echo $PATH
/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/check_user/.local/bin:/
那么既然python还可以找到老版本sqlite,说明sqlite在目前系统PATH里还是存在的,我执行:
> whereis sqlite3
sqlite3: /usr/bin/sqlite3 /usr/local/bin/sqlite3 /usr/include/sqlite3.h /usr/share/man/man1/sqlite3.1.gz
最后发现/usr/bin/sqlite3应该是老的sqlite3,现在因为源文件版本不匹配已经无法启动了,那么python又是如何导入的呢。。还是说现在python即使能导入也无法使用了:
SQLite header and source version mismatch
2021-11-27 14:13:22 bd41822c7424d393a30e92ff6cb254d25c26769889c1499a18a0b9339f5d6c8a
2013-05-20 00:56:22 118a3b35693b134d56ebd780123b7fd6f1497668
随后我干掉老sqlite3,发现我的猜测是错的,不设置LD_LIBRARY_PATH,python还是会导入老的sqlite3。。。以后再来研究
所以python使用的sqlite版本其实是导入时确定的。。。更换python使用的SQLite版本不需要重装python,只需要系统安装最新版本SQLite,然后设置LD_LIBRARY_PATH指向新版本路径,这样python就能使用新版本的SQLite了。