Library Management System in Python
Intermediate · Useful tools · about 75 minutes to build · 150 lines
Keep track of books and members, issue a book with a due date and work out the fine when it comes back late.
The program
Press Run and answer its questions in the box that appears under the code.
Open it in the full editor to save it, share it and keep building.
Sample run
What the program printed, and what was typed (in yellow).
Library management system 1) Books 2) Members 3) Add book 4) Add member 5) Issue 6) Return 7) Quit Choose 1-7: 1 ID Title Author Status B101 Wings of Fire A. P. J. Abdul Kalam Available B102 Malgudi Days R. K. Narayan Available B103 The Jungle Book Rudyard Kipling Available B104 Pride and Prejudice Jane Austen Available 1) Books 2) Members 3) Add book 4) Add member 5) Issue 6) Return 7) Quit Choose 1-7: 5 Book ID: b102 Member ID: m1 Issue date (DD-MM-YYYY, Enter for today): 01-10-2026 Malgudi Days issued to Ananya Gupta. Due back on 15-10-2026. 1) Books 2) Members 3) Add book 4) Add member 5) Issue 6) Return 7) Quit Choose 1-7: 5 Book ID: B102 Malgudi Days is out until 15-10-2026. 1) Books 2) Members 3) Add book 4) Add member 5) Issue 6) Return 7) Quit Choose 1-7: 4 Member name: Sara Thomas Added member M3. 1) Books 2) Members 3) Add book 4) Add member 5) Issue 6) Return 7) Quit Choose 1-7: 5 Book ID: B104 Member ID: M3 Issue date (DD-MM-YYYY, Enter for today): 3rd Oct Please type the date like 05-10-2026. Issue date (DD-MM-YYYY, Enter for today): 03-10-2026 Pride and Prejudice issued to Sara Thomas. Due back on 17-10-2026. 1) Books 2) Members 3) Add book 4) Add member 5) Issue 6) Return 7) Quit Choose 1-7: 6 Book ID: B102 Return date (DD-MM-YYYY, Enter for today): 19-10-2026 Returned 4 day(s) late. Fine: 20 1) Books 2) Members 3) Add book 4) Add member 5) Issue 6) Return 7) Quit Choose 1-7: 1 ID Title Author Status B101 Wings of Fire A. P. J. Abdul Kalam Available B102 Malgudi Days R. K. Narayan Available B103 The Jungle Book Rudyard Kipling Available B104 Pride and Prejudice Jane Austen Out to M3, due 17-10-2026 1) Books 2) Members 3) Add book 4) Add member 5) Issue 6) Return 7) Quit Choose 1-7: 7 Goodbye.
How it is built
1. The Book class
A book knows its title and author and, while it is out, who has it and when it is due. issue works out the due date with timedelta, and take_back returns how many days late the book is.
class Book: """A book on the shelf, and who has it while it is out.""" def __init__(self, title, author): self.title = title self.author = author self.borrower = None # Member ID while the book is out self.due = None # Date it must come back def issue(self, member_id, day): """Lend the book to a member for LOAN_DAYS days.""" self.borrower = member_id self.due = day + timedelta(days=LOAN_DAYS) def take_back(self, day): """Mark the book as returned and return how many days late it is.""" days_late = max(0, (day - self.due).days) self.borrower, self.due = None, None return days_late
2. Dates in DD-MM-YYYY form
datetime.strptime reads the text with DATE_FORMAT and raises ValueError for dates like 31-02-2026. Pressing Enter uses today's date.
def ask_date(prompt): """Ask for a date like 05-10-2026; Enter means today.""" while True: text = input(f"{prompt} (DD-MM-YYYY, Enter for today): ").strip() if text == "": return date.today() try: return datetime.strptime(text, DATE_FORMAT).date() except ValueError: print(" Please type the date like 05-10-2026.")
3. Listing the books
Each book shows Available, or which member has it and the due date, turned back into text with strftime.
def show_books(books): """Print every book with its status.""" print(f" {'ID':<6}{'Title':<21}{'Author':<22}Status") for book_id, book in books.items(): status = "Available" if book.borrower: status = f"Out to {book.borrower}, due {book.due.strftime(DATE_FORMAT)}" print(f" {book_id:<6}{book.title:<21}{book.author:<22}{status}")
4. Issuing a book
The function stops early when the user cancels or the book is already out. books.get() gives None for a cancelled ID instead of raising KeyError.
def issue_book(books, members): """Ask for a book, a member and a date, then lend the book.""" book = books.get(ask_id("Book ID: ", books)) # None if cancelled if book is None: return if book.borrower: print(f" {book.title} is out until {book.due.strftime(DATE_FORMAT)}.") return member_id = ask_id("Member ID: ", members) if not member_id: return book.issue(member_id, ask_date("Issue date")) print(f" {book.title} issued to {members[member_id]}. " f"Due back on {book.due.strftime(DATE_FORMAT)}.")
5. Returning a book and the fine
Subtracting two dates gives a timedelta, and its .days is the number of days late. The fine is that number times FINE_PER_DAY.
def return_book(books): """Take a book back and work out any late fine.""" book = books.get(ask_id("Book ID: ", books)) if book is None: return if book.borrower is None: print(f" {book.title} is not out.") return days_late = book.take_back(ask_date("Return date")) if days_late: print(f" Returned {days_late} day(s) late. Fine: {days_late * FINE_PER_DAY}") else: print(" Returned on time. No fine.")
6. Setting up the library
Books live in a dictionary keyed by ID and members in another. dict(STARTING_MEMBERS) makes a copy, so adding a member never changes the constant.
def main(): """Set up the library and run the menu until the user quits.""" books = {} # Book ID -> Book for book_id, title, author in STARTING_BOOKS: books[book_id] = Book(title, author) members = dict(STARTING_MEMBERS) # Member ID -> name (a copy we can change) print("Library management system") while True: print() print(MENU) choice = input("Choose 1-7: ").strip() if choice == "1": show_books(books) elif choice == "2": for member_id, name in members.items(): count = sum(1 for book in books.values() if book.borrower == member_id) print(f" {member_id:<5}{name:<18}{count} book(s) out") elif choice == "3": title, author = input("Title: ").strip(), input("Author: ").strip() if title and author: book_id = f"B{101 + len(books)}" books[book_id] = Book(title, author) print(f" Added book {book_id}.") else: print(" A book needs a title and an author.") elif choice == "4": name = input("Member name: ").strip() if name: member_id = f"M{len(members) + 1}" members[member_id] = name print(f" Added member {member_id}.") else: print(" A member needs a name.") elif choice == "5": issue_book(books, members) elif choice == "6": return_book(books) elif choice == "7": print("Goodbye.") break else: print(" Please choose a number from 1 to 7.")
Make it bigger
- Save books and members to CSV files so the library keeps its records between runs.
- Limit each member to three books at a time.
- Add a search by title or author.
- List every overdue book on a chosen date with the fine owed so far.