Python技术迷

为什么Python没有main函数?

最近项目上,我写了个小玩意儿,就是那种电子考勤系统,用 Python 做的。其实一开始也没打算搞得多复杂,毕竟就是内部团队用用,能打卡、能统计、能导出就行。结果越写越上头,越写越觉得有点意思。

那天我们组的老王又迟到了,打卡系统崩了他就赖系统。我当时心想,这玩意儿不就一个签到时间嘛,整那么复杂干啥?于是晚上回去我就开干了,拿 Flask + SQLite 先撸个简易版看看能不能跑起来。

其实核心逻辑特别简单:用户输入工号 → 记录当前时间 → 存数据库。只是后来发现,光打卡没用,还得有迟到统计、请假记录、导出日报表之类的功能。

数据库设计那块

我用 SQLite 是因为方便,不想一开始就上 MySQL。表也就两张:

import sqlite3

conn = sqlite3.connect('attendance.db')
cursor = conn.cursor()

cursor.execute('''
CREATE TABLE IF NOT EXISTS users (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    name TEXT NOT NULL,
    employee_id TEXT UNIQUE NOT NULL
)
'''
)

cursor.execute('''
CREATE TABLE IF NOT EXISTS records (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    employee_id TEXT NOT NULL,
    timestamp DATETIME DEFAULT CURRENT_TIMESTAMP,
    type TEXT CHECK(type IN ('checkin', 'checkout'))
)
'''
)

conn.commit()
conn.close()

其实后来我才发现,这里用 CHECK 限制字段类型真的挺好用的,防止别人瞎传值。

Flask 接口部分

我没写前端,直接用 Postman 调就够了。打卡接口其实也就十来行:

from flask import Flask, request, jsonify
import sqlite3, datetime

app = Flask(__name__)

@app.route('/checkin', methods=['POST'])
defcheckin():
    data = request.get_json()
    employee_id = data.get('employee_id')
    conn = sqlite3.connect('attendance.db')
    cursor = conn.cursor()
    cursor.execute('INSERT INTO records (employee_id, type) VALUES (?, ?)', (employee_id, 'checkin'))
    conn.commit()
    conn.close()
return jsonify({'status': 'ok', 'time': datetime.datetime.now().isoformat()})

最开始我还想着用 JWT 做个登录鉴权,后来觉得有点杀鸡用牛刀,就懒得整了,反正内部使用嘛。

迟到判断逻辑

这个我一开始写得特糙,就是直接用时间比对。上班时间是 9:00,那谁 9:05 打卡我就标记成迟到。

defis_late(timestamp):
    work_time = datetime.time(9, 0, 0)
return timestamp.time() > work_time

然后每天跑个脚本统计:

defgenerate_report():
    conn = sqlite3.connect('attendance.db')
    cursor = conn.cursor()
    cursor.execute('SELECT employee_id, timestamp FROM records WHERE type="checkin"')
    rows = cursor.fetchall()
    report = []
for r in rows:
        ts = datetime.datetime.fromisoformat(r[1])
        report.append({
'employee_id': r[0],
'checkin': r[1],
'status': 'late'if is_late(ts) else'on time'
        })
    conn.close()
return report

导出功能

后来领导说要看 Excel 报表,我又加了点 Pandas 的代码,一键导出成 .xlsx:

import pandas as pd

defexport_report():
    data = generate_report()
    df = pd.DataFrame(data)
    df.to_excel('attendance_report.xlsx', index=False)

那天真是笑死我了,导完之后我自己一看,居然我自己都迟到两次。

后来踩的坑

说实话最坑的地方是时间存储。SQLite 默认存的是字符串格式时间,我一开始还傻乎乎地比较字符串,结果 "9:30" 比 "10:00" 小,我还以为逻辑对,后来才发现 "9" 在字符串里其实比 "1" 大。最后老老实实转成 datetime 对象才搞定。

还有一点就是并发打卡,有时候俩人同时打卡会卡住,我后来加了个线程锁:

from threading import Lock
lock = Lock()

@app.route('/checkin', methods=['POST'])
defcheckin():
with lock:
# 原逻辑不变
        ...

就这样系统才算稳定。

说实话这东西不复杂,但好玩。用 Python 写这类小系统,Flask + SQLite 真的香,启动快、调试方便。你要想扩展也简单,换成 MySQL、加个前端页面、再上个定时任务推日报,妥妥的。

现在我们组的人每天打卡都用这个系统,偶尔会有人调侃说“老王你又迟到了”,我心想,这系统算没白写。

-END-

我为大家打造了一份RPA教程,完全免费:songshuhezi.com/rpa.html

🔥虎哥私藏精品🔥

虎哥作为一名老码农,整理了全网最全《python高级架构师资料合集》,总量高达650GB,点击下方公众号回复关键字 python 全部免费领