关于配置 SQLite 数据库的 URI 路径的困惑

bub*_*ain 12 python sqlite uri relative-path absolute-path

嗨,我正在使用 Flask 和 Sqlite3 构建一个 Web 应用程序。有一段时间我在连接数据库时遇到问题,但在我写这个时它不起作用:

#version 1
app.config['SQLALCHEMY_DATABASE_URI'] =
'sqlite:////C:/Users/Giang/PyCharmProjects/FlaskWebBlog/FlaskWebBlog/site.db'
Run Code Online (Sandbox Code Playgroud)

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

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

 'sqlite:///C:/Users/Giang/PyCharmProjects/FlaskWebBlog/FlaskWebBlog/site.db'
Run Code Online (Sandbox Code Playgroud)

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

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

'sqlite:////Users/Giang/PyCharmProjects/FlaskWebBlog/FlaskWebBlog/site.db'
Run Code Online (Sandbox Code Playgroud)

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

driver://user:pass@host/database
Run Code Online (Sandbox Code Playgroud)

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

# relative path
e = create_engine('sqlite:///path/to/database.db')
Run Code Online (Sandbox Code Playgroud)

以斜杠开头的绝对路径意味着您需要四个斜杠:

# absolute path
e = create_engine('sqlite:////path/to/database.db')
Run Code Online (Sandbox Code Playgroud)

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

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

the*_*man 5

您将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': {}}
Run Code Online (Sandbox Code Playgroud)

在 Windows 中,路径开头的斜杠被规范化为“当前工作目录的根驱动器”。使用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'
Run Code Online (Sandbox Code Playgroud)

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

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

>>> os.chdir('D:/')
>>> os.getcwd()
'D:\\'

>>> win32file.GetFullPathName('/test')
'D:\\test'

>>> win32file.GetFullPathName('C:/test')
'C:\\test'
Run Code Online (Sandbox Code Playgroud)

  • 前两个斜杠标志着方案的结束(例如`sqlite3://` 或`https://`)。之后是用户名、密码和主机来连接到数据库——但是,sqlite3 不支持身份验证,并且存在于文件系统中,因此没有主机可以连接。这意味着 `user:pass@host` 部分总是空白,但仍然需要斜线将它与数据库名称分开——这只是数据库文件的路径。文档实际上说“对于绝对文件路径,三个斜杠后跟绝对路径” https://docs.sqlalchemy.org/en/13/core/engines.html#sqlite (6认同)