Attendance Register for a Coaching Class
Mark daily attendance and get each student's monthly percentage with the shortfalls flagged.
1Introduction: the problem it solves
A small coaching class with forty students keeps attendance in a register. At the end of the month somebody has to count the P's in every row by hand to find who is below 75%, and by then it is too late to do anything about it.
The counting is mechanical, so the computer should do it — and it should do it any day of the month, not only at the end.
A coaching centre, a school club, a sports coach, or any teacher who tracks daily attendance.
Why it is worth computerising
Marking attendance on paper is quick. Working out from that paper who has fallen below seventy-five per cent is not, and it is only done at the end of the month because of how long it takes. By then the student has already missed the classes, and nothing can be done about it.
The value of computerising this is not the marking, which was never the problem. It is that the percentage can be calculated on any day of the month, in a second, for the whole class. A shortage found on the tenth can still be fixed; the same shortage found on the thirtieth can only be recorded.
Objectives
- To record attendance for a whole class in one action rather than one entry at a time
- To store the register in a file that can never lose a day already written
- To count classes held and attended for every student without counting by hand
- To calculate the attendance percentage and flag anyone below the 75% requirement
- To make that report available on any day, not only at the end of the month
2How the job is done today
Before writing anything it is worth asking how the work is handled at present, and why each of those answers falls short. These were examined:
Universal, and the reason this project exists. Marking is quick; the counting at month end is not, and a shortage is discovered too late to be fixed.
Excellent where a school has one. They are priced per student per year, which puts them out of reach of a small coaching class.
Works for a month. The sheet grows sideways until it is unreadable, and adding a student mid-term means editing every row.
3Functionalities
- Marks a whole day's attendance in one call, writing P or A for every student on the roll
- Appends to the file rather than rewriting it, so no earlier day can be lost
- Counts classes held and classes attended for every student
- Works out the percentage and flags anyone below 75%
- Runs on any day, so a warning can be given while it still helps
The functions that provide them
| Function | Arguments | What it does |
|---|---|---|
mark() | roll_list, day, present_rolls | Append one day's attendance: P for present, A for absent. |
report() | — | Work out each student's attendance percentage. |
4Technical details
| Language | Python 3 |
| Storage | Plain text and CSV files |
| Modules used |
|
5How the data is stored
One file, `attendance.csv`, holding one row per student per day: the date, the roll number, and P or A. Append mode is the whole design — a register you can only add to cannot lose yesterday.
attendance.csv — one row per student per day
| Field | Type | Description |
|---|---|---|
date | text | The day, written as DD-MM |
roll | text | Roll number of the student |
status | text | P if present, A if absent |
What the report works out
| Field | Type | Description |
|---|---|---|
held | integer | How many days that roll number appears — classes held |
present | integer | How many of those rows say P |
percent | decimal | present / held x 100, flagged when below 75 |
6How it works, step by step
mark() takes the roll list and the list of who turned up, and writes P or A for every student on the roll.
The file is opened in 'a' mode, so each day is added below the last one.
report() reads the whole file once, counting classes held and classes attended per roll number.
Anything under 75% is printed with a marker, which is the number a student is actually judged on.
7Source code
# ---------------------------------------------------------------------------
# attendance.py
#
# A month's attendance register for a small coaching class. Attendance is
# marked a day at a time and written to a CSV file; the report reads that file
# back and works out each student's percentage.
#
# The file is only ever APPENDED to. That is the central decision of this
# program: a register you can only add to is a register that cannot silently
# lose a day that was already marked.
# ---------------------------------------------------------------------------
import csv
FILE = "attendance.csv" # one row per student per day
def mark(roll_list, day, present_rolls):
"""Append one day's attendance: P for present, A for absent."""
# "a" is append mode. Opening with "w" here would wipe every earlier day,
# which is exactly the accident this program is written to prevent.
with open(FILE, "a", newline="") as f:
writer = csv.writer(f)
# Walk the whole roll, not just the students who turned up — an absence
# has to be recorded as firmly as a presence, or it cannot be counted.
for roll in roll_list:
status = "P" if roll in present_rolls else "A"
writer.writerow([day, roll, status])
def report():
"""Work out each student's attendance percentage."""
days = {} # roll -> how many classes were held for them
present = {} # roll -> how many of those they attended
with open(FILE, "r", newline="") as f:
# Each row was written as three values, so it can be unpacked into three
# names in one step.
for day, roll, status in csv.reader(f):
# Every row means a class was held, whoever attended it.
days[roll] = days.get(roll, 0) + 1
if status == "P":
present[roll] = present.get(roll, 0) + 1
print("LAMBDALAB COACHING CLASSES — ATTENDANCE, AUGUST")
print("{:<8}{:>8}{:>10}{:>10}".format("ROLL", "HELD", "PRESENT", "PERCENT"))
# sorted() so the roll numbers come out in order rather than in the order
# the dictionary happens to hold them.
for roll in sorted(days):
held = days[roll]
came = present.get(roll, 0) # .get() because a student who was
# never present has no entry at all
percent = came / held * 100
# 75% is the figure a student is actually judged on, so it is marked
# rather than left for the reader to work out.
flag = " <-- short" if percent < 75 else ""
print("{:<8}{:>8}{:>10}{:>9.1f}%{}".format(roll, held, came, percent, flag))
# --- the program itself ----------------------------------------------------
rolls = ["A01", "A02", "A03", "A04"] # the class list
open(FILE, "w").close() # start a fresh register for the demo;
# a real term would keep the old file
# Four days of attendance. In use, each of these lines would be run on its own
# day, with the list of who actually attended.
mark(rolls, "01-08", ["A01", "A02", "A03"])
mark(rolls, "02-08", ["A01", "A03", "A04"])
mark(rolls, "03-08", ["A01", "A02", "A03", "A04"])
mark(rolls, "04-08", ["A01", "A03"])
report()The full report as a PDF — cover page, certificate, index, code, output, future scope and references, ready to print and fill in. Or the code on its own as a zip.
8Sample output
This is a real run, not a mock-up — the transcript below is what the program actually printed.
C:\LambdaLab\Projects\Attendance> python attendance.py
LAMBDALAB COACHING CLASSES — ATTENDANCE, AUGUST
ROLL HELD PRESENT PERCENT
A01 4 4 100.0%
A02 4 2 50.0% <-- short
A03 4 4 100.0%
A04 4 2 50.0% <-- shortRunning it also wrote attendance.csv. This is what that file held afterwards:
01-08,A01,P
01-08,A02,P
01-08,A03,P
01-08,A04,A
02-08,A01,P
02-08,A02,A
02-08,A03,P
02-08,A04,P
03-08,A01,P
03-08,A02,P
03-08,A03,P
03-08,A04,P
04-08,A01,P
04-08,A02,A
04-08,A03,P
04-08,A04,A9Testing
Every case below was actually run and the result recorded as it appeared — including the ones expected to fail.
| Test case | Expected | Actual |
|---|---|---|
| Four days marked for four students | A02 at 50%, flagged as short | A02 4 2 50.0% <-- short |
| A student on exactly 75% | 75.0% and NOT flagged - the boundary | A04 4 3 75.0% |
| A day on which nobody attended | The day still counts as held for all | A01 4 3 75.0% |
| A class of one student | One row, 100% | A01 4 4 100.0% |
Two kinds of case are in there on purpose. The boundary cases test the edge of a rule, where a program is most often wrong by one. The failure cases check that it refuses cleanly and says why, instead of quietly producing a wrong answer.
10Advantages
Set against the ways the job is done today:
- A shortage is visible while there is still time to fix it
- No day can be lost, because the file is only ever added to
- The percentage is calculated the same way for every student
- One command produces a report for the whole class
- The file opens in any spreadsheet if it has to be checked by hand
11Future scope
What this version does not do
A report should be honest about its own limits, and each of these is the reason for one of the additions below:
- The roll list lives in the program, so a student joining mid-term needs a code change
- Attendance is a whole-day mark; separate periods are not recorded
- There is no correction facility — a wrong entry must be fixed in the file by hand
- Nothing is sent to a parent; the shortfall is only shown on screen
Proposed enhancements
This is also where you make the project yours. Pick one or two of these, or something nobody here thought of:
- Send an SMS or email to a parent as soon as a student drops below 75%
- A monthly chart of attendance with matplotlib
- Mark attendance from a phone by scanning a QR code on each student's card
- Separate the roll list into its own file so students can join mid-term
- Warn about a student absent three days running
12What you may have to teach yourself
CBSE expects some self-learning in a project, and says so. For this one, that means:
- dict.get(key, 0), which is what makes the counting loop short
- Why append mode matters here, and what 'w' would have destroyed
- Optional: matplotlib, for the attendance chart
13Conclusion
The register now answers, on any day of the month, the one question it was always being asked at the end of it. Marking takes no longer than it did on paper; the counting takes no time at all.
The choice of append mode turned out to matter more than anything clever in the program. A register that can only be added to is a register that cannot quietly lose a day.
14References
Every report needs a bibliography. This one used:
- Computer Science with Python, Class XII — the NCERT / CBSE prescribed textbook, for the chapters on file handling and working with text and CSV files
- Computer Science with Python, Class XI — for functions, lists, dictionaries and string handling
- Python 3 documentation — https://docs.python.org/3/
- CBSE Senior School Curriculum, Computer Science (Subject Code 083) — the project guidelines this report follows
- LambdaLab — https://www.lambdalab.in