Python买药提醒和数据统计

时间:2024-11-17 11:00:32

一、为什么要搞

之前我感觉腰子剧痛,医生诊断尿道有结石,还不到超声碎石的程度,需要坚持运动和吃药,可很多时候药吃完了,却忘记了买药。

于是乎,我尝试使用Python实现买药提醒并且统计买药数据

二、准备如何搞

买药的数据记录在excel文件中:

Python买药提醒和数据统计_自动邮件提醒

tablib读取最近买药数据,计算出下次买药日期

tinydb记录下次购买日期JSON数据

zmail发送买药提醒邮件

matplotlib绘制买药数据统计图表

三、说搞咱就搞

计算

读取excel,获取最后购买时间和数量,根据每日用量3袋计算出下次购买时间,并将其记录至medicine_purchase_notice.json文件

import datetime
import math
from tablib import Dataset
from tinydb import TinyDB


# 计算
def medicine_cant_stop(file):
    """
    计算下次买药日期
    """
    with open(file, 'rb') as f:  # 读取excel到数据集
        data = Dataset().load(f)
    last_purchase_time = data[-1][0]  # 最后购买时间
    last_purchase_num = data[-1][1]  # 最后购买数量
    use_num = 3  # 每日用量--3小袋
    gap_days = math.trunc(last_purchase_num / use_num)  # 购买的数量还能吃多少天--取整
    next_purchase_time = datetime.timedelta(days=gap_days) + last_purchase_time  # 预计下次购买时间

    with TinyDB('medicine_purchase_notice.json') as db:  # 创建db
        db.insert({'notice_date': str(next_purchase_time.date())})  # 插入数据
    return next_purchase_time.date()


if __name__ == "__main__":
    file_path = 'medicine_record.xlsx'
    print(medicine_cant_stop(file_path))

运行结果:

Python买药提醒和数据统计_Python_02

提醒

读取medicine_purchase_notice.json文件最后一条数据,若与当前日期相同,则发送买药提醒邮件

import datetime
import traceback
import zmail
from tinydb import TinyDB


# 提醒
def medicine_purchase_notice():
    """
    发送买药提醒邮件
    """
    with TinyDB('medicine_purchase_notice.json') as db:  # 从json文件获取所有数据
        data = db.all()
    notice_date = datetime.datetime.strptime(data[-1]['notice_date'], '%Y-%m-%d').date()  # 将最后一条数据转换为日期格式
    today = datetime.date.today()  # 今天
    if today == notice_date:  # 提醒日期=今天
        # 发送邮件
        try:
            server = zmail.server('********@163.com', 'L************V')  # 发件人邮箱地址和授权码
            mail_content = {
                'subject': '买药提醒',  # 主题
                'content_text': '今天要买药了哦!'  # 文本内容
            }
            server.send_mail('********@163.com', mail_content)  # 收件人地址和邮件内容
        except Exception as e:
            info = f"邮件发送失败!\n{repr(e)}\n{traceback.format_exc()}"
            print(info)
        else:
            print('邮件发送成功!')


if __name__ == "__main__":
    medicine_purchase_notice()

运行结果:

Python买药提醒和数据统计_Python_03

统计

读取excel中的数据,绘制时间-数量折线图和时间-花费柱状图

import os
import mplcyberpunk
from matplotlib import pyplot as plt
from tablib import Dataset


# 统计
def medicine_purchase_report(file):
    """
    历史买药数据统计
    """
    with open(file, 'rb') as f:  # 读取excel到数据集
        data = Dataset().load(f)

    plt.style.use(os.path.dirname(os.path.abspath(__file__)) + os.sep + 'cyberpunk.mplstyle')  # 设置主题样式
    plt.rcParams['font.sans-serif'] = ['STSong']  # Simhei(黑体) Kaiti(楷体) Lisu(隶书) STSong(宋体)--设置后可正常显示中文

    x = [d.date() for d in data.get_col(0)]  # X轴
    y_num = data.get_col(1)  # Y轴--数量(小袋)
    y_cost = data.get_col(2)  # Y轴--花费
    fig, ax_num = plt.subplots()  # 创建图表和数量坐标轴

    ax_num.plot(x, y_num, label=data.headers[1], color='b')  # 数量折线图--蓝色
    ax_num.set_ylabel(data.headers[1], color='b')  # 数量折线图Y轴标签--蓝色
    ax_num.tick_params('y', colors='b')  # 设置数量折线图Y轴刻度和标签颜色--蓝色
    ax_num.set_ylim([0, max(y_num)])  # 设置Y轴刻度范围
    ax_num.set_xticks(x, labels=x, rotation=35)  # 设置X轴标签和角度

    ax_cost = ax_num.twinx()  # 花费坐标轴--共享数量坐标轴的X轴
    bars = ax_cost.bar(x, y_cost, label=data.headers[2], color='r')  # 花费柱状图--红色
    ax_cost.set_xlabel(data.headers[0])  # X轴标题
    ax_cost.set_ylabel(data.headers[2], color='r')  # 花费柱状图Y轴标签--红色
    for index, val in enumerate(y_cost):  # 设置Y轴数据
        plt.text(x[index], val, val, ha='center', va='bottom')
    mplcyberpunk.add_bar_gradient(bars=bars)  # 柱状图颜色渐变
    ax_cost.tick_params('y', colors='r')  # 设置花费柱状图Y轴刻度和标签颜色--红色
    ax_cost.grid(linestyle='--')  # 设置网格线样式

    plt.show()  # 显示图像


if __name__ == "__main__":
    file_path = 'medicine_record.xlsx'
    medicine_purchase_report(file_path)

运行结果:

Python买药提醒和数据统计_自动邮件提醒_04

运行

既然是提醒,当然得是自动的才会有意义,故将上面包含medicine_cant_stop和medicine_purchase_notice两个方法的py文件(medicine_cant_stop.py)放入Linux云服务器或者装有python环境的Windows电脑中。

Case1:若是Linux云服务器,则设置crontab定时任务每天执行medicine_cant_stop.py即可

Case2:若是Windows电脑,则添加计划任务每天执行medicine_cant_stop.py

当然,基础买药数据excel文件也得放入与medicine_cant_stop.py相同的文件目录下,若有新买药,也需要手动更新数据。