【问题标题】:How to make sqlite3.connect() fail if the db file does not exist?如果 db 文件不存在,如何使 sqlite3.connect() 失败?
【发布时间】:2020-01-09 16:51:06
【问题描述】:

sqlite3.connect() 如果 db 文件不存在,将创建它。我希望它失败。有办法吗?

【问题讨论】:

  • 可以先使用os.path.exists()查看文件
  • 我可以。但我希望有一个选项可以让它变得更容易。

标签: python python-3.x sqlite


【解决方案1】:

第一种方法是用os.path.isfile检查文件路径:

import sqlite3
import os

my_path = 'database.db' # or 'absolute_path/to/the/file'
if os.path.isfile(my_path):
    sqlite3.connect(my_path)

否则,您可以使用uri=True 参数指定打开mode 并在文件丢失的情况下引发错误。 如果没有mode,文件将在不存在时创建,因此您可以使用例如rwro 来避免新文件:

  • 以读写模式打开:

    sqlite3.connect('file:database.db?mode=rw', uri=True)
    
  • 以只读模式打开:

    sqlite3.connect('file:database.db?mode=ro', uri=True)
    

如果文件不存在,这将引发以下错误:

sqlite3.OperationalError: 无法打开数据库文件

您可以在文档的这些章节中找到有关这些模式的更多信息:

https://www.sqlite.org/uri.html

https://www.sqlite.org/c3ref/open.html#urifilenamesinsqlite3open


为了能够打开带有特殊字符(URI 专用)的文件,另一种方法是使用以下方法:

import pathlib

my_db = pathlib.Path('path/to/data?ba=se.db').as_uri()
sqlite3.connect('{}?mode=rw'.format(my_db), uri=True)

# or sqlite3.connect(f'{my_db}?mode=rw', uri=True)  with f-string

【讨论】:

  • 这有点麻烦。如果数据库文件名中包含?=,应该先转义?从这个意义上说,也许检查os.path.exists() 更好?
  • 在文件名中添加 ?= 证明了真正的风险热情 :) 最终这可以通过 python 3.7 docs.python.org/3/library/sqlite3.html#sqlite3.connect 中添加的功能来处理:在 3.7 版中更改: 数据库现在也可以是一个类似路径的对象,而不仅仅是一个字符串。
  • 不是我想在文件名中使用?=。但是如果我使用uri 选项,我需要编写代码来防止这种情况。不确定类似路径的对象能否解决问题。如果使用它,我看不到指定只读的方法。
  • 确实,我在想,如果路径不存在,创建类似路径的对象可能会失败,但我也找不到方法。不确定你能找到除os.path.exists() 或 uri 之外的其他解决方案
  • @user1424739 至少答案为您的问题提供了解决方案。您始终可以执行先前的文件/路径验证以排除包含?= 的文件。这将需要一个非常简单的正则表达式检查,排除文件名上的某些字符和/或后缀。有安全意识是好的,但我仍然想知道这种程度的关注是否是必要的,因为如果某些流氓进程制作并创建了一个可以欺骗 URI 格式的文件名,那么很可能该进程已经损害了系统,而不仅仅是欺骗你的应用程序打开一个新创建的数据库文件。
猜你喜欢
  • 2016-01-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-07-29
  • 2016-02-05
相关资源
最近更新 更多