Build a fully functional console-based Student Management System in Python that stores, reads, updates, and deletes student records permanently using file handling - no database needed.
Before we write any code, make sure Python is installed on your computer. If you already have it, you can skip ahead to the next step.
python --version
Python 3.12.0. If you see a version number, you're all set!
student_management.student_management.py.students.csv - leave it empty for now. This will be our data file.csv and os modules. No pip install needed!
Before jumping into code, it is very important to understand what our program will do and how it is broken into small, manageable functions. Think of each function as a small machine that does one specific job.
Our Student Management System will support these operations - often called CRUD:
Here is every function we will write, explained in plain English before you see the code:
| Function Name | What It Does |
|---|---|
| initialize_file() | Creates the CSV file with a header row (Name, Roll No, Grade, Marks) if it doesn't already exist. Runs once when the program starts. |
| add_student() | Asks the user for a student's details and appends a new row to the CSV file. Uses append mode so existing records are not erased. |
| view_all_students() | Opens the CSV file, reads every row, and prints each student's details to the console in a neat, readable format. |
| search_student() | Asks for a Roll Number, scans through all records, and displays the matching student's details if found. |
| update_student() | Finds a student by Roll Number, asks for new values, rewrites the entire file with the updated record. This is called a rewrite technique. |
| delete_student() | Finds a student by Roll Number, removes that record, then rewrites the file without that row. |
| main_menu() | Displays a numbered menu and runs in a loop, calling the correct function based on what the user types. This is the heart of the program. |
csv module that makes reading and writing these files very easy - no complicated setup needed.
Our students.csv file will look like this after a few students are added:
The first row is the header (column names). Each row after that is one student's record.
Copy the complete code below into your student_management.py file. Read the comments (lines starting with #) - they explain what each block does as you go.
# ============================================
# Student Management System
# NKDevSpace Tutorial
# Uses Python File Handling (CSV Format)
# ============================================
import csv
import os
# ----- CONFIGURATION -----
FILE_NAME = "students.csv"
HEADERS = ["Name", "Roll No", "Grade", "Marks"]
# ============================================
# 1. INITIALIZE - Create file if not present
# ============================================
def initialize_file():
"""Creates the CSV file with headers if it doesn't exist."""
if not os.path.exists(FILE_NAME):
with open(FILE_NAME, mode="w", newline="") as file:
writer = csv.writer(file)
writer.writerow(HEADERS)
print(f"[INFO] File '{FILE_NAME}' created successfully.\n")
# ============================================
# 2. ADD - Append a new student record
# ============================================
def add_student():
print("\n--- Add New Student ---")
name = input("Enter Student Name : ").strip()
roll_no = input("Enter Roll Number : ").strip()
grade = input("Enter Grade/Class : ").strip()
marks = input("Enter Marks (0-100) : ").strip()
# Basic validation - make sure no field is left empty
if not name or not roll_no or not grade or not marks:
print("[ERROR] All fields are required. Student not added.\n")
return
# Append mode ("a") adds to the end without erasing existing data
with open(FILE_NAME, mode="a", newline="") as file:
writer = csv.writer(file)
writer.writerow([name, roll_no, grade, marks])
print(f"\n[SUCCESS] Student '{name}' added successfully!\n")
# ============================================
# 3. VIEW - Display all student records
# ============================================
def view_all_students():
print("\n--- All Students ---")
with open(FILE_NAME, mode="r") as file:
reader = csv.DictReader(file)
students = list(reader)
if not students:
print("[INFO] No student records found.\n")
return
# Print table header
print(f"\n{'#':<5} {'Name':<20} {'Roll No':<10} {'Grade':<10} {'Marks':<8}")
print("-" * 58)
# Print each student row
for index, student in enumerate(students, start=1):
print(
f"{index:<5} {student['Name']:<20} {student['Roll No']:<10} "
f"{student['Grade']:<10} {student['Marks']:<8}"
)
print(f"\n[INFO] Total students: {len(students)}\n")
# ============================================
# 4. SEARCH - Find a student by Roll Number
# ============================================
def search_student():
print("\n--- Search Student ---")
roll_no = input("Enter Roll Number to search: ").strip()
with open(FILE_NAME, mode="r") as file:
reader = csv.DictReader(file)
for student in reader:
if student["Roll No"] == roll_no:
print("\n[FOUND] Student Details:")
print(f" Name : {student['Name']}")
print(f" Roll No : {student['Roll No']}")
print(f" Grade : {student['Grade']}")
print(f" Marks : {student['Marks']}\n")
return
print(f"[NOT FOUND] No student with Roll Number '{roll_no}' exists.\n")
# ============================================
# 5. UPDATE - Edit a student's record
# ============================================
def update_student():
print("\n--- Update Student Record ---")
roll_no = input("Enter Roll Number of student to update: ").strip()
updated = False
all_rows = []
with open(FILE_NAME, mode="r") as file:
reader = csv.DictReader(file)
for student in reader:
if student["Roll No"] == roll_no:
print(f"\n[FOUND] Updating record for: {student['Name']}")
print("(Press Enter to keep the current value)\n")
new_name = input(f" New Name [{student['Name']}] : ").strip()
new_grade = input(f" New Grade [{student['Grade']}] : ").strip()
new_marks = input(f" New Marks [{student['Marks']}] : ").strip()
# Keep old value if user pressed Enter without typing
student["Name"] = new_name if new_name else student["Name"]
student["Grade"] = new_grade if new_grade else student["Grade"]
student["Marks"] = new_marks if new_marks else student["Marks"]
updated = True
all_rows.append(student)
if not updated:
print(f"[NOT FOUND] No student with Roll Number '{roll_no}' exists.\n")
return
# Rewrite the entire file with the updated row
with open(FILE_NAME, mode="w", newline="") as file:
writer = csv.DictWriter(file, fieldnames=HEADERS)
writer.writeheader()
writer.writerows(all_rows)
print(f"\n[SUCCESS] Student record updated successfully!\n")
# ============================================
# 6. DELETE - Remove a student by Roll Number
# ============================================
def delete_student():
print("\n--- Delete Student ---")
roll_no = input("Enter Roll Number of student to delete: ").strip()
deleted = False
all_rows = []
with open(FILE_NAME, mode="r") as file:
reader = csv.DictReader(file)
for student in reader:
if student["Roll No"] == roll_no:
confirm = input(
f" Are you sure you want to delete '{student['Name']}'? (yes/no): "
).strip().lower()
if confirm == "yes":
deleted = True
continue # Skip this row - don't add it to all_rows
all_rows.append(student)
if deleted:
# Rewrite the file without the deleted student
with open(FILE_NAME, mode="w", newline="") as file:
writer = csv.DictWriter(file, fieldnames=HEADERS)
writer.writeheader()
writer.writerows(all_rows)
print(f"\n[SUCCESS] Student deleted successfully!\n")
else:
print(f"[INFO] No record was deleted.\n")
# ============================================
# 7. MAIN MENU - The program's control center
# ============================================
def main_menu():
initialize_file()
while True:
print("=" * 42)
print(" STUDENT MANAGEMENT SYSTEM")
print(" NKDevSpace")
print("=" * 42)
print(" 1. Add Student")
print(" 2. View All Students")
print(" 3. Search Student")
print(" 4. Update Student Record")
print(" 5. Delete Student")
print(" 6. Exit")
print("=" * 42)
choice = input(" Enter your choice (1-6): ").strip()
if choice == "1": add_student()
elif choice == "2": view_all_students()
elif choice == "3": search_student()
elif choice == "4": update_student()
elif choice == "5": delete_student()
elif choice == "6":
print("\n[GOODBYE] Thank you for using NKDevSpace Student Manager!\n")
break
else:
print("[ERROR] Invalid choice. Please enter a number between 1 and 6.\n")
# ============================================
# ENTRY POINT
# ============================================
if __name__ == "__main__":
main_menu()
This is the most important step. We will go through every key concept in this program in detail. Do not skip this - understanding these ideas will help you write your own projects later.
import csv
import oscsv module handles all of that safely for you.
os.path.exists() to check if our data file already exists before trying to create it. This prevents accidentally overwriting existing data.
FILE_NAME = "students.csv"
HEADERS = ["Name", "Roll No", "Grade", "Marks"]"students.csv" in every single function, we define it once at the top as a constant (a variable that never changes). This is a professional practice - if you ever want to rename your file, you only change it in one place, not in 10 places throughout the code.
HEADERS is a Python list containing the column names for our CSV file. Using ALL_CAPS names for constants is a widely accepted Python convention.
File handling in Python uses the open() function. The mode parameter controls what you can do with the file:
open(FILE_NAME, mode="w", newline="")initialize_file() (only when the file doesn't exist yet) and when rewriting the file after an update or delete.
open(FILE_NAME, mode="a", newline="")add_student() - we want to add one new row at a time without touching the old ones.
open(FILE_NAME, mode="r")view_all_students(), search_student(), and at the start of update_student() and delete_student().
writer = csv.writer(file)
writer.writerow([name, roll_no, grade, marks])csv.writer writes data as a plain list. Each element in the list becomes one cell in the CSV row. We use this in add_student() because we are building the row from scratch with new user input.
writer = csv.DictWriter(file, fieldnames=HEADERS)
writer.writeheader()
writer.writerows(all_rows)csv.DictWriter writes data from a dictionary (where each key matches a column header). This is more reliable when rewriting the entire file because it ensures columns always line up correctly with the headers. We use this in update_student() and delete_student().
writeheader() writes the column names as the first row. writerows() writes all the student dictionaries at once.
reader = csv.DictReader(file)
for student in reader:
print(student["Name"])csv.DictReader reads each row as a dictionary, where the keys are the column headers. So instead of accessing a student's name by position (like row[0]), you access it by name (student["Name"]). This makes the code far more readable and less error-prone.
Aarav Sharma,101,10th,87.5, then student["Name"] gives you "Aarav Sharma" and student["Marks"] gives you "87.5".
This is the trickiest concept in file handling. CSV files don't support editing individual lines in the middle of the file. So to update or delete a record, we use this 3-step technique:
# Step 1: Read ALL rows into memory
all_rows = list(reader)
# Step 2: Modify or remove the target row
for row in all_rows: ...
# Step 3: Rewrite the file with the changes
writer.writerows(all_rows)list(reader) call converts the reader object into a regular Python list so we can loop through it, modify it, and use it again.
while True:
# show menu
choice = input(...)
if choice == "6": breakwhile True creates an infinite loop - the menu keeps showing forever. The only way out is break, which we trigger when the user chooses option 6 (Exit). This pattern is standard for menu-driven console programs. Every iteration of the loop shows the menu, waits for input, and calls the right function.
if __name__ == "__main__":
main_menu()__name__ is a special variable Python sets automatically. When you run the file directly (e.g., python student_management.py), Python sets __name__ to "__main__", so main_menu() runs.
__name__ will be the module name instead, so main_menu() will not run automatically. This keeps the program flexible for reuse.
name = input("Enter Name: ").strip()
if not name: return.strip() removes any leading or trailing spaces the user might accidentally type. For example, if the user types " Aarav ", .strip() converts it to "Aarav".
if not name check catches empty inputs. If the user just presses Enter without typing anything, the field will be an empty string and we stop the function early using return. This prevents storing blank records in our file.
Now that the code is written, let's run it and test all the features.
student_management.py file in VS Code.ls (Mac/Linux) or dir (Windows) - you should see student_management.py listed.python student_management.py
Type 1 and press Enter. You'll be prompted:
Add 2–3 more students. Then try option 2 to view them all.
Type 4, enter Roll Number 101, update the marks, and press Enter for fields you don't want to change.
Open students.csv in VS Code or Excel. You'll see all your students saved there permanently. Close the program and run it again - all your data will still be there. That's the power of file handling!
student_management.py file. Use cd folder_name to navigate into the correct folder first.
You've built the core system. Now push further with these challenges and turn a good project into a great one: