【问题标题】:Force Python to forego native sqlite3 and use the (installed) latest sqlite3 version强制 Python 放弃原生 sqlite3 并使用(已安装)最新的 sqlite3 版本
【发布时间】:2010-12-05 10:52:31
【问题描述】:

我试图摆脱的错误消息是:

AttributeError: 'sqlite3.Connection' 对象没有属性 'enable_load_extension'

我有'easy_install'-ed 最新的 sqlite3 版本,python 不知何故知道它在那里,因为 sqlite3.version_info 产生 3.6.13。在这个版本中,连接应该有“enable_load_extension”属性。

我认为发生的事情是 python 仍然使用我认为是 2.4.1 的本机 sqlite3 模块,因为 sqlite3.version (i.s.o. sqlite3.version_info) 产生 2.4.1。

问题是如何强制 python 对所有 sqlite3 调用使用新的 sqlite3 模块?

【问题讨论】:

    标签: python sqlite


    【解决方案1】:

    sqlite3 在 Python 中的支持可能有点令人困惑。 sqlite 数据库适配器最初是一个单独的项目,pysqlite2,但对于 Python 2.5,它的一个版本被合并到 Python 标准库中,名称为 sqlite3。原始适配器继续作为单独的项目开发,同时 Python 本身的版本会定期更新以匹配它。如果您尝试使用较新版本的适配器,通常将其安装为pysqlite2,以免与标准库中包含的版本冲突。而且,根据它的构建方式,它可能链接到底层sqlite3 database library 的不同版本。因此,请确保您正确导入它:

    >>> import sqlite3
    >>> sqlite3.version_info
    (2, 4, 1)
    >>> sqlite3.sqlite_version_info
    (3, 6, 11)
    
    >>> from pysqlite2 import dbapi2 as sqlite3
    >>> sqlite3.version_info
    (2, 5, 5)
    >>> sqlite3.sqlite_version_info
    (3, 6, 18)
    

    version_infosqlite3pysqlite2 或内置sqlite3)数据库适配器的版本。 sqlite_version_info 是底层sqlite3 数据库库的版本。

    建议使用from ... import ... as sqlite3,这样当您从一个版本迁移到另一个版本时,您的其余代码无需更改。

    注意,enable_load_extension 最早出现在pysqlite2 2.5.0。

    编辑: enable_load_extension 在构建适配器时默认禁用。要启用它,您可以手动构建pysqlite2。以下配方假设使用unix-y 系统和pysqlite2 的最新版本,在撰写本文时为2.5.5。

    首先,如果您最初通过easy_install安装了适配器,请先运行将其卸载:

    $ sudo /path/to/easy_install -m pysqlite # or whatever package name you first used
    

    会有一些输出,包括如下行:

    Removing pysqlite 2.5.5 from easy-install.pth file
    
    Using /path/to/site-packages/pysqlite-2.5.5-py2.x-something.egg
    

    使用列出的文件名删除鸡蛋(名称会根据您的平台和版本而有所不同,它可能指的是文件或目录):

    $ sudo rm -r /path/to/site-packages/pysqlite-2.5.5-py2.x-something.egg
    

    现在下载并解压pysqlite-2.5.5 源压缩包:

    $ mkdir /tmp/build
    $ cd /tmp/build
    $ curl http://oss.itsystementwicklung.de/download/pysqlite/2.5/2.5.5/pysqlite-2.5.5.tar.gz | tar xz
    $ cd pysqlite-2.5.5
    

    然后编辑setup.cfg文件,将SQLITE_OMIT_LOAD_EXTENSION指令注释掉:

    $ ed setup.cfg <<EOF
    > /SQLITE_OMIT_LOAD_EXTENSION/s/define=/#define=/
    > w
    > q
    > EOF
    

    由于sqlite3 的版本太旧(3.4.0),您还应该使用最新的sqlite3 库构建。这在pysqlite2 setup.py 脚本中很容易:

    $ /path/to/python2.x setup.py build_static
    

    这将自动下载最新的sqlite3 amalgamation source 并构建适配器以及sqlite3 的最新静态链接版本。此步骤可能需要很长时间才能完成。

    更新(2015/07/21):根据最新的pysqlite 2.6.3 commit,您必须自行下载 sqlite 源代码并将它们放在 pysqlite 根文件夹中。

    现在,安装适配器:

    $ sudo /path/to/python2.x setup.py install
    

    并运行测试:

    $ cd     # somewhere out of the build directory
    $ /path/to/python2.x
    >>> from pysqlite2 import test
    >>> test.test()
    

    如果他们通过了,你应该准备好了。

    作为奖励,如果您想要加载扩展支持的原因是使用 sqlite3 的全文搜索扩展 FTS3,您应该会发现它已作为静态库的一部分包含在内,无需进一步工作必要的:

    >>> from pysqlite2 import dbapi2 as sqlite3
    >>> con = sqlite3.connect(":memory:")
    >>> con.execute("create virtual table recipe using fts3(name, ingredients)")
    <pysqlite2.dbapi2.Cursor object at 0xca5e0>
    

    【讨论】:

    • 亲爱的 Ned:这肯定对我有很大帮助 - 谢谢!现在我的python脚本在使用'from ... import ... as sqlite3'构造后似乎确实加载了适配器的最新版本,因为我得到2.5.5 for version_info和3.4.0 for sqlite_version。然而,更进一步,我尝试使用'enable_load_extension',我现在得到: AttributeError: 'pysqlite2.dbapi2.Connection' object has no attribute 'enable_load_extension' 根据你给我的所有信息,这似乎令人惊讶,不是吗?非常感谢您迄今为止的帮助 - 非常感谢! --阿尔伯特
    • 该死!我已经扩展了答案,包括如何在启用负载扩展支持和最新版本的 sqlite3 库的情况下构建适配器。
    • 它工作 - 它工作 - 它工作!我对这个 Ted 感到非常满意,非常感谢!我没有安装最新的python。而且,我什至没有执行您建议的 chmod 命令。不知何故,许可是在一夜之间完成的。今天早上的惊喜。再次感谢,这解决了问题。我相信其他人会从阅读您在这里的所有有用建议中受益。最好的,阿尔伯特
    • 它对我有用! (即使某些步骤失败了,我不得不手动执行)但仅在 Python2 上。有没有办法同时更新 Python3 的?
    • 遗憾的是,您无法在 Python3 中以这种方式启用_load_extension,因为 pysqlite2 仅适用于 Python2。为了 enable_load_extension,您必须使用 configure --enable-loadable-sqlite-extensions 标志重新编译 Python3。确实希望 pip 可以在 Python2 和 Python3 中处理这种自定义,例如: pip install pysqlite3 --configure-opts="--enable-loadable-sqlite-extensions"
    【解决方案2】:

    我在 Windows 机器上安装了 python 2.7,内置的 sqlite3.sqlite_version 是 3.6.x。通过执行以下步骤,我能够让它使用 sqlite 3.7.9。

    1. 下载并解压预编译的二进制 DLL(http://www.sqlite.org/download.html 上的“sqlite-dll-win32-x86-3070900.zip”)
    2. (为了安全起见,此时可能应该关闭所有 python 实例)转到 C:\Python27\DLLs 并将“sqlite3.dll”的文件名更改为“sqlite3.dll.old”
    3. 将“sqlite3.dll”文件复制到文件夹C:\Python27\DLLs
    4. 打开 python shell 并导入 sqlite3
    5. 验证 sqlite3.sqlite_version 是否显示为“3.7.9”

    【讨论】:

    • 谢谢威尔。但是我想知道新的 sqlite3.dll 和 python 2.7 之间是否没有不兼容的风险。? sqlite3 包代码。我想 sqlite3 包是针对特定的 sqlite3.dll 测试的,它的 API 可能会及时发展。也许您只是幸运地使用了这些特定版本和测试场景……或者是否有测试套件?
    • 嗨 Dim,我没有做任何测试,所以我可能只是走运了!
    • 似乎也对我有用。我从 3.6.21 到了 3.8.8.2,也就是 5 年的更新。
    【解决方案3】:

    您需要查看您的 Python 路径并确保您想要的 sqlite 安装在比内置 sqlite 更早的目录中。

    你可以看到路径:

    import sys
    print(sys.path)
    

    如果你想知道一个模块来自哪里,试试:

    print(sqlite3.__file__)
    

    【讨论】:

    • 亲爱的 Ned:这非常有用 - 非常感谢!在您发表评论和 Ned Deily 发表的评论之后,我觉得我现在离完全解决问题更近了。 --阿尔伯特
    【解决方案4】:

    除了标准的 Python sqlite3 模块,您还可以使用 apsw 模块,这是一个更接近 SQLite API 的第三方 SQLite 模块。它包括对加载扩展的支持,以及基本上 SQLite C/C++ API 中允许的任何内容。它还尽可能地跟上 SQLite 中的任何新变化。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-07-29
      • 1970-01-01
      • 2011-06-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-05-30
      • 2021-02-05
      相关资源
      最近更新 更多