📜  使用Python的简单考勤跟踪器

📅  最后修改于: 2022-05-13 01:54:35.673000             🧑  作者: Mango

使用Python的简单考勤跟踪器

在许多大学中,我们对每个科目都有一个考勤系统,缺乏相同的系统会导致问题。学生很难记住特定科目的休假次数。如果每次都要做文书工作来跟踪员工请假的数量,并检查是否缺勤,这会耗费大量时间,效率也很低。

本文将带来一个简单的考勤跟踪器和提醒系统。该系统的输入是一个 Excel 表格,其中包含学生的邮件 ID 和他们在每个班级主题中的休假数。比如说,如果一个学生请假超过 3 次,就不允许他为特定科目写考试。该跟踪器将在学生第二次休假时向他发送一封电子邮件,以提醒他在该主题上只剩下 1 人。如果他再请假,学生和相应的工作人员都会收到有关缺勤的电子邮件。唯一要做的就是输入缺课学生的科目代码和卷号,其余的将由这个跟踪系统处理。

使用的 Python模块

使用 pip 或 conda 命令安装以下模块。

  • openpyxl - 更新和读取 excel 表。
  • smtplib & email – 发送电子邮件。

使用中的数据集:

Excel 工作表应包含以下数据:

  • 卷号
  • 学生邮件ID
  • 主题 {1,2,……..N}

对于本文,将三个主题及其代码视为输入的数字:

  • 计算机智能(CI)——> 1
  • Python--> 2
  • 数据挖掘(DM)--> 3

最初,Excel 工作表应如下所示:

用于发送邮件的 Gmail ID

建议创建一个单独的邮件 ID 用作发件人,因为 Google 会阻止不太安全的应用程序登录 Gmail。发送邮件必须授予某些权限,这与使用个人邮件 ID 有风险。如果您不授予权限,您最终会收到“错误凭据”错误,并会收到一封电子邮件,如下面的屏幕截图所示:

为避免这些问题,请按照以下步骤操作:

  • 登录到您的帐户。
  • 单击右上角的个人资料图标,然后单击管理您的谷歌帐户。

  • 转到安全选项卡并搜索“不太安全的应用程序”设置。

  • 不太安全的应用程序选项将被关闭。点击“开启访问”。

  • 您将看到以下屏幕并单击切换按钮以允许非 Google 应用程序使用您的 Gmail 帐户。

现在所有的先决条件都准备好了。必须编写Python脚本才能进行跟踪。让我们一步一步来。

逐步实施

  • 导入所需模块
  • 初始化所需变量并导入正在使用的数据文件。
  • 创建一个函数以在每次更新时保存 excel
Python3
def savefile():
  
    book.save(r'\attendance.xlsx')
    print("saved!")


Python3
def check(no_of_days, row_num, b):
  
  # to use the globally declared lists and strings
    global staff_mails
    global l2
    global l3


Python3
# for students
def 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 staffs
def 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')


Python3
import openpyxl
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
  
# loading the excel sheet
book = openpyxl.load_workbook('D:\\attendance.xlsx')
  
# Choose the sheet
sheet = book['Sheet1']
  
# counting number of rows / students
r = sheet.max_row
  
# variable for looping for input
resp = 1
  
# counting number of columns / subjects
c = sheet.max_column
  
# list of students to remind
l1 = []
  
# to concatenate list of roll numbers with
# lack of attendance
l2 = ""
  
# list of roll numbers with lack of attendance
l3 = []
  
# staff mail ids
staff_mails = ['erakshaya485@gmail.com', 'yyyyyyyy@gmail.com']
  
# Warning messages
m1 = "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 students
def 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 staff
def 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'))


  • 创建一个跟踪出勤率的函数:需要一个根据阈值条件检查缺勤者列表的函数。必须对在函数外部声明为全局变量的变量进行更新。因此,编写了以下行。

Python3

def check(no_of_days, row_num, b):
  
  # to use the globally declared lists and strings
    global staff_mails
    global l2
    global l3
  • 这个check()函数接受三个参数:
    • no_of_days :包含 total.no.of 的 A-List。 row_num 参数中学生的叶子。
    • row_num :今天缺勤者的卷号列表
    • b :主题代码

例子 :

  • 遍历学生列表 (row_num) 并为每个学生检查以下条件:
    • 如果总叶数 == 警告阈值
    • 如果总叶数 > 警告阈值
  • 在这里,考虑到一个学生如果超过 2 个假期就不能参加考试。因此,警告阈值为 2。如果学生请假 2 次,包括今天缺勤,则必须向他发送提醒邮件,否则必须发送两封说明缺勤的邮件,一封给学生,另一封给学生为员工。
  • 现在,如果总 no.of.leaves == 警告阈值 -将相应学生的邮件 ID 添加到列表'l1' 中,否则,列表'l3' 。如果将学生的邮件 ID 添加到列表'l3' ,则应将卷号添加到字符串'l2'以发送给工作人员。
  • 创建邮件函数:将创建两个函数,即mailstu()mailstaff() 。可以有一份要向其发送警告的学生列表,但该相应科目只有一名工作成员。因此,相应地编写了两种不同的方法。
    • smtplib 和 email.mime 模块用于在此脚本中发送邮件。
    • MIME 电子邮件现在被广泛使用。它们可以扩展为多用途互联网邮件扩展。它们允许在邮件正文中组合纯文本和 HTML。 email.mime API提供了从Python结构化电子邮件以及添加附件的功能。
    • smtplib模块提供通过端口连接到主机的能力。端口是为每个域预定义的,适当使用它有助于建立连接和发送邮件。 yahoo 的端口号也是587 ,但主机将是smtp.mail.yahoo.com

Python3

# for students
def 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 staffs
def 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')
  • 最后一步是编写一个循环,从用户那里获取输入,直到他们说不再输入。

下面给出了遵循上述方法的完整实现。

示例:简单的考勤跟踪器

Python3

import openpyxl
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
  
# loading the excel sheet
book = openpyxl.load_workbook('D:\\attendance.xlsx')
  
# Choose the sheet
sheet = book['Sheet1']
  
# counting number of rows / students
r = sheet.max_row
  
# variable for looping for input
resp = 1
  
# counting number of columns / subjects
c = sheet.max_column
  
# list of students to remind
l1 = []
  
# to concatenate list of roll numbers with
# lack of attendance
l2 = ""
  
# list of roll numbers with lack of attendance
l3 = []
  
# staff mail ids
staff_mails = ['erakshaya485@gmail.com', 'yyyyyyyy@gmail.com']
  
# Warning messages
m1 = "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 students
def 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 staff
def 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'))

输出:

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

执行前要记住的几点:

  • 有效的 Internet 连接是必需的。
  • 确保excel文件没有在窗口中打开,否则更新时会显示“Permission denied error”。