【问题标题】:Confusion about URI path to configure SQLite database关于配置 SQLite 数据库的 URI 路径的困惑
【发布时间】:2019-10-18 08:43:57
【问题描述】:

您好,我正在使用 Flask 和 Sqlite3 构建一个 Web 应用程序。我在连接数据库时遇到了一段时间的问题,当我写这个时它没有工作:

#version 1
app.config['SQLALCHEMY_DATABASE_URI'] =
'sqlite:////C:/Users/Giang/PyCharmProjects/FlaskWebBlog/FlaskWebBlog/site.db'

Python 给了我操作错误:无法打开数据库,因为我在冒号后面写了 4 个斜线。在阅读了 sqlalchemy 文档并进行了多次试验后,我发现这很有效:

#with 3 slashes, version 2
app.config['SQLALCHEMY_DATABASE_URI'] = 

 'sqlite:///C:/Users/Giang/PyCharmProjects/FlaskWebBlog/FlaskWebBlog/site.db'

或者这个有 4 个斜线但没有 C:

#version 3
app.config['SQLALCHEMY_DATABASE_URI'] = 

'sqlite:////Users/Giang/PyCharmProjects/FlaskWebBlog/FlaskWebBlog/site.db'

我很困惑,因为基于连接字符串的文档:SQLite 数据库的文件规范被视为 URL 的“数据库”部分。请注意,SQLAlchemy url 的格式是:

driver://user:pass@host/database

这意味着要使用的实际文件名以第三个斜杠右侧的字符开头。所以连接到相对文件路径看起来像:

# relative path
e = create_engine('sqlite:///path/to/database.db')

绝对路径,以斜杠开头表示,需要四个斜杠:

# absolute path
e = create_engine('sqlite:////path/to/database.db')

根据这个,如果我使用绝对路径,我需要 4 个斜杠,但是当我使用版本 1 时,python 给了我错误。当我在版本 2 中使用 3 个斜线作为绝对路径时,它起作用了。

所以我真的很困惑。谁能为我解释为什么?我真的很感激。谢谢

【问题讨论】:

标签: python sqlite uri relative-path absolute-path


【解决方案1】:

如果您将 SQLite3 指向当前工作目录以外的位置,我建议您执行以下操作以避免找不到数据库的问题:

import os
study_and_database_name = "something_unique"
rdb_string_url = "sqlite:///" + os.path.join(dir, (study_and_database_name + ".db"))
rdb_raw_bytes_url = r'{}'.format(rdb_string_url)

恢复存储在 RDB storage 中的 Optuna study 时,它对我有用:

storage_instance = optuna.storages.RDBStorage(url=rdb_raw_bytes_url)
study_instance = optuna.create_study(
    study_name=study_and_database_name,
    storage=storage_instance,
    load_if_exists=True,
)

【讨论】:

    【解决方案2】:

    您对database 组件被读取为第三个斜线后的所有字符是正确的。这是解析的:版本 1 URL

    >>> import sqlalchemy.engine.url as url
    >>> url.make_url('sqlite:////C:/Users/Giang/PyCharmProjects/FlaskWebBlog/FlaskWebBlog/site.db')
    sqlite:////C:/Users/Giang/PyCharmProjects/FlaskWebBlog/FlaskWebBlog/site.db
    
    >>> vars(_)
    {'drivername': 'sqlite',
     'username': None,
     'password_original': None,
     'host': None,
     'port': None,
     'database': '/C:/Users/Giang/PyCharmProjects/FlaskWebBlog/FlaskWebBlog/site.db',
     'query': {}}
    

    在 Windows 中,路径 gets normalized 开头的斜杠指向“当前工作目录的根驱动器”。使用pywin32,我们可以调用GetFullPathName查看路径的规范化版本:

    >>> import os
    >>> import win32file
    
    >>> os.getcwd()
    'C:\\Users\\they4kman'
    
    >>> win32file.GetFullPathName('/C:/test')
    'C:\\C:\\test'
    
    >>> win32file.GetFullPathName('/test')
    'C:\\test'
    
    >>> win32file.GetFullPathName('C:/test')
    'C:\\test'
    

    版本 1 不起作用的原因是,同时指定前导斜杠和驱动器号会被 Windows 规范化为无效路径。 (更具体地说,路径无效,因为在 Windows 路径中不允许使用冒号,除非在开头作为驱动器说明符。)

    为了显示前导斜杠如何根据环境进行不同的规范化,让我们将当前工作目录更改为另一个驱动器上的一个并检查规范化路径:

    >>> os.chdir('D:/')
    >>> os.getcwd()
    'D:\\'
    
    >>> win32file.GetFullPathName('/test')
    'D:\\test'
    
    >>> win32file.GetFullPathName('C:/test')
    'C:\\test'
    

    【讨论】:

    • 谢谢。这么详细的回答。我现在明白为什么我的第一个版本是错误的,但我仍然很困惑为什么我的版本 2 有效,因为如果“C:/”完整路径是“C:\\”,那仍然意味着我前面有三个斜杠,它是绝对路径。但是根据文档,绝对路径前面应该有4个斜杠,那么你是否知道为什么它仍然是正确的呢?非常感谢
    • 前两个斜线标志着方案的结束(例如sqlite3://https://)。之后是用于连接数据库的用户名、密码和主机——然而,sqlite3 不支持身份验证,并且存在于文件系统中,因此没有可连接的主机。这意味着user:pass@host 部分始终为空白,但仍需要斜杠将其与数据库名称隔开——这只是数据库文件的路径。文档实际上说“对于绝对文件路径,三个斜杠后跟绝对路径”docs.sqlalchemy.org/en/13/core/engines.html#sqlite
    猜你喜欢
    • 2012-03-06
    • 1970-01-01
    • 1970-01-01
    • 2015-02-03
    • 1970-01-01
    • 2012-10-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多