Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Confusion about URI path to configure SQLite database

Hi I am building a web application using Flask and Sqlite3. I had issues with connecting the database for a while and it did not work when I wrote this:

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

Python gave me operational error: can not open database because I wrote with 4 slashes after the colon. After reading sqlalchemy documentation and doing so many trials, I found out this worked:

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

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

or this with 4 slashes but no C:

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

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

I am confused because based on the documentation of connecting strings: The file specification for the SQLite database is taken as the “database” portion of the URL. Note that the format of a SQLAlchemy url is:

driver://user:pass@host/database

This means that the actual filename to be used starts with the characters to the right of the third slash. So connecting to a relative filepath looks like:

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

An absolute path, which is denoted by starting with a slash, means you need four slashes:

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

SO according to this, if I use absolute path, I need 4 slashes, but when I did that with version 1, python gave me errors. And when I used 3 slashes for absolute path in version 2, it worked.

So I am really confused. Can anyone explain for me why ? I would really appreciate it. Thank you

like image 322
bubble rain Avatar asked Jun 02 '19 15:06

bubble rain


People also ask

What is the path component of a SQLite Uri?

The path component of the URI specifies the disk file that is the SQLite database to be opened. If the path component is omitted, then the database is stored in a temporary file that will be automatically deleted when the database connection closes. If the authority section is present, then the path is always an absolute pathname.

What is the connection URI for the SQL adapter?

The following is a sample connection URI for the SQL adapter. In the preceding example, “sql_server” is the name of the computer on which SQL Server is installed whereas “sql_server_instance” is the name of the database instance to connect to. Because no database name is specified, the adapter will connect to the default database.

How do I specify connection parameters for a SQL Server Uri?

If you specify the URI directly in the Configure a URI field and the connection parameters contain special characters, you must specify the connection parameters using proper escape characters. For example, if the connection URI has a parameter with name sql server, you must specify it as sql%20server.

What is an example of a connection Uri?

The following is an example of a connection URI where the SQL Server database is installed on the same computer as the SQL adapter. In this example, the adapter connects to the database “my_database” for the “sql_server_instance” database instance on the local computer.


2 Answers

If you are pointing SQLite3 to a location other than the current working directory, I recommend the following to avoid problems where it cannot find the database:

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)

It worked for me when resuming an Optuna study stored in RDB storage:

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,
)
like image 111
brethvoice Avatar answered Sep 23 '22 18:09

brethvoice


You are correct about the database component being read as all the characters after the third slash. Here's the parsed: version 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': {}}

In Windows, a slash at the beginning of a path gets normalized to "the root drive of the current working directory". Using pywin32, we can call GetFullPathName to view the normalized version of a path:

>>> 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'

The reason version 1 doesn't work is because specifying both a leading slash and a drive letter will get normalized by Windows into an invalid path. (More specifically, the path is invalid because colons are not allowed in Windows paths, except at the beginning as a drive specifier.)

To show how a leading slash is normalized differently depending on the environment, let's change the current working directory to one on another drive and check out the normalized path:

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

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

>>> win32file.GetFullPathName('C:/test')
'C:\\test'
like image 41
theY4Kman Avatar answered Sep 19 '22 18:09

theY4Kman