Pythonで蔵書管理プログラムを作る【CUI】

719, 2023-08-10

目次

Pythonで蔵書管理プログラムを作る【CUI】

毎日暑いですが皆さんいかがお過ごしでしょうか。
最近は暑さもマシになってきたかな? という感じがやっと出てきましたが、それでもまだ暑いです。
感覚がマヒしてるんですね、きっと。

今回は暑いのでPythonで蔵書管理プログラムを作りました。
そのソースコードを掲載し、解説します。

動かしているところ

プログラムを動かすと以下のようなに感じなります。

蔵書管理: 見る(0) 追加(1) 削除(2) > 0
蔵書管理: 見る(0) 追加(1) 削除(2) > 1
蔵書を追加します。
タイトル > ababa
説明 > hige
蔵書管理: 見る(0) 追加(1) 削除(2) > 0
ababa
hige
----------------------------------------
蔵書管理: 見る(0) 追加(1) 削除(2) > 1
蔵書を追加します。
タイトル > ugogo
説明 > huge
蔵書管理: 見る(0) 追加(1) 削除(2) > 0
ababa
hige
----------------------------------------
ugogo
huge
----------------------------------------
蔵書管理: 見る(0) 追加(1) 削除(2) > 2
蔵書を削除します。
タイトル > ugogo
蔵書管理: 見る(0) 追加(1) 削除(2) > 0
ababa
hige
----------------------------------------
蔵書管理: 見る(0) 追加(1) 削除(2) >

番号で「見る、追加、削除」を選択して蔵書を見たり追加したりします。
コンソールアプリですので端末上で動きます。
データーベースはJSONで作成し管理します。お手軽ですね。

ソースコード全文

以下がソースコード全文です。

import json
import os


DB_NAME = 'data.json'


def touch_db():
    if not os.path.exists(DB_NAME):
        with open(DB_NAME, 'w', encoding='utf-8') as fout:
            fout.write('{ "books": [] }')


def load_db():
    touch_db()
    with open(DB_NAME, 'r', encoding='utf-8') as fin:
        return json.load(fin)


def save_db(d: dict):
    with open(DB_NAME, 'w', encoding='utf-8') as fout:
        fout.write(json.dumps(d))


def see():
    db = load_db()
    books = db['books']

    for book in books:
        print(book['title'])
        print(book['description'])
        print('-' * 40)


def add():
    print('蔵書を追加します。')
    title = input('タイトル > ')
    description = input('説明 > ')
    book = {
        'title': title,
        'description': description,
    }

    db = load_db()
    db['books'].append(book)
    save_db(db)


def remove():
    print('蔵書を削除します。')
    title = input('タイトル > ')

    db = load_db()
    books = db['books']

    dst = []
    for book in books:
        if title == book['title']:
            pass
        else:
            dst.append(book)

    db['books'] = dst
    save_db(db)


def main():
    while True:
        try:
            cmd = input('蔵書管理: 見る(0) 追加(1) 削除(2) > ')
        except KeyboardInterrupt:
            break

        cmd = int(cmd)
        if cmd == 0:
            see()
        elif cmd == 1:
            add()
        elif cmd == 2:
            remove()


main()

main関数

プログラムはmain関数から始まります。

def main():
    while True:
        try:
            cmd = input('蔵書管理: 見る(0) 追加(1) 削除(2) > ')
        except KeyboardInterrupt:
            break

        cmd = int(cmd)
        if cmd == 0:
            see()
        elif cmd == 1:
            add()
        elif cmd == 2:
            remove()


main()

この関数では無限ループを作り、コマンドを処理します。
コマンドの入力はinput()で行います。
このinput関数は標準入力から一行文字列として読み取る関数です。

cmdに読み取った文字列を保存したらそれをint(cmd)で整数に変換します。
そしてcmdの値に応じてsee(), add(), remove()関数を呼び出します。

see関数

see関数は蔵書情報を閲覧する関数です。

def see():
    db = load_db()
    books = db['books']

    for book in books:
        print(book['title'])
        print(book['description'])
        print('-' * 40)

この関数ではまずload_db()でデータを読み込みます。
そしてデータの辞書からbooksを取り出します。これはリストです。
そしてfor文でbooksを回し、titledescriptionを出力します。
print('-' * 40)とやるとハイフンを40個出力します。

load_db関数

def load_db():
    touch_db()
    with open(DB_NAME, 'r', encoding='utf-8') as fin:
        return json.load(fin)

この関数はデータベースを読み込みます。
データベースはDB_NAMEの名前のJSONファイルです。

DB_NAME = 'data.json'

touch_db()でファイルが無い場合は作成しています。
ファイルをopen()で開いたらファイルオブジェクトをjson.load()でパースして辞書に変換します。

open()は第1引数がファイル名、第2引数がオープンモード、encoding引数が文字コードの指定です。
オープンモードはrだとテキストファイルの読み込み、wだとテキストファイルの書き込みになります。
wはファイルを空にしますので、既存のファイルが存在する場合は注意が必要です。

またencodingutf-8にします。
Linuxではデフォルトでutf-8になるんですが、Windowsではcp932になります。
ですのでUTF-8でファイルを扱いたい場合はこの指定が必要です。

touch_db関数

def touch_db():
    if not os.path.exists(DB_NAME):
        with open(DB_NAME, 'w', encoding='utf-8') as fout:
            fout.write('{ "books": [] }')

この関数はDB_NAMEのファイルが存在しない場合に、空のデータベースを作成します。
os.path.exists()はファイルが存在するときにTrueを返します。
ファイルが存在しなかったらファイルを書き込みモードで開き、ファイル内容を書き込みます。
ファイル内容は

{ "books": [] }

になっており、これはJSONのフォーマットを満たすものです。
空のbooksを入れていますが、こうしておくと面倒な処理が減ります。

add関数

def add():
    print('蔵書を追加します。')
    title = input('タイトル > ')
    description = input('説明 > ')
    book = {
        'title': title,
        'description': description,
    }

    db = load_db()
    db['books'].append(book)
    save_db(db)

この関数は蔵書データをデータベースに保存します。
input()で蔵書のタイトルと説明を読み取ります。
それをbookという辞書にして読み込んだデータベースのbooksに追加します。
追加したらsave_db()で辞書をファイルに保存します。

save_db関数

def save_db(d: dict):
    with open(DB_NAME, 'w', encoding='utf-8') as fout:
        fout.write(json.dumps(d))

この関数は引数の辞書をデータベースとして保存します。
open()wモードはファイルを空にして書き込みしますが、dには全データが入っている前提の設計なので問題ないです。
実用的なアプリではこういった設計はあまり見られませんが、このような簡易的なアプリではよくあります。

辞書はjson.dumps()で文字列にできます。
それを開いたファイルにfout.write()で保存します。

ちなみにfinfile inputfoutfile outputの略です。

remove関数

def remove():
    print('蔵書を削除します。')
    title = input('タイトル > ')

    db = load_db()
    books = db['books']

    dst = []
    for book in books:
        if title == book['title']:
            pass
        else:
            dst.append(book)

    db['books'] = dst
    save_db(db)

remove関数は蔵書データを削除します。
削除対処の蔵書のタイトルを入植してもらい、それをbooksから検索し、ヒットしたらdstに保存しないようにします。
dstにはヒットした蔵書以外の蔵書データが保存されますので、あとはこれをbooksに代入し、その辞書をsave_db()で保存します。

おわりに

今回はPythonで蔵書管理プログラムを作りました。
なにか参考になれば幸いです。

(^ _ ^)

蔵書を管理するぞ!

(・ v ・)

どうぞ



この記事のアンケートを送信する