Simple Attendance Tracker using Python

28 Nov, 2021
In many colleges, we have an attendance system for each subject, and the lack of the same leads to problems. It is difficult for students to remember the number of leaves taken for a particular subject. If every time paperwork has to be done to track the number of leaves taken by staff and check whether it is a lack of attendance or not, it involves a lot of time and is inefficient too. 
This article will bring a simple tracker & reminder system for attendance. The input to this system is an excel sheet containing the students’ mail-id and their number of leaves in each class subject. For say, if a student will not be allowed to write the exam for a particular subject if he takes more than 3 leaves. This tracker will send out an email to the student when he takes the second leave as a reminder that only 1 more left with him on that subject. If he takes further leave, both the student and the corresponding staff receive emails regarding the lack of attendance. The only thing to do is just enter the subject code and roll number of the student absent from the class and the rest will be taken care of by this tracker system.
Install the following modules using pip or conda commands.
openpyxl – To update and read from the excel sheet.
smtplib & email   – To send out emails.
The Excel sheet should contain the following data:
Roll number
Student mail ID
Subject {1,2,........N}
For this article, consider three subjects and their codes as numbers for input: 
Computer Intelligence (CI)—-> 1
Python —-> 2
Data Mining (DM) —-> 3
Initially, the Excel sheet should look like this:
It is advisable to create a separate mail ID for use as the sender, as Google blocks less secure apps from signing in to Gmail. Certain permissions have to be given for sending the mail which is risky to do with a personal mail ID. If you do not give permissions you will end up with “bad credentials” error and will receive an email, as you see in the screenshot below:
To avoid these issues, follow the steps below:
Sign in to your account.
Click the profile icon in the top-right corner and click manage your google account.
Go to the security tab and search for “less secure apps” settings.
The less secure apps option will be turned off. Click on “Turn on access”.
You will see the following screen and click on the toggle button to allow non-Google apps use your Gmail account.
Now all the prerequisites are ready. A Python script has to be written for tracking. Let us do it step by step.
Import required modules
Initialize required variables and import the data file in use.
Create a function to save excel on every update
Python3
def savefile():      book.save(r'<your-path>\attendance.xlsx')    print("saved!")
Create a function to track attendance: A function for checking the list of absentees against the threshold condition is required. The updates must take place to the variables declared outside the function as global variables. Thus, the following lines are written.
Python3
def check(no_of_days, row_num, b):    # to use the globally declared lists and strings    global staff_mails    global l2    global l3
This check() function takes three arguments:no_of_days : A-List containing total.no.of. leaves of the students in the row_num parameter.row_num : A List of roll numbers of today’s absenteesb : Subject code
no_of_days : A-List containing total.no.of. leaves of the students in the row_num parameter.
row_num : A List of roll numbers of today’s absentees
b : Subject code
Example : 
If the parameters are [1,1,2,3] , [1,2,3,4] , 1
no_of_days : [1,1,2,3] – total number of leaves till date taken by each student in the next list.
row_num : [1,2,3,4] – roll numbers absent for today.
b: 1 – Subject Code : here Computer Intelligence
Loop through the list of students (row_num) and for each student check the following conditions:If total no.of.leaves == warning thresholdIf total no.of.leaves > warning threshold
If total no.of.leaves == warning threshold
If total no.of.leaves > warning threshold
Here, considering that a student will not be allowed to write exams if he takes more than 2 leaves. Thus, the warning threshold is 2. If a student takes 2 leaves, including today’s absence, then a reminder mail has to be sent to him, else two mails stating the lack of attendance have to be sent such that one for student and the other for staff.
Now, if total no.of.leaves == warning threshold – add the mail Id of the corresponding student to the list ‘l1’, otherwise, list ‘l3’. If the student’s mail ID is added to list ‘l3’, then the roll number should be added to the string ‘l2’ to send to the staff.
Create functions for mailing: Two functions, namely mailstu() and mailstaff() are to be created. There can be a list of students to whom warnings are to be sent but only one staff member for that corresponding subject. Thus, two different methods have been written accordingly.The smtplib and email.mime modules are used to send the mail in this script.MIME emails are widely used now. They can be expanded as Multipurpose Internet Mail Extensions. They allow a combination of plain text and HTML in the body of the mail. The email.mime API provides functionalities to structurize emails from Python and also to add attachments.The smtplib module gives the power to connect to a host via port. The ports are predefined for each domain and appropriate use of it helps to establish connections and send mail. The port number for yahoo is also 587, but the host will be smtp.mail.yahoo.com
The smtplib and email.mime modules are used to send the mail in this script.
MIME emails are widely used now. They can be expanded as Multipurpose Internet Mail Extensions. They allow a combination of plain text and HTML in the body of the mail. The email.mime API provides functionalities to structurize emails from Python and also to add attachments.
The smtplib module gives the power to connect to a host via port. The ports are predefined for each domain and appropriate use of it helps to establish connections and send mail. The port number for yahoo is also 587, but the host will be smtp.mail.yahoo.com
Python3
# for studentsdef mailstu(li, msg):    from_id = 'cXXXXXXXXXs@gmail.com'    pwd = 'XXXXXXXXXXXXX'    s = smtplib.SMTP('smtp.gmail.com', 587)    s.starttls()    s.login(from_id, pwd)      # for each student to warn send mail    for i in range(0, len(li)):        to_id = li[i]        message = MIMEMultipart()        message['Subject'] = 'Attendance report'        message.attach(MIMEText(msg, 'plain'))        content = message.as_string()        s.sendmail(from_id, to_id, content)        s.quit()    print("mail sent to students")  # for staffsdef mailstaff(mail_id, msg):    from_id = 'cXXXXXXXXXXs@gmail.com'    pwd = 'XXXXXXXX'    to_id = mail_id    message = MIMEMultipart()    message['Subject'] = 'Lack of attendance report'    message.attach(MIMEText(msg, 'plain'))    s = smtplib.SMTP('smtp.gmail.com', 587)    s.starttls()    s.login(from_id, pwd)    content = message.as_string()    s.sendmail(from_id, to_id, content)    s.quit()    print('Mail Sent to staff')
The final step is to write a loop that gets input from users until they say no more inputs.
The complete implementation following the above approach is given below.
Example: Simple attendance tracker 
Python3
import openpyxlimport smtplibfrom email.mime.multipart import MIMEMultipartfrom email.mime.text import MIMEText  # loading the excel sheetbook = openpyxl.load_workbook('D:\\attendance.xlsx')  # Choose the sheetsheet = book['Sheet1']  # counting number of rows / studentsr = sheet.max_row  # variable for looping for inputresp = 1  # counting number of columns / subjectsc = sheet.max_column  # list of students to remindl1 = []  # to concatenate list of roll numbers with# lack of attendancel2 = ""  # list of roll numbers with lack of attendancel3 = []  # staff mail idsstaff_mails = ['erakshaya485@gmail.com', 'yyyyyyyy@gmail.com']  # Warning messagesm1 = "warning!!! you can take only one more day leave for CI class"m2 = "warning!!! you can take only one more day leave for python class"m3 = "warning!!! you can take only one more day leave for DM class"    def savefile():    book.save(r'D:\\attendance.xlsx')    print("saved!")    def check(no_of_days, row_num, b):      # to use the globally declared lists and strings    global staff_mails    global l2    global l3      for student in range(0, len(row_num)):        # if total no.of.leaves equals threshold        if no_of_days[student] is 2:            if b is 1:                                  # mail_id appending                l1.append(sheet.cell(row=row_num[student], column=2).value)                mailstu(l1, m1)  # sending mail            elif b is 2:                l1.append(sheet.cell(row=row_num[student], column=2).value)                mailstu(l1, m2)            else:                l1.append(sheet.cell(row=row_num[student], column=2).value)                mailstu(l1, m3)          # if total.no.of.leaves > threshold        elif no_of_days[student] > 2:            if b is 1:                  # adding roll no                l2 = l2+str(sheet.cell(row=row_num[student], column=1).value)                  # student mail_id appending                l3.append(sheet.cell(row=row_num[student], column=2).value)                subject = "CI"  # subject based on the code number              elif b is 2:                l2 = l2+str(sheet.cell(row=row_num[student], column=1).value)                l3.append(sheet.cell(row=row_num[student], column=2).value)                subject = "Python"              else:                l2 = l2+str(sheet.cell(row=row_num[student], column=1).value)                l3.append(sheet.cell(row=row_num[student], column=2).value)                subject = "Data mining"          # If threshold crossed, modify the message        if l2 != "" and len(l3) != 0:              # message for student            msg1 = "you have lack of attendance in " + subject + " !!!"              # message for staff            msg2 = "the following students have lack of attendance in your subject : "+l2              mailstu(l3, msg1)  # mail to students            staff_id = staff_mails[b-1]  # pick respective staff's mail_id            mailstaff(staff_id, msg2)  # mail to staff  # for studentsdef mailstu(li, msg):    from_id = 'crazygirlaks@gmail.com'    pwd = 'ERAkshaya485'    s = smtplib.SMTP('smtp.gmail.com', 587, timeout=120)    s.starttls()    s.login(from_id, pwd)      # for each student to warn send mail    for i in range(0, len(li)):        to_id = li[i]        message = MIMEMultipart()        message['Subject'] = 'Attendance report'        message.attach(MIMEText(msg, 'plain'))        content = message.as_string()        s.sendmail(from_id, to_id, content)        s.quit()    print("mail sent to students")  # for staffdef mailstaff(mail_id, msg):    from_id = 'crazygirlaks@gmail.com'    pwd = 'ERAkshaya485'    to_id = mail_id    message = MIMEMultipart()    message['Subject'] = 'Lack of attendance report'    message.attach(MIMEText(msg, 'plain'))    s = smtplib.SMTP('smtp.gmail.com', 587, timeout=120)    s.starttls()    s.login(from_id, pwd)    content = message.as_string()    s.sendmail(from_id, to_id, content)    s.quit()    print('Mail Sent to staff')    while resp is 1:    print("1--->CI\n2--->python\n3--->DM")      # enter the correspondingnumber    y = int(input("enter subject :"))      # no.of.absentees for that subject    no_of_absentees = int(input('no.of.absentees :'))      if(no_of_absentees > 1):        x = list(map(int, (input('roll nos :').split(' '))))    else:        x = [int(input('roll no :'))]      # list to hold row of the student in Excel sheet    row_num = []      # list to hold total no.of leaves    # taken by ith student    no_of_days = []      for student in x:          for i in range(2, r+1):              if y is 1:                if sheet.cell(row=i, column=1).value is student:                    m = sheet.cell(row=i, column=3).value                    m = m+1                    sheet.cell(row=i, column=3).value = m                    savefile()                    no_of_days.append(m)                    row_num.append(i)              elif y is 2:                if sheet.cell(row=i, column=1).value is student:                    m = sheet.cell(row=i, column=4).value                    m = m+1                    sheet.cell(row=i, column=4).value = m+1                    no_of_days.append(m)                    row_num.append(i)              elif y is 3:                if sheet.cell(row=i, column=1).value is student:                    m = sheet.cell(row=i, column=5).value                    m = m+1                    sheet.cell(row=i, column=5).value = m+1                    row_num.append(i)                    no_of_days.append(m)      check(no_of_days, row_num, y)    resp = int(input('another subject ? 1---->yes 0--->no'))
Output:
1--->CI
2--->python
3--->DM
enter subject :1
no.of.absentees :2
roll nos :1 3
saved!
saved!
another subject ? 1---->yes 0--->no 1
1--->CI
2--->python
3--->DM
enter subject :1
no.of.absentees :1
roll no :1
saved!
mail sent to students
another subject ? 1---->yes 0--->no 1
1--->CI
2--->python
3--->DM
enter subject :1
no.of.absentees :1
roll no :1
saved!
mail sent to students
Mail Sent to staff
another subject ? 1---->yes 0--->no 0
Points to remember before executing:
Active Internet connection is mandatory.
Make sure the excel file is not open in a window, otherwise upon updating, “Permission denied error” will be displayed.
Python-projects
python-utility
Python
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.