46

I am trying out SQLAlchemy and I am using this connection string:

engine = create_engine('sqlite:///C:\\sqlitedbs\\database.db')

Does SQLAlchemy create an SQLite database if one is not already present in a directory it was supposed to fetch the database file?

user4157124
  • 2,809
  • 13
  • 27
  • 42
Gandalf
  • 1
  • 29
  • 94
  • 165

5 Answers5

47

Yes,sqlalchemy does create a database for you.I confirmed it on windows using this code

from sqlalchemy import create_engine, ForeignKey
from sqlalchemy import Column, Date, Integer, String
from sqlalchemy.ext.declarative import declarative_base

engine = create_engine('sqlite:///C:\\sqlitedbs\\school.db', echo=True)
Base = declarative_base()


class School(Base):

    __tablename__ = "woot"

    id = Column(Integer, primary_key=True)
    name = Column(String)  


    def __init__(self, name):

        self.name = name    


Base.metadata.create_all(engine)
Gandalf
  • 1
  • 29
  • 94
  • 165
  • 2
    so if the sqlite database is an existing file in that directory that you are pointing at, it will call it up instead? Ie: if it exist, connect to it, else, create it. Am I right to say that? – jake wong Mar 29 '16 at 15:17
  • 3
    Absolutely,i found that to be the case. – Gandalf May 04 '16 at 18:16
  • 11
    In case others are confused: the file is created during the `create_all(engine)` statement, not during the `create_engine(...)` statement. – dthor Aug 21 '18 at 21:45
16

As others have posted, SQLAlchemy will do this automatically. I encountered this error, however, when I didn't use enough slashes!

I used SQLALCHEMY_DATABASE_URI="sqlite:///path/to/file.db" when I should have used four slashes: SQLALCHEMY_DATABASE_URI="sqlite:////path/to/file.db"

dsummersl
  • 6,588
  • 50
  • 65
11

Linux stored SQLite3 database

database will be create in the same folder as the .py file:

engine = create_engine('sqlite:///school.db', echo=True)

will instantiate the school.db file in the same folder as the .py file.

Arthur Zennig
  • 2,058
  • 26
  • 20
8

I found (using sqlite+pysqlite) that if the directory exists, it will create it, but if the directory does not exist it throws an exception:

OperationalError: (sqlite3.OperationalError) unable to open database file

My workaround is to do this, although it feels nasty:

    if connection_string.startswith('sqlite'):
        db_file = re.sub("sqlite.*:///", "", connection_string)
        os.makedirs(os.path.dirname(db_file), exist_ok=True)
    self.engine = sqlalchemy.create_engine(connection_string)
danio
  • 8,548
  • 6
  • 47
  • 55
  • Right, in this case I would probably just print a message to the user that says, "Sorry, I can't create database FOO because directory BAR does not exist." Then, if the user wants to create it and proceed, they can. – Tom Barron Jul 02 '16 at 18:46
  • For an interactive app that's fine, but I also want this to work in a continuous integration context – danio Sep 23 '16 at 09:23
  • 1
    Once the directories exist, it will work in continuous integration. You have to decide whether the missing directory is an error and requires user intervention (in which case you generate a error message and give up) or whether a missing directory is just a warning or minor exception in which case you create (possibly a whole chain of) directories and carry on, which, as you say, is 'nasty'. Or you make it configurable... – Tom Barron Sep 26 '16 at 18:18
  • by "make it configurable", I mean provide a config setting where the user can say 'create any missing directories without bothering me about it' or 'let me know if directories are missing and I'll create them for you.' – Tom Barron Sep 26 '16 at 18:19
4

@Gandolf's answer was good.

The database is created it when you make any connection with your engine.

Here's an example of doing nothing with a database besides connecting to it, and this will create the database.

from sqlalchemy import create_engine

engine = create_engine('sqlite:///database.db')

with engine.connect() as conn:
    pass

Without the engine.connect() or some form of metadata.create_all() the database will not be created.

Zack Plauché
  • 3,307
  • 4
  • 18
  • 34