文章目录
初衷设计1.实现锁屏2.实现计时秒表3.重新分析需求。4.输入时间5.集成测试6.打包成exe文件debug和优化exe循环锁屏占用资源优化最新代码闲谈锁屏木马初衷
突发奇想写定时锁屏软件,是想限制连续专注时间,做到劳逸结合。最好是每45分钟休息一下,读篇文章/散个步/聊聊天。
操作系统Win10,
语言版本Python3.7.6
开发环境Pycharm
设计
1.实现锁屏
代码:
# -*- coding: UTF-8 -*-from ctypes import *user32 = windll.LoadLibrary('user32.dll')user32.LockWorkStation()
测试效果:运行.py文件,系统会直接进入锁屏状态,需要输入锁屏密码来解锁。
参考:《用python写个一键锁屏的小脚本》,地址/md/?articleId=112380986
2.实现计时秒表
要求:
计时可见。
通过GUI(图形用户界面)进行操作。
计算时间差:
time.time()返回当前时间的时间戳。
tkinter库:
tkinter是一个使用Python语言构建的GUI工具包。允许采用GUI的方式执行你的Python脚本。
英文教程地址:
https://python-textbok.readthedocs.io/en/1.0/Introduction_to_GUI_Programming.html介绍的部分原文:
事件的监听:Anything that happens in a user interface isan event.
窗口的组件:GUI elements, such asbuttons,menusand various kinds ofentry fieldsanddisplay areas.
We call these elementswidgets.
窗口的树型结构:We are going to constructa tree of widgetsfor our GUI – each widget will have a parent widget, all the way up to the root window of our application.
Python中文版官方文档:
tkinter教程地址,/docs/zh/python/3.7.2rc1/all/library-tk.html。(感谢该项目的创建者和维护者)
(2)文档可以慢读,程序可以先写
测试程序:
import tkinterimport timestar = time.time()def gettime():elap = time.time() - star # 获取时间差hours = int(elap / 3600)minutes = int(elap / 60 - hours * 60.0)seconds = int(elap - minutes * 60.0)var.set('%02d:%02d:%02d' % (hours, minutes, seconds))root.after(1, gettime) # 每隔1ms调用函数自身获取时间root = tkinter.Tk()root.title('电子时钟')var = tkinter.StringVar()lb = tkinter.Label(root, textvariable=var, fg='orange', font=("微软雅黑", 100)) # 设置字体大小颜色lb.pack()gettime()root.mainloop()
测试效果:
使用到的tkinter内容:
tk = tkinter.TK()# 创建一个窗口的实例对象tk.title()# 设置窗口标题tkinter.Stringvar()# 窗口变量lb = tkinter.Label(text="", fg="", bg="")# 窗口标签,包含窗口变量lb.pack()# 一种理解是绑定事件tk.mainloop()# 进入事件循环,保持监听事件
3.重新分析需求。
实现了计时器、锁屏的基本功能,接下来重新分析需求。
分析需求:
需要输入时间吗,或采用定长时间锁屏?定长。
突然想到输入时间,可以有包时的效果,更改需求为输入时间。
需要暂停或终止计时吗?不需要。
4.输入时间
测试代码:
def get_text():global setimesetime = int(entry1.get())root2.destroy()def time_set():global entry1, root2, setimeroot2 = tkinter.Tk()root2.title('设置时间')root2.geometry('300x300')lb = tkinter.Label(root2, text="输入锁屏Minutes:")lb.pack()entry1 = tkinter.Entry(root2)entry1.pack()anniu = tkinter.Button(root2, text='GO', command=get_text)anniu.pack()root2.mainloop()
参考:《python:从输入框中读取》,地址/hzliyaya/article/details/9321493?utm_source=blogxgwz0
5.集成测试
测试代码(较单元测试略有修改):
# -*- coding: UTF-8 -*-import tkinterimport timefrom ctypes import *def gettime():elap = time.time() - star # 获取时间差hours = int(elap / 3600)minutes = int(elap / 60 - hours * 60.0)seconds = int(elap - minutes * 60.0)var.set('%02d:%02d:%02d' % (hours, minutes, seconds))root.after(1, gettime) # 每隔1ms调用函数自身获取时间if minutes > setime-1:user32 = windll.LoadLibrary('user32.dll')user32.LockWorkStation()exit(0)def timing(): # 计时器global root, var, starstar = time.time()root = tkinter.Tk()root.title('计时器')var = tkinter.StringVar()lb = tkinter.Label(root, textvariable=var, fg='orange', font=("微软雅黑", 100)) # 设置字体大小颜色lb.pack()gettime()root.mainloop()def get_text():global setimesetime = int(entry1.get())root2.destroy()def time_set():global entry1, root2, setimeroot2 = tkinter.Tk()root2.title('设置时间')root2.geometry('300x300')lb = tkinter.Label(root2, text="输入锁屏Minutes:")lb.pack()entry1 = tkinter.Entry(root2)entry1.pack()anniu = tkinter.Button(root2, text='GO', command=get_text)anniu.pack()root2.mainloop()if __name__ == '__main__':time_set()timing()
测试图:
输入0会立即锁屏
输入2则关闭第一个窗口,打开第二个窗口开始计时:
6.打包成exe文件
命令行执行:pyinstaller -w lock.py
在打包生成的dist目录中找到lock.exe,即为最终exe程序。
运行lock.exe,如图:
debug和优化
exe循环锁屏
遇到一个奇怪的情况,打包脚本生成的exe文件会循环锁屏。做了一个对比测试,如下图。
蛮难受的问题,临时/最终解决方式:直接运行py脚本。
占用资源优化
发现问题,是因为开启脚本电脑风扇就会启动,说明CPU利用率提高。
对比CPU利用率如下,观察进程发现CPU占用率在20%初头。
开启py脚本前,CPU和磁盘文件利用率基本都在10%以内。
开启py脚本后,CPU利用率在20%-30%
原因分析:root.after(1, gettime)
,每隔1ms都会获取一次时间。
解决方式:每隔1秒获取一次时间,也就是1000毫秒。
(一分钟获取一次,计时器看上去就不是实时的,体验不好)
root.after(1000, gettime)
效果:进程的CPU占用率在1%以内。
最新代码
# -*- coding: UTF-8 -*-import tkinterimport timefrom ctypes import *def gettime():elap = time.time() - star # 获取时间差hours = int(elap / 3600)minutes = int(elap / 60 - hours * 60.0)seconds = int(elap - minutes * 60.0)var.set('%02d:%02d:%02d' % (hours, minutes, seconds))root.after(1000, gettime) # 每隔1ms调用函数自身获取时间if minutes > setime-1:user32 = windll.LoadLibrary('user32.dll')user32.LockWorkStation()exit(0)def timing(): # 计时器global root, var, starstar = time.time()root = tkinter.Tk()root.title('计时器')var = tkinter.StringVar()lb = tkinter.Label(root, textvariable=var, fg='orange', font=("微软雅黑", 100)) # 设置字体大小颜色lb.pack()gettime()root.mainloop()def get_text():global setimesetime = int(entry1.get())root2.destroy()def time_set():global entry1, root2, setimeroot2 = tkinter.Tk()root2.title('设置时间')root2.geometry('300x300')lb = tkinter.Label(root2, text="输入锁屏Minutes:")lb.pack()entry1 = tkinter.Entry(root2)entry1.pack()anniu = tkinter.Button(root2, text='GO', command=get_text)anniu.pack()root2.mainloop()if __name__ == '__main__':time_set()timing()
闲谈
锁屏木马
编写锁屏程序的过程中,由于没有做好循环控制,碰到了0秒循环锁屏的情况。幸好CSDN会自动保存草稿,心态被救。
循环锁屏的情况是通过重启电脑的手段解决的,如果把该锁屏程序设置为开机自启呢?联想冰河木马修改注册表、自启动的方式,以及最近的incaseformat蠕虫病毒,这个锁屏程序似乎也可以写成一个木马。
想象锁屏木马的效果,开机即无限锁屏。
如果像冰河木马一样修改注册表,单纯删除文件是无法清除的。
可以通过U盘、网页flash等方式传播这个恶作剧小程序。
最简单直接的解决方式,就是重装操作系统。
如果觉得《使用Python写一个定时锁屏软件》对你有帮助,请点赞、收藏,并留下你的观点哦!