Pythonで蔵書管理プログラムを作る【CUI】
目次
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
を回し、title
とdescription
を出力します。
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
はファイルを空にしますので、既存のファイルが存在する場合は注意が必要です。
またencoding
はutf-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()
で保存します。
ちなみにfin
はfile input
、fout
はfile 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 ・) | どうぞ |