boB Stepp wrote:

> While reading about SQL, SQLite and the Python module sqlite3, it
> appears that I could (1) have a program check for the existence of the
> program's database, and if not found, create it, make the tables,
> etc.; or, 

I'm only a casual user of sqlite, and therefore I prefer to have the table 
definitions in the script. It's as easy writing

create table if not exists foo ...

instead of

create table foo ...

This also allows you to easily add tables later on.


> (2) create the database separately and include it with the
> program.  What are the pros and cons of each approach?  (1) to me
> looks only helpful if I wish to write a program that might want to
> allow the user to have multiple databases.  

Even if the user needs only a single db you should make that configurable to 
allow for testing.

> But this sounds like a lot
> of extra coding and checking to make it work well.  

I don't think so. You need the database schema, and once you have that it 
doesn't matter if you build one or 1000 databases from it.

> But if I only wish
> to have a single database, then (2) sounds like the approach to use.
> I would create the database, populate it with the needed empty tables
> with the desired fields, making it ready to use by the program's user.
> 
> Not having any experience in the database arena, I'm not even sure I
> know how to properly think about this.

Here's a little demo script to get you going. There's only a single table, 
but the principle works with any number of tables and indices. 

$ ls
sqlitedemo.py
$ cat sqlitedemo.py   
#!/usr/bin/env python3

import sqlite3
from itertools import chain
from contextlib import closing


def ensure_db(filename):
    db = sqlite3.connect(filename)
    with closing(db.cursor()) as cursor:
        cursor.execute(
            "create table if not exists addresses (name, email);"
        )
    return db


def insert_action(args, parser):
    with ensure_db(args.database) as db:
        with closing(db.cursor()) as cursor:
            cursor.execute(
                "insert into addresses values (?, ?);",
                (args.name, args.email)
            )


def fix_none(row):
    return [
        "NULL"if value is None else value
        for value in row
    ]


def show_action(args, parser):
    with ensure_db(args.database) as db:
        with closing(db.cursor()) as cursor:
            cursor.execute("select * from addresses order by name")
            fieldnames = [
                column_desc[0]
                for column_desc in cursor.description
            ]
            template = " | ".join(("{:20}",)*len(fieldnames))
            separator = ["-" * 20] * len(fieldnames)
            for row in chain([fieldnames, separator], cursor):
                print(template.format(*fix_none(row)))


def main():
    import argparse

    parser = argparse.ArgumentParser()
    parser.add_argument("-d", "--database", default="default.sqlite")
    sub = parser.add_subparsers()

    insert = sub.add_parser("insert")
    insert.add_argument("name")
    insert.add_argument("email")
    insert.set_defaults(func=insert_action)

    show = sub.add_parser("show")
    show.set_defaults(func=show_action)

    args = parser.parse_args()

    args.func(args, parser)


if __name__ == "__main__":
    main()

$ ./sqlitedemo.py show
name                 | email               
-------------------- | --------------------
$ ls
default.sqlite  sqlitedemo.py
$ ./sqlitedemo.py insert jim j...@example.com
$ ./sqlitedemo.py insert sue s...@elsewhere.org
$ ./sqlitedemo.py show
name                 | email               
-------------------- | --------------------
jim                  | j...@example.com     
sue                  | s...@elsewhere.org   
$ ./sqlitedemo.py -d otherdb insert peter peter@uknowwhere
$ ls
default.sqlite  otherdb  sqlitedemo.py
$ ./sqlitedemo.py -d otherdb show
name                 | email               
-------------------- | --------------------
peter                | peter@uknowwhere    

PS: I don't know if it makes sense to close the cursors, I just thought it 
looked clean when I added it to ensure_db() and ended up adding it 
everywhere.

_______________________________________________
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor

Reply via email to