用 Python 写了一个电子考勤系统
前段时间我们公司新来了几个实习生,每天上班都要签到,但是 HR 老是抱怨表格太乱了。那天中午我在茶水间喝咖啡,HR 跟我吐槽说:“能不能搞个自动的,不用手动登记那种。”我当时随口一说:“用 Python 搞个电子考勤系统不就行了嘛。”
结果第二天她真发了邮件过来让我试试。于是我就花了两晚,整了一个能扫码签到的系统。
架构思路其实挺简单
说白了,这玩意儿就是三部分:
人脸或二维码识别(识别是谁) 时间记录(记录签到签退时间) 界面展示(让 HR 一眼看到谁迟到早退)
最开始我打算用人脸识别,但后来发现有点麻烦,摄像头角度、光线一搞就识别不出来。后来我就换成二维码,反正每个人一个员工号,签到的时候手机一扫就行。
用 Flask 搭了个小后端
我这系统没用什么花哨的框架,就是一个 Flask + SQLite 的组合,小巧、方便部署。
后端主要负责两个接口:
/checkin负责签到/checkout负责签退
核心逻辑其实就几行,比如下面这段代码:
from flask import Flask, request, jsonify
import sqlite3, datetimeapp = Flask(__name__)
defdb_conn():
conn = sqlite3.connect("attendance.db")
return conn
@app.route('/checkin', methods=['POST'])
defcheckin():
emp_id = request.json.get("emp_id")
now = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
conn = db_conn()
cursor = conn.cursor()
cursor.execute("INSERT INTO records (emp_id, checkin_time) VALUES (?, ?)", (emp_id, now))
conn.commit()
conn.close()
return jsonify({"status": "ok", "msg": f"{emp_id} 签到成功"})
if __name__ == '__main__':
app.run(host="0.0.0.0", port=8080)
数据库用的 SQLite,因为小项目够用了。建表也就一行:
CREATE TABLE records (
id INTEGER PRIMARY KEY AUTOINCREMENT,
emp_id TEXT,
checkin_time TEXT,
checkout_time TEXT
);
前端我用的 PyQt5 做的桌面端
虽然是个后端程序员,但 HR 不会用命令行,我就顺手用 PyQt5 做了个简单的可视化界面。界面上就两个按钮:“签到”和“签退”,然后显示当天所有人的状态。
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QLabel, QVBoxLayout
import requestsclassAttendanceApp(QWidget):
def__init__(self):
super().__init__()
self.init_ui()
definit_ui(self):
self.label = QLabel('扫描二维码签到或签退')
self.btn_checkin = QPushButton('签到')
self.btn_checkout = QPushButton('签退')
self.btn_checkin.clicked.connect(self.check_in)
self.btn_checkout.clicked.connect(self.check_out)
layout = QVBoxLayout()
layout.addWidget(self.label)
layout.addWidget(self.btn_checkin)
layout.addWidget(self.btn_checkout)
self.setLayout(layout)
self.setWindowTitle("电子考勤系统")
self.show()
defcheck_in(self):
emp_id = "E1001"# 模拟扫码结果
res = requests.post("http://127.0.0.1:8080/checkin", json={"emp_id": emp_id})
self.label.setText(res.json().get("msg"))
defcheck_out(self):
emp_id = "E1001"
res = requests.post("http://127.0.0.1:8080/checkout", json={"emp_id": emp_id})
self.label.setText(res.json().get("msg"))
app = QApplication([])
win = AttendanceApp()
app.exec_()
虽然简陋,但 HR 说挺好用,还让我加个导出功能,于是我后来又加了个按钮,可以把考勤数据导出成 Excel:
import pandas as pd
conn = sqlite3.connect("attendance.db")
df = pd.read_sql_query("SELECT * FROM records", conn)
df.to_excel("attendance.xlsx", index=False)
实际部署的时候踩了一些坑
最开始我放在公司服务器上跑,结果第二天就被 IT 部门警告占用端口(笑)。后来我改成放在本地电脑上启动 Flask,局域网内访问。 顺便用 ngrok 开了个内网穿透,这样 HR 在家也能查记录。
有一次我忘了加锁,两个实习生同时点签到按钮,数据库插入冲突了。后来我在接口里加了一个简单的防重机制:
cursor.execute("SELECT * FROM records WHERE emp_id=? AND date(checkin_time)=date('now')", (emp_id,))
if cursor.fetchone():
return jsonify({"status": "fail", "msg": "今天已经签过到了"})
整个项目写下来就三百多行代码,但比想象中好用多了。 后来我还加了个小彩蛋:每天第一个签到的人会显示“今天你最早来公司 👍”,HR 说这个功能太有趣了。
其实用 Python 做这种轻量级系统真的挺方便的,Flask 搭个接口,SQLite 存数据,PyQt5 做个界面,半天就能出原型。 我下个计划是接入摄像头做人脸签到,到时候可能得上 OpenCV,那估计又得掉一堆头发了。
-END-
我为大家打造了一份RPA教程,完全免费:songshuhezi.com/rpa.html
虎哥作为一名老码农,整理了全网最全《python高级架构师资料合集》,总量高达650GB,点击下方公众号回复关键字 python 全部免费领