20242212 2024-2025-2 《Python程序设计》实验四报告

20242212 2024-2025-2 《Python程序设计》实验一报告

课程:《Python程序设计》
班级: 2422
姓名: 王士霖
学号:20242212
实验教师:王志强
实验日期:2025年6月8日
必修/选修: 公选课
一.实验课题
因为自身的管理能力较差,所以想做一个软件来记录自己使用的各个软件的使用时长,并在时长过长时提醒自己关闭软件。
二.实验过程
1.准备工作
Python 环境中安装 psutil 模块
pip install psutil

2.完整代码实现
第一版:

{
    "check_interval": 10,
    "max_usage_time": {
        "chrome.exe": 3600,
        "firefox.exe": 3600,
        "msedge.exe": 3600,
        "notepad.exe": 1800
    },
    "website_limits": {
        "www.example.com": 1800,
        "news.example.com": 1200
    },
    "reminder_threshold": 2700,
    "website_reminder_threshold": 900,
    "reminder_message": "您使用{app}的时间已过长,请适当休息!",
    "website_reminder_message": "您浏览{website}的时间已过长,请适当休息!",
    "flush_interval": 60
}
import time
import subprocess
import platform
import json
import os
from datetime import datetime, timedelta
import psutil

class AppUsageTracker:
    def __init__(self, config_file='app_tracker_config.json'):
        self.config_file = config_file
        self.app_usage = {}  # 应用使用时间
        self.website_usage = {}  # 网站使用时间
        self.running = True
        self.config = self.load_config()
        self.browser_processes = ['chrome.exe', 'firefox.exe', 'msedge.exe']
        self.management_folder = "管理"
        self.current_log_file = None
        self.ensure_management_folder()
        self.update_log_file()

    def load_config(self):
        """加载配置文件,如果不存在则创建默认配置"""
        if os.path.exists(self.config_file):
            with open(self.config_file, 'r') as f:
                return json.load(f)
        else:
            default_config = {
                "check_interval": 10,  # 检查间隔(秒)
                "max_usage_time": {
                    "chrome.exe": 3600,  # Chrome最大使用时间(秒)
                    "firefox.exe": 3600,
                    "msedge.exe": 3600,
                    "notepad.exe": 1800
                },
                "website_limits": {
                    "www.example.com": 1800,  # 示例网站限制(秒)
                    "news.example.com": 1200
                },
                "reminder_threshold": 2700,  # 应用提醒阈值(秒)
                "website_reminder_threshold": 900,  # 网站提醒阈值(秒)
                "reminder_message": "您使用{app}的时间已过长,请适当休息!",
                "website_reminder_message": "您浏览{website}的时间已过长,请适当休息!",
            }
            self.save_config(default_config)
            return default_config

    def save_config(self, config):
        """保存配置文件"""
        with open(self.config_file, 'w') as f:
            json.dump(config, f, indent=4)

    def ensure_management_folder(self):
        """确保管理文件夹存在"""
        if not os.path.exists(self.management_folder):
            os.makedirs(self.management_folder)

    def get_current_date_string(self):
        """获取当前日期字符串(YYYY-MM-DD)"""
        return datetime.now().strftime("%Y-%m-%d")

    def update_log_file(self):
        """更新日志文件,如果到了新的一天则创建新文件"""
        current_date = self.get_current_date_string()
        log_file_name = os.path.join(self.management_folder, f"{current_date}.txt")
        
        # 如果文件改变了,关闭当前文件并创建新文件
        if self.current_log_file != log_file_name:
            if self.current_log_file:
                self.log("日志文件已更新")
            self.current_log_file = log_file_name
            self.log("开始记录新一天的使用数据")

    def get_seconds_until_midnight(self):
        """获取距离午夜(23:59:59)的秒数"""
        now = datetime.now()
        midnight = (now + timedelta(days=1)).replace(
            hour=0, minute=0, second=0, microsecond=0
        )
        return (midnight - now).total_seconds()

    def log(self, message):
        """记录消息到当前日志文件"""
        timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        log_entry = f"[{timestamp}] {message}\n"
        
        try:
            with open(self.current_log_file, 'a', encoding='utf-8') as f:
                f.write(log_entry)
        except Exception as e:
            print(f"写入日志时出错: {e}")

    def log_usage(self, app, duration, is_website=False):
        """记录应用或网站使用情况"""
        entry_type = "网站" if is_website else "应用"
        self.log(f"{entry_type}: {app} 使用了 {duration} 秒")

    def get_running_apps(self):
        """获取当前运行的应用程序"""
        if platform.system() == "Windows":
            try:
                output = subprocess.check_output("tasklist", shell=True).decode('cp850')
                lines = output.strip().split('\n')[3:]  # 跳过标题行
                apps = []
                for line in lines:
                    parts = line.strip().split()
                    if len(parts) > 0:
                        apps.append(parts[0])
                return apps
            except Exception as e:
                self.log(f"获取应用列表时出错: {e}")
                return []
        else:
            self.log("目前只支持Windows系统")
            return []

    def get_browser_urls(self):
        """获取浏览器当前打开的URL(实验性,可能不支持所有浏览器)"""
        urls = []
        for proc in psutil.process_iter(['name', 'cmdline']):
            try:
                if proc.info['name'] in self.browser_processes:
                    cmdline = proc.info['cmdline']
                    if cmdline:
                        for part in cmdline:
                            if 'http' in part:
                                # 简单提取URL
                                url = part
                                # 提取域名
                                domain = self.extract_domain(url)
                                if domain:
                                    urls.append(domain)
            except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess):
                pass
        return urls

    def extract_domain(self, url):
        """从URL中提取域名"""
        try:
            # 简单的域名提取逻辑
            if '//' in url:
                domain = url.split('//')[1].split('/')[0]
                # 移除端口和参数
                domain = domain.split(':')[0].split('?')[0]
                return domain
            return None
        except:
            return None

    def send_reminder(self, message):
        """发送提醒"""
        if platform.system() == "Windows":
            try:
                # 使用Windows消息框提醒
                subprocess.Popen(f'powershell -Command "Add-Type -AssemblyName System.Windows.Forms; '
                               f'[System.Windows.Forms.MessageBox]::Show(\\"{message}\\", \\"使用时间提醒\\", '
                               f'[System.Windows.Forms.MessageBoxButtons]::OK, '
                               f'[System.Windows.Forms.MessageBoxIcon]::Information)"', shell=True)
                self.log(f"发送提醒: {message}")
            except Exception as e:
                self.log(f"发送提醒时出错: {e}")

    def close_app(self, app):
        """关闭应用程序"""
        if platform.system() == "Windows":
            try:
                subprocess.run(f"taskkill /F /IM {app}", shell=True, check=True)
                self.log(f"已关闭应用: {app}")
                if app in self.app_usage:
                    self.log_usage(app, self.app_usage[app])
                    self.app_usage[app] = 0  # 重置使用时间
            except subprocess.CalledProcessError as e:
                self.log(f"关闭应用 {app} 失败: {e}")
            except Exception as e:
                self.log(f"关闭应用时出错: {e}")

    def update_usage_time(self, apps):
        """更新应用和网站使用时间"""
        # 更新应用使用时间
        for app in apps:
            if app in self.config["max_usage_time"]:
                if app in self.app_usage:
                    self.app_usage[app] += self.config["check_interval"]
                else:
                    self.app_usage[app] = self.config["check_interval"]

                # 检查是否超过提醒阈值
                if (self.app_usage[app] >= self.config["reminder_threshold"] and 
                    self.app_usage[app] % self.config["check_interval"] == 0):
                    message = self.config["reminder_message"].format(app=app)
                    self.send_reminder(message)

                # 检查是否超过最大使用时间
                if self.app_usage[app] >= self.config["max_usage_time"][app]:
                    self.close_app(app)

        # 更新网站使用时间
        if any(browser in apps for browser in self.browser_processes):
            urls = self.get_browser_urls()
            for url in urls:
                if url in self.config["website_limits"]:
                    if url in self.website_usage:
                        self.website_usage[url] += self.config["check_interval"]
                    else:
                        self.website_usage[url] = self.config["check_interval"]

                    # 检查是否超过网站提醒阈值
                    if (self.website_usage[url] >= self.config["website_reminder_threshold"] and 
                        self.website_usage[url] % self.config["check_interval"] == 0):
                        message = self.config["website_reminder_message"].format(website=url)
                        self.send_reminder(message)

                    # 检查是否超过网站最大使用时间
                    if self.website_usage[url] >= self.config["website_limits"][url]:
                        # 关闭浏览器
                        for browser in self.browser_processes:
                            if browser in apps:
                                self.close_app(browser)
                        # 记录所有网站使用时间
                        for site, duration in self.website_usage.items():
                            self.log_usage(site, duration, is_website=True)
                        self.website_usage = {}  # 重置所有网站使用时间

    def check_midnight_reset(self):
        """检查是否到了午夜,需要重置日志文件"""
        current_time = datetime.now()
        if current_time.hour == 23 and current_time.minute == 59 and current_time.second >= 50:
            # 等待到午夜
            time.sleep(10)
            self.update_log_file()
            # 记录所有应用和网站使用时间
            for app, duration in self.app_usage.items():
                self.log_usage(app, duration)
            for site, duration in self.website_usage.items():
                self.log_usage(site, duration, is_website=True)
            # 重置所有使用时间
            self.app_usage = {}
            self.website_usage = {}
            self.log("已重置所有使用时间,开始新的一天记录")

    def run(self):
        """运行应用监控程序"""
        self.log("应用使用时间监控程序已启动...")
        self.log(f"监控应用: {list(self.config['max_usage_time'].keys())}")
        self.log(f"监控网站: {list(self.config['website_limits'].keys())}")
        
        try:
            while self.running:
                self.update_log_file()
                self.check_midnight_reset()
                apps = self.get_running_apps()
                self.update_usage_time(apps)
                time.sleep(self.config["check_interval"])
        except KeyboardInterrupt:
            self.log("\n程序已停止")
        except Exception as e:
            self.log(f"程序运行出错: {e}")
        finally:
            # 保存当前使用数据
            self.save_config(self.config)
            # 记录所有应用和网站使用时间
            for app, duration in self.app_usage.items():
                self.log_usage(app, duration)
            for site, duration in self.website_usage.items():
                self.log_usage(site, duration, is_website=True)

if __name__ == "__main__":
    tracker = AppUsageTracker()
    tracker.run()    

第二版:将输出文件改为实时运行且增加使用网站和软件超过一个小时就强行停止

添加了 实时使用数据.txt 文件,每 60 秒(可配置)更新一次
包含当前所有监控应用和网站的累计使用时间
格式清晰,便于实时查看使用状态
添加了 flush_usage_data() 方法,专门处理数据刷新
在关键时间点(如应用关闭、午夜重置、定时检查)都会刷新数据
通过 flush_interval 配置项可调整刷新频率
保留原有日志功能,同时提供实时数据文件
所有操作都有详细时间戳记录
程序异常退出时也会保存当前数据
修改 app_tracker_config.json 中的 max_usage_time 和 website_limits

第三版:在星期六和星期天只用记录时间不用强行关闭

添加 is_weekend() 方法检测当前是否为周末
在 close_app() 中添加周末判断,周末不执行关闭操作
更新日志和实时数据文件,显示当前模式状态
在配置中添加 weekend_mode 部分
可自定义启用 / 禁用周末模式
可配置哪些天属于周末(默认周六和周日)
日志文件中明确标识当前模式
实时数据文件显示当前是周末模式还是工作日模式
周末达到使用上限时记录日志但不关闭应用

最终版

{
    "check_interval": 10,
    "max_usage_time": {
        "chrome.exe": 3600,
        "firefox.exe": 3600,
        "msedge.exe": 3600,
        "notepad.exe": 3600
    },
    "website_limits": {
        "*": 3600,
        "www.example.com": 3600,
        "news.example.com": 3600
    },
    "reminder_threshold": 3000,
    "website_reminder_threshold": 3000,
    "reminder_message": "\u60a8\u4f7f\u7528{app}\u7684\u65f6\u95f4\u5df2\u63a5\u8fd11\u5c0f\u65f6\uff0c\u5373\u5c06\u81ea\u52a8\u5173\u95ed\uff01",
    "website_reminder_message": "\u60a8\u6d4f\u89c8{website}\u7684\u65f6\u95f4\u5df2\u63a5\u8fd11\u5c0f\u65f6\uff0c\u5373\u5c06\u81ea\u52a8\u5173\u95ed\uff01",
    "flush_interval": 60,
    "weekend_mode": {
        "enabled": true,
        "allowed_days": [
            5,
            6
        ],
        "weekend_message": "\u5468\u672b\u4ec5\u8bb0\u5f55\u4f7f\u7528\u65f6\u95f4\uff0c\u4e0d\u4f1a\u5f3a\u5236\u5173\u95ed\u5e94\u7528"
    }
}
import time
import subprocess
import platform
import json
import os
from datetime import datetime, timedelta
import psutil

class AppUsageTracker:
    def __init__(self, config_file='app_tracker_config.json'):
        self.config_file = config_file
        self.app_usage = {}  # 应用使用时间
        self.website_usage = {}  # 网站使用时间
        self.running = True
        self.config = self.load_config()
        self.browser_processes = ['chrome.exe', 'firefox.exe', 'msedge.exe']
        self.management_folder = "管理"
        self.current_log_file = None
        self.ensure_management_folder()
        self.update_log_file()
        self.last_flush_time = datetime.now()  # 上次刷新文件时间

    def load_config(self):
        """加载配置文件,如果不存在则创建默认配置"""
        if os.path.exists(self.config_file):
            # 以 UTF-8 编码打开文件,解决中文乱码问题
            with open(self.config_file, 'r', encoding='utf-8') as f:
                return json.load(f)
        else:
            default_config = {
                "check_interval": 10,  # 检查间隔(秒)
                "max_usage_time": {
                    "chrome.exe": 3600,  # Chrome最大使用时间(秒)
                    "firefox.exe": 3600,
                    "msedge.exe": 3600,
                    "notepad.exe": 3600,
                },
                "website_limits": {
                    "*": 3600,  # 所有网站默认1小时限制
                },
                "reminder_threshold": 3000,  # 应用提醒阈值(50分钟)
                "website_reminder_threshold": 3000,  # 网站提醒阈值(50分钟)
                "reminder_message": "您使用{app}的时间已接近1小时,即将自动关闭!",
                "website_reminder_message": "您浏览{website}的时间已接近1小时,即将自动关闭!",
                "flush_interval": 60,  # 数据刷新到文件的间隔(秒)
                "weekend_mode": {
                    "enabled": True,  # 是否启用周末模式
                    "allowed_days": [5, 6],  # 周六(5)和周日(6)
                    "weekend_message": "周末仅记录使用时间,不会强制关闭应用"
                }
            }
            self.save_config(default_config)
            return default_config

    def is_weekend(self):
        """检查当前是否为周末"""
        if not self.config["weekend_mode"]["enabled"]:
            return False
        current_day = datetime.now().weekday()
        return current_day in self.config["weekend_mode"]["allowed_days"]

    def save_config(self, config):
        """保存配置文件"""
        with open(self.config_file, 'w', encoding='utf-8') as f:
            json.dump(config, f, indent=4)

    def ensure_management_folder(self):
        """确保管理文件夹存在"""
        if not os.path.exists(self.management_folder):
            os.makedirs(self.management_folder)

    @staticmethod
    def get_current_date_string():
        """获取当前日期字符串(YYYY-MM-DD)"""
        return datetime.now().strftime("%Y-%m-%d")

    def update_log_file(self):
        """更新日志文件,如果到了新的一天则创建新文件"""
        current_date = self.get_current_date_string()
        log_file_name = os.path.join(self.management_folder, f"{current_date}.txt")
        
        # 如果文件改变了,关闭当前文件并创建新文件
        if self.current_log_file != log_file_name:
            if self.current_log_file:
                self.log("日志文件已更新")
            self.current_log_file = log_file_name
            is_weekend = self.is_weekend()
            weekend_status = "周末模式:仅记录使用时间" if is_weekend else "工作日模式:超时将强制关闭"
            self.log(f"开始记录新一天的使用数据 - {weekend_status}")
            self.flush_usage_data()  # 切换文件时刷新数据

    @staticmethod
    def get_seconds_until_midnight():
        """获取距离午夜(23:59:59)的秒数"""
        now = datetime.now()
        midnight = (now + timedelta(days=1)).replace(
            hour=0, minute=0, second=0, microsecond=0
        )
        return (midnight - now).total_seconds()

    def log(self, message):
        """记录消息到当前日志文件"""
        timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        log_entry = f"[{timestamp}] {message}\n"
        
        try:
            with open(self.current_log_file, 'a', encoding='utf-8') as f:
                f.write(log_entry)
        except Exception as e:
            print(f"写入日志时出错: {e}")

    def flush_usage_data(self):
        """将当前使用数据刷新到文件"""
        timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        data_file = os.path.join(self.management_folder, "实时使用数据.txt")
        
        with open(data_file, 'w', encoding='utf-8') as f:
            f.write(f"数据更新时间: {timestamp}\n")
            f.write(f"当前模式: {'周末模式(仅记录)' if self.is_weekend() else '工作日模式(超时关闭)'}\n\n")
            f.write("=== 应用使用时间 ===\n")
            for app, seconds in self.app_usage.items():
                if seconds > 0:
                    f.write(f"{app}: {seconds} 秒 ({seconds/3600:.2f} 小时)\n")
            
            f.write("\n=== 网站使用时间 ===\n")
            for site, seconds in self.website_usage.items():
                if seconds > 0:
                    f.write(f"{site}: {seconds} 秒 ({seconds/3600:.2f} 小时)\n")

    def log_usage(self, app, duration, is_website=False):
        """记录应用或网站使用情况"""
        entry_type = "网站" if is_website else "应用"
        self.log(f"{entry_type}: {app} 使用了 {duration} 秒 ({duration/3600:.2f} 小时)")

    def get_running_apps(self):
        """获取当前运行的应用程序"""
        if platform.system() == "Windows":
            try:
                output = subprocess.check_output("tasklist", shell=True).decode('cp850')
                lines = output.strip().split('\n')[3:]  # 跳过标题行
                apps = []
                for line in lines:
                    parts = line.strip().split()
                    if len(parts) > 0:
                        apps.append(parts[0])
                return apps
            except Exception as e:
                self.log(f"获取应用列表时出错: {e}")
                return []
        else:
            self.log("目前只支持Windows系统")
            return []

    def get_browser_urls(self):
        """获取浏览器当前打开的URL(实验性,可能不支持所有浏览器)"""
        urls = []
        for proc in psutil.process_iter(['name', 'cmdline']):
            try:
                if proc.info['name'] in self.browser_processes:
                    cmdline = proc.info['cmdline']
                    if cmdline:
                        for part in cmdline:
                            if 'http' in part:
                                # 简单提取URL
                                url = part
                                # 提取域名
                                domain = self.extract_domain(url)
                                if domain:
                                    urls.append(domain)
            except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess):
                pass
        return urls

    @staticmethod
    def extract_domain(url):
        """从URL中提取域名"""
        try:
            # 简单的域名提取逻辑
            if '//' in url:
                domain = url.split('//')[1].split('/')[0]
                # 移除端口和参数
                domain = domain.split(':')[0].split('?')[0]
                return domain
            return None
        except:
            return None

    def send_reminder(self, message):
        """发送提醒"""
        if platform.system() == "Windows":
            try:
                # 使用Windows消息框提醒
                subprocess.Popen(f'powershell -Command "Add-Type -AssemblyName System.Windows.Forms; '
                               f'[System.Windows.Forms.MessageBox]::Show(\\"{message}\\", \\"使用时间提醒\\", '
                               f'[System.Windows.Forms.MessageBoxButtons]::OK, '
                               f'[System.Windows.Forms.MessageBoxIcon]::Warning)"', shell=True)
                self.log(f"发送提醒: {message}")
            except Exception as e:
                self.log(f"发送提醒时出错: {e}")

    def close_app(self, app):
        """关闭应用程序"""
        if self.is_weekend():
            self.log(f"周末模式: {app} 使用时间已达上限,但不会关闭")
            return
        
        if platform.system() == "Windows":
            try:
                subprocess.run(f"taskkill /F /IM {app}", shell=True, check=True)
                self.log(f"已强制关闭应用: {app}")
                if app in self.app_usage:
                    self.log_usage(app, self.app_usage[app])
                    self.app_usage[app] = 0  # 重置使用时间
                self.flush_usage_data()  # 关闭应用后刷新数据
            except subprocess.CalledProcessError as e:
                self.log(f"关闭应用 {app} 失败: {e}")
            except Exception as e:
                self.log(f"关闭应用时出错: {e}")

    def update_usage_time(self, apps):
        """更新应用和网站使用时间"""
        is_weekend = self.is_weekend()
        
        # 更新应用使用时间
        for app in apps:
            # 检查是否在监控列表中或是否为浏览器
            if app in self.config["max_usage_time"] or app in self.browser_processes:
                if app in self.app_usage:
                    self.app_usage[app] += self.config["check_interval"]
                else:
                    self.app_usage[app] = self.config["check_interval"]

                # 获取最大使用时间
                max_time = self.config["max_usage_time"].get(app, 3600)
                
                # 周末模式仅记录,不提醒和关闭
                if is_weekend:
                    continue

                # 检查是否超过提醒阈值
                if (self.app_usage[app] >= self.config["reminder_threshold"] and 
                    self.app_usage[app] % self.config["check_interval"] == 0):
                    message = self.config["reminder_message"].format(app=app)
                    self.send_reminder(message)

                # 检查是否超过最大使用时间
                if self.app_usage[app] >= max_time:
                    self.close_app(app)

        # 更新网站使用时间
        if any(browser in apps for browser in self.browser_processes):
            urls = self.get_browser_urls()
            for url in urls:
                # 检查是否在网站监控列表中或使用默认限制
                limit = self.config["website_limits"].get(url, 
                                           self.config["website_limits"].get('*', 3600))
                
                if url in self.website_usage:
                    self.website_usage[url] += self.config["check_interval"]
                else:
                    self.website_usage[url] = self.config["check_interval"]

                # 周末模式仅记录,不提醒和关闭
                if is_weekend:
                    continue

                # 检查是否超过网站提醒阈值
                if (self.website_usage[url] >= self.config["website_reminder_threshold"] and 
                    self.website_usage[url] % self.config["check_interval"] == 0):
                    message = self.config["website_reminder_message"].format(website=url)
                    self.send_reminder(message)

                # 检查是否超过网站最大使用时间
                if self.website_usage[url] >= limit:
                    # 关闭所有浏览器
                    for browser in self.browser_processes:
                        if browser in apps:
                            self.close_app(browser)
                    # 记录所有网站使用时间
                    for site, duration in self.website_usage.items():
                        self.log_usage(site, duration, is_website=True)
                    self.website_usage = {}  # 重置所有网站使用时间
                    self.flush_usage_data()  # 刷新数据

    def check_midnight_reset(self):
        """检查是否到了午夜,需要重置日志文件"""
        current_time = datetime.now()
        if current_time.hour == 23 and current_time.minute == 59 and current_time.second >= 50:
            # 等待到午夜
            time.sleep(10)
            self.update_log_file()
            # 记录所有应用和网站使用时间
            for app, duration in self.app_usage.items():
                self.log_usage(app, duration)
            for site, duration in self.website_usage.items():
                self.log_usage(site, duration, is_website=True)
            # 重置所有使用时间
            self.app_usage = {}
            self.website_usage = {}
            self.log("已重置所有使用时间,开始新的一天记录")
            self.flush_usage_data()  # 刷新数据

    def check_flush_interval(self):
        """检查是否到了刷新数据的时间"""
        now = datetime.now()
        if (now - self.last_flush_time).total_seconds() >= self.config["flush_interval"]:
            self.flush_usage_data()
            self.last_flush_time = now

    def run(self):
        """运行应用监控程序"""
        is_weekend = self.is_weekend()
        weekend_status = "周末模式:仅记录使用时间" if is_weekend else "工作日模式:超时将强制关闭"
        self.log(f"应用使用时间监控程序已启动 - {weekend_status}")
        self.log(f"监控应用: {list(self.config['max_usage_time'].keys())}")
        self.log(f"监控网站: {list(self.config['website_limits'].keys())}")
        self.flush_usage_data()  # 初始化数据文件
        
        try:
            while self.running:
                self.update_log_file()
                self.check_midnight_reset()
                self.check_flush_interval()  # 检查是否需要刷新数据
                apps = self.get_running_apps()
                self.update_usage_time(apps)
                time.sleep(self.config["check_interval"])
        except KeyboardInterrupt:
            self.log("\n程序已停止")
        except Exception as e:
            self.log(f"程序运行出错: {e}")
        finally:
            # 保存当前使用数据
            self.save_config(self.config)
            self.flush_usage_data()  # 程序结束时刷新数据
            # 记录所有应用和网站使用时间
            for app, duration in self.app_usage.items():
                self.log_usage(app, duration)
            for site, duration in self.website_usage.items():
                self.log_usage(site, duration, is_website=True)

if __name__ == "__main__":
    tracker = AppUsageTracker()
    tracker.run()

3.结果展示


4.设计

应用和网站检测算法
基于 Windows 系统的 tasklist 命令获取进程列表
通过 psutil 库解析浏览器进程命令行参数提取 URL
域名提取算法:从完整 URL 中解析出主域名部分
时间管理算法
使用字典结构维护应用和网站的累计使用时间
周期性检查(默认每 10 秒)更新使用时间
基于配置的阈值(提醒阈值和强制关闭阈值)触发相应操作
周末模式实现
通过 Python 的 datetime 模块获取当前星期几
根据配置的周末日期列表判断是否启用周末模式
在周末模式下改变程序行为(仅记录不关闭)

三. 实验过程中遇到的问题和解决过程
遇到了以下情况:
1.安装psutil时

Requirement already satisfied: psutil in c:\users\23036\appdata\local\programs\python\python313\lib\site-packages (7.0.0)
[notice] A new release of pip is available: 24.3.1 -> 25.1.1
[notice] To update, run: C:\Users\23036\AppData\Local\Programs\Python\Python313\python.exe -m pip install --upgrade pip

在通过以下步骤解决此问题

通过 IDE 界面安装 psutil(以常见的 PyCharm 为例,其他 IDE 操作类似)
打开 “管理软件包”:点击截图里的 “管理软件包...” 选项,这会打开对应 Python 解释器的包管理界面。
搜索 psutil:在包管理界面的搜索框中,输入 psutil 进行搜索。
安装 psutil:找到 psutil 后,点击 “安装” 按钮,IDE 会自动将 psutil 安装到当前选中的 Python 3.13 (python2) 环境中。

2.程序运行时
程序在读取配置文件时遇到了编码问题

F:\python2\venv\Scripts\python.exe F:\python2\jiankong.py
Traceback (most recent call last):
File "F:\python2\jiankong.py", line 341, in
tracker = AppUsageTracker()
File "F:\python2\jiankong.py", line 15, in init
self.config = self.load_config()
~~~~~~~~~~~~~~~~^^
File "F:\python2\jiankong.py", line 27, in load_config
return json.load(f)
~~~~~~~~~^^^
File "C:\Users\23036\AppData\Local\Programs\Python\Python313\Lib\json_init_.py", line 293, in load
return loads(fp.read(),
~~~~~~~^^
UnicodeDecodeError: 'gbk' codec can't decode byte 0xad in position 459: illegal multibyte sequence

通过以下代码解决

def load_config(self):
"""加载配置文件,如果不存在则创建默认配置"""
if os.path.exists(self.config_file):
# 以 UTF-8 编码打开文件
with open(self.config_file, 'r', encoding='utf-8') as f:
return json.load(f)

四.实验总结
通过正确使用AI,我们可以更好地管理自己,提高自己,助力自己成长
五.其他
感谢老师,感谢帮助我的同学,感谢豆包

全课报告
*知识总结是用AI生产的

1. 序列类型
列表(list):有序、可变序列,元素可不同,支持创建、访问、增删改、排序及推导式等操作。
元组(tuple):与列表类似但元素不可变。
字典(dictionary):无序、可变的键值对集合,通过键访问值,支持创建、遍历、元素操作。
集合(set):无序、可变的无重复元素集合,支持添加、删除及交并差集等操作。
2. 字符串与正则表达式
字符串操作:涵盖拼接(+)、重复(*)、截断、分割(split)、合并(join)、检索(count、find)、大小写转换(lower、upper)、去首尾字符(strip)及格式化(% 操作符、format 方法)等。
正则表达式:用于字符串模式匹配,由普通字符和元字符组成,通过 re 模块实现查找(match、search、findall)、替换(sub)和分割(split)等操作,可处理复杂格式匹配。
(二)Python 进阶主题
1. 函数
函数创建与调用:封装重复代码,提高复用性,需注意参数传递(实参、形参、默认参数、可变参数)和返回值。
匿名函数(lambda):无名称函数,适用于临时使用场景,格式为lambda [arg1, ...]: expression。
2. 面向对象程序设计
类与对象:类是对象的蓝图,包含属性和方法;对象是类的实例。
关键概念:
封装:通过_(保护)、__(私有)实现访问限制。
继承:子类继承父类属性和方法,可重写方法。
多态:同一操作作用于不同对象,产生不同结果。
特殊方法:如__init__(构造方法)、__str__(字符串表示)。
3. 模块与异常处理
模块:扩展名为.py的文件,提高代码重用性,通过import或from...import导入,可使用if __name__ == '__main__'区分模块直接运行与导入运行。
异常处理:通过try...except...finally捕获并处理运行时错误,可使用raise抛出异常、assert调试程序。
4. 文件与目录操作
文件操作:包括打开(open)、读写(read、write)和关闭(close),需注意文件模式(r、w、a等)。
目录操作:利用os和os.path模块实现目录相关功能,如os.walk遍历目录。
(三)Python 网络编程技术
1. Socket 技术
Socket 概念:套接字由 IP 地址和端口组成,是网络通信的关键接口,分为低级 Socket(访问底层 API)和高级 Socket(如 SocketServer 模块)。
Socket 类型:
TCP(SOCK_STREAM):面向连接,可靠。
UDP(SOCK_DGRAM):面向无连接,不可靠。
Socket 函数:
服务端:bind(绑定地址)、listen(监听)、accept(接受连接)。
客户端:connect(连接服务器)。
公共:recv(接收数据)、send(发送数据)。
2. 网络爬虫技术(补充)
基础原理:模拟浏览器行为获取网页信息,常用模块包括urllib、requests,解析库有BeautifulSoup、lxml。
反爬虫应对:处理请求头(headers)、设置代理、处理超时异常。

感想体会
通过学习,我对 Python 编程有了相对完整的完整认知。从最初对列表、字典等基础数据结构的理解,到面向对象编程中类与对象的抽象思维,再到网络编程中 Socket 通信的底层原理,知识体系逐渐体系化。非常感谢王哥的教导。本身我是一个计算机基础比较薄弱的学生,上学期的c语言甚至是补考过的。但是通过王哥的python课,我感觉又重拾了对计算机的兴趣。Python是一门博大的学问,也是我感觉来说对于我来说相当友好的一个学科。我会努力学习,提高自我。
建议
希望老师把上课的内容录成网课发在学习通中

posted @ 2025-06-10 20:22  wwwaaasssl  阅读(13)  评论(0)    收藏  举报