Einfache Buchverwaltung mit Barcode-Scanner und Python

Einfache Buchverwaltung mit Barcode-Scanner und Python

Sehr geehrte Leserinnen und Leser,

Aufgrund einer Anfrage habe ich neulich ein einfaches Programm entwickelt, welches zur Verwaltung einer Bücher-Ausleihe dient. Dieses praktische Beispiel möchte ich hier als Inspiration für Ihre eigenen Projekte veröffentlichen. Sie dürfen dieses Skript gerne kopieren und für Ihre eigenen Projekte anpassen. Im Folgenden möchte ich ein bisschen darüber Berichten und Ihnen die Funktionsweise erläutern.

Ziel und Zweck der Anwendung

Ziel des Projektes war eine Anwendung für eine Buch-Ausleihe. Die Ausleihe funktioniert auf freiwilliger Basis. Bücher, die man nicht mehr ließt kann man abgeben und sich dafür neue Bücher ausleihen. Da diese Ausleihe relativ schnell beliebt wurde, war das Regal relativ schnell mit Büchern gefüllt. Mit der Zeit haben Bücher, die sich keiner mehr ausleiht Platz im Regal weggenommen.

Die Anwendung war dafür bestimmt, Bücher ausfindig zu machen, die nicht mehr gelesen werden, um diese endgültig aus zu sortieren. Aussortierte Bücher sollen an eine weitere Organisation gespendet werden.

Funktionsweise der Anwendung

Mit einem angeschlossenen Funk-Barcode-Scanner und einem angeschlossenen Bluetooth-Kopfhörer (für laute Umgebungen) an einem Laptop wird jedes Buch eingescannt. Hierzu wird die Anwendung gestartet. Nach dem Start wird automatisch die Datenbank-Datei des letzten Scan-Events in den Arbeitsspeicher des Computers geladen. Der Maus-Cursor muss nun auf die Kommandozeile gesetzt werden. Danach kann das Scannen beginnen.

Jedes Buch wird nun anhand seiner ISBN-Nummer eingescannt. Nach der Erfassung wird automatisch eine Audio-Datei abgespielt, die über die Bluetooth-Kopfhörer mitteilen, ob das erfasste Buch behalten oder aussortiert werden soll.

Tipp: Falls ein Buch keinen Barcode für die ISBN-Nummer hat, kann auch eine Rolle mit Inventur-Label (Barcodes mit aufsteigenden Nummern) verwendet werden, um diesen Büchern eine eindeutige ID zuzuweisen.

Nach dem Einscannen aller Bücher wird durch Eingabe von “exit” das Programm beendet. Es ist wichtig, dass das Programm auf diese Weise beendet wird, damit die Datenbank aktualisiert und gespeichert wird.

Funktionsweise von Barcode-Scannern

Barcode-Scanner sind in Grunde genommen von der Funktionsweise sehr einfach. Für das Betriebssystem ist ein Barcode-Scanner ein gewöhnliches USB-Eingabegerät, wie Tastaturen auch. Wenn ein Barcode eingescannt wird, wird der Code wie eine Tastatureingabe eingegeben und danach mit einer Tabulator-Taste oder Enter-Taste automatisch ergänzt.

Diese einfache Funktionsweise von Barcode-Scannern lässt sich mit einem Kommandozeilen-Programm oder einer Benutzeroberfläche mit einem Textfeld abfangen.

Verwendete Hardware und Software

Die Anwendung selbst ist in Python 3 programmiert worden und somit Plattform übergreifend auf Linux, Windows und Mac lauffähig. Barcode-Scanner sind wie bereits beschrieben einfache USB-Eingabegeräte, die auch Plattform übergreifend einsetzbar sind. Falls Sie sich trotzdem für die genaue Hardware interessieren, habe ich Ihnen hier folgende Liste mit Amazon-Links zusammengestellt:

Was die Software angeht, brauchen Sie nur eine Python-Umgebung einzurichten. (https://www.python.org/)

Python-Skript

Zunächst möchte ich Ihnen das komplette Python-Skript zur Übersicht zeigen, bevor ich Ihnen die einzelnen Stücke davon erläutere:

# Autor: Christopher Mahn
from playsound import playsound

file = open("database.csv", "r")
database = file.readlines()
file.close()

for index, item in enumerate(database):
    database[index] = item.split(",")
    database[index][1] = int(database[index][1])

scanned_list = []

print("to exit: type 'exit'")
while(True):
    scanned_item = input()
    if(scanned_item == "exit"):
        break
    scanned_list.append(scanned_item)
    audio = False
    for i in database:
        if(scanned_item == i[0]):
            if(i[1] > 12):
                playsound(f"dont_keep_item.mp3")
                audio = True
                break
    if audio is False:
        playsound(f"keep_item.mp3")

# sorting
scanned_list.sort()

# removing duplicates from list
scanned_list = list(dict.fromkeys(scanned_list))

for i in range(len(scanned_list)):
    duration = 1
    for j in database:
        if(scanned_list[i] == j[0]):
            duration = j[1]+1
    scanned_list[i] = f"{scanned_list[i]}, {duration}"


file = open("database.csv", "w")
for i in scanned_list:
    file.write(f"{i}\n")
file.close()Code-Sprache: Python (python)

Erläuterung des Python-Codes

Die Erläuterung dient zum Verständnis, wie dieses Skript funktioniert und wo die Grenzen liegen. Beachten Sie dabei auch die unten stehenden Anmerkungen zur Nutzung, bevor ein eventueller Schaden entsteht.

Import von Bibliotheken

from playsound import playsound
Code-Sprache: Python (python)

Am Anfang des Programms werden zunächst sämtliche Bibliotheken, die von der Anwendung verwendet werden importiert. In diesem Fall wird nur eine Bibliothek für die Wiedergabe von Audio-Dateien benötigt.

Einlesen der Datenbank-Datei

file = open("database.csv", "r")
database = file.readlines()
file.close()
Code-Sprache: Python (python)

Wie sich bereits aus der Überschrift deuten lässt, wird nun die komplette Datenbank-Datei zeilenweise eingelesen und in einer Listen-Variable gespeichert.

Umwandeln der Datenbank-Informationen

for index, item in enumerate(database):
    database[index] = item.split(",")
    database[index][1] = int(database[index][1])
Code-Sprache: Python (python)

Die Datenbank ist sehr einfach aufgebaut. Jeder Barcode wird in einer Zeile gespeichert. Um Nachverfolgen zu können, wie oft ein Buch schon abgescannt wurde, wird hinter dem jeweiligen Codes mit einem Komma getrennt numerisch angehängt, wie oft dieser Artikel schon “gesehen” wurde. Um diese Anzahl der Sichtungen bei der Evaluation der Artikel berücksichtigen zu können, wird jede Zeile am Komma getrennt und das jeweilige zweite Element in einen Integer zurück verwandelt. So wird aus einer Liste mit Strings “9843720395720, 7” eine Liste mit Listen [“9843720395720”, 7].

Anlegen einer Liste gescannter Artikel

scanned_list = []
Code-Sprache: Python (python)

Um beim Scannen der Artikel möglichst zügig arbeiten zu können, werden alle Scan-Vorgänge in einer Liste gespeichert und am Ende in die Datenbank eingepflegt.

Scan-Input und Feedback zur Aussortierung

print("to exit: type 'exit'")
while(True):
    scanned_item = input()
    if(scanned_item == "exit"):
        break
    scanned_list.append(scanned_item)
    audio = False
    for i in database:
        if(scanned_item == i[0]):
            if(i[1] > 12):
                playsound(f"dont_keep_item.mp3")
                audio = True
                break
    if audio is False:
        playsound(f"keep_item.mp3")
Code-Sprache: Python (python)

Zeile 1 bis 5 initialisieren eine Endlos-Schleife, die das Scannen von vielen Artikeln hintereinander ermöglichen. Hierbei wartet das Programm in Zeile 3 auf die Eingabe des Barcode-Scanners. Wenn die Eingabe von “exit” empfangen wird, wird die Endlosschleife unterbrochen und keine weiteren Eingaben sind möglich.

In Zeile 6 wird der gescannte Artikel in der zuvor angelegten Liste zwischengespeichert, um am Ende des Programms in der Datenbank eingetragen zu werden.

Die Zeilen 7 bis 15 überprüfen, ob der jeweilige Artikel zulange gelagert wurde oder nicht. Dies wird dem Anwender mit dem Abspielen einer bestimmten Audio-Datei mitgeteilt.

Sortieren der gescannten Artikel

scanned_list.sort()
Code-Sprache: Python (python)

Nachdem alle Artikel gescannt wurden, werden für eine bessere Übersicht die gescannten Artikel sortiert.

Entfernen von Duplikaten

scanned_list = list(dict.fromkeys(scanned_list))
Code-Sprache: PHP (php)

Eigentlich brauche ich hier nicht viel erklären. Hier werden die gescannten Duplikate entfernt, damit keine doppelten Einträge in der Datenbank entstehen.

Ermittlung der neuen Lagerzeit und Formatierung

for i in range(len(scanned_list)):
    duration = 1
    for j in database:
        if(scanned_list[i] == j[0]):
            duration = j[1]+1
    scanned_list[i] = f"{scanned_list[i]}, {duration}"
Code-Sprache: JavaScript (javascript)

In Zeile 1 bis 5 wird mit der Datenbank verglichen, ob der jeweilige Artikel letztes Mal auch eingescannt wurde. Wenn dies zutrifft, wird der jeweilige Eintrag inkrementiert. Andernfalls wird eine Eins eingetragen, wenn der Artikel zum ersten Mal gesichtet wurde.

In Zeile 6 wird der entsprechende Eintrag für die neue Datenbank in der Liste der gescannten Artikel ersetzt.

Achtung: Dieser Teil des Programms läuft mit einem Laufzeitverhalten von O(n²).

Aktualisieren der Datenbank

file = open("database.csv", "w")
for i in scanned_list:
    file.write(f"{i}\n")
file.close()
Code-Sprache: JavaScript (javascript)

In diesem Code-Ausschnitt wird die Liste der gescannten Artikel zur neuen Datenbank. Hierzu wird die Datei ersetzt und jede Zeile nacheinander in die Datei geschrieben. Hinterher wird die Datei geschlossen.

Anmerkungen zur Nutzung

Dieses Programm macht so gut wie keine Überprüfungen auf Richtigkeit. Sofern Sie also Datenbanken einlesen, die nicht kompatibel sind, kann es beispielsweise zu Abstürzen führen. Verwenden Sie dieses Programm nur, wenn Sie es vollständig und mit allen Konsequenzen verstehen.

Wenn Sie das Programm mitten im Scan-Betrieb beenden, kommt es zu Datenverlust. Machen Sie nach jedem Programm-Lauf ein Backup der Datenbank, um Datenverlust vorzubeugen.

Sie können Barcodes mehrfach scannen. Dieses wird durch das Programm richtig verarbeitet. Schauen Sie sich trotzdem die Funktionsweise hierzu an, bevor Sie sich darauf verlassen.

Download

Mit folgendem Link kommen Sie auf einen Ordner mit sämtlichen Dateien:
https://gitlab.com/cmahn/python-book-management

Hinweis

Das Beitragsbild stammt von matthew Feeney on Unsplash.

Tags: , , , , , , , , , , , ,

3 Antworten

  1. Elke sagt:

    Wow, da hast Du Dir echt viel Mühe gemacht. Das ist ja wie eine Ausarbeitung! 👍

  2. SeppTW sagt:

    Hi, vergisst du hier nicht die alten Datensätze in der Datenbank?

    • Ja, das ist richtig.
      Die Datensätze, die ich im jeweiligen Durchlauf nicht erfasse, werden gelöscht.

      Das ist eine einfache Möglichkeit einerseits ausgeliehene (und beliebte) Bücher von der “Aussortierungs-Frist” zurückzusetzen (da diese bei der Rückgabe wieder mit Standardwert “0” angelegt werden) und anderseits die Menge der erhobenen Metadaten zu minimieren (höherer Datenschutz und Datenminimierung).

      Man könnte eine Sicherung der “Datenbank” nach jedem Durchlauf durchführen. Dann hätte man die Möglichkeit alle Dateien über einen längeren Zeitraum umfangreich auszuwerten.

Kommentar verfassen