使用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 :主题代码
例子 :
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
- 遍历学生列表 (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”。