CS学生学期项目:程序时长追踪应用开发技术咨询
Hey Alex, great project idea—building a program usage time tracker is a practical way to dive into system APIs, data persistence, and UI development. Let’s break down how to approach this step by step, starting with the basics you can tackle right now.
First, choose tools that align with what you already know (or want to learn):
- Python + PyQt/Tkinter: Perfect for beginners. Python has great libraries for system process access, and PyQt/Tkinter lets you build a basic GUI without too much overhead.
- Electron: If you know JavaScript/TypeScript, Electron lets you build cross-platform desktop apps with web tech (HTML/CSS/JS). You’ll still need to use system-specific APIs via Node.js modules.
- Native Languages: For more control, use C#/.NET (Windows), Swift (macOS), or GTK (Linux)—but this has a steeper learning curve if you’re new to native development.
For starters, I’d recommend Python—it’s easy to prototype with, and there are tons of libraries to handle the heavy lifting.
Let’s split your app’s requirements into manageable chunks, starting with the most critical functionality.
Track Program Usage Duration
This is the backbone of your app. The goal is to periodically check which program is active, then accumulate its usage time.
How to Get Active Programs
Different OSes require different approaches:
- Windows: Use the
pywin32library to call Windows APIs likeGetForegroundWindow()to get the active window, then map it to a process. - macOS: Use
pyobjcto interact with AppKit’sNSWorkspaceclass, which lets you fetch the currently active application. - Linux: Use
wmctrlorxpropcommand-line tools (call them via Python’ssubprocess), or use thepsutillibrary for cross-platform process listing.
Basic Tracking Logic (Python Example)
Here’s a simplified script to get you started—this samples the active process every 10 seconds and accumulates time:
import psutil import time from datetime import datetime # Store cumulative time per program tracking_data = {} current_process = None session_start_time = time.time() def get_active_process_name(): # Simplified example (adjust for your OS) # For Windows, replace with pywin32 logic to get foreground window's process # For macOS, use pyobjc's NSWorkspace for proc in psutil.process_iter(['name', 'pid']): # This is a stand-in—you'll need better logic to find the active process if proc.name() == "Code.exe": # Example: VS Code return proc.name() # Fallback to current process (not ideal, but works for testing) return psutil.Process().name() while True: active_proc = get_active_process_name() if active_proc != current_process: # Calculate elapsed time for the previous process if current_process is not None: elapsed = time.time() - session_start_time tracking_data[current_process] = tracking_data.get(current_process, 0) + elapsed # Reset for the new process current_process = active_proc session_start_time = time.time() # Print progress for testing print(f"Tracking: {current_process} | Current Data: {tracking_data}") time.sleep(10) # Sample every 10 seconds
Key Notes:
- Permissions: On macOS, you’ll need to grant your app "Accessibility" permissions to read active windows. On Windows, no special permissions are usually needed.
- Performance: Don’t sample more often than 5-30 seconds—frequent checks will waste system resources.
Generate Productive/Distractive Time Reports
To build this, first let users categorize programs (e.g., "VS Code = productive", "Steam = distracting"). Then aggregate the tracked time by category.
Step 1: Let Users Define Categories
Create a simple config file (JSON) where users can map program names to categories:
{ "productive": ["Code.exe", "PyCharm.exe", "chrome.exe"], "distractive": ["Steam.exe", "TikTok.exe", "Discord.exe"] }
Step 2: Calculate & Display Totals
Add logic to sum time by category and format it into a readable report:
import json # Load category config with open("categories.json", "r") as f: categories = json.load(f) def calculate_category_totals(tracking_data): totals = {"productive": 0, "distractive": 0, "unclassified": 0} for proc, duration in tracking_data.items(): if proc in categories["productive"]: totals["productive"] += duration elif proc in categories["distractive"]: totals["distractive"] += duration else: totals["unclassified"] += duration return totals def format_seconds(seconds): hours = int(seconds // 3600) minutes = int((seconds % 3600) // 60) return f"{hours}h {minutes}m" # Usage example category_totals = calculate_category_totals(tracking_data) print(f"Productive Time: {format_seconds(category_totals['productive'])}") print(f"Distractive Time: {format_seconds(category_totals['distractive'])}") print(f"Unclassified Time: {format_seconds(category_totals['unclassified'])}")
You can take this further by adding charts (use matplotlib or plotly to generate pie charts or bar graphs for the report).
Track Task Completion Durations
For this, you’ll need to let users create tasks (e.g., "Finish Algorithm Homework") and link them to program usage or manual start/stop times.
Data Storage with SQLite
Use SQLite (lightweight, file-based database) to store task data. Here’s a basic table schema:
CREATE TABLE tasks ( id INTEGER PRIMARY KEY AUTOINCREMENT, task_name TEXT NOT NULL, start_time DATETIME, end_time DATETIME, total_duration REAL, associated_programs TEXT # Comma-separated list of programs linked to the task );
Basic Task Tracking Logic
Add functions to start/stop tasks and calculate their duration:
import sqlite3 from datetime import datetime def init_db(): conn = sqlite3.connect("tasks.db") cursor = conn.cursor() cursor.execute(""" CREATE TABLE IF NOT EXISTS tasks ( id INTEGER PRIMARY KEY AUTOINCREMENT, task_name TEXT NOT NULL, start_time DATETIME, end_time DATETIME, total_duration REAL, associated_programs TEXT ) """) conn.commit() conn.close() def start_task(task_name, associated_programs): conn = sqlite3.connect("tasks.db") cursor = conn.cursor() start_time = datetime.now().isoformat() cursor.execute(""" INSERT INTO tasks (task_name, start_time, associated_programs) VALUES (?, ?, ?) """, (task_name, start_time, associated_programs)) conn.commit() conn.close() return cursor.lastrowid def stop_task(task_id): conn = sqlite3.connect("tasks.db") cursor = conn.cursor() end_time = datetime.now().isoformat() cursor.execute(""" UPDATE tasks SET end_time = ? WHERE id = ? """, (end_time, task_id)) # Calculate duration cursor.execute(""" SELECT start_time FROM tasks WHERE id = ? """, (task_id,)) start_time = datetime.fromisoformat(cursor.fetchone()[0]) duration = (datetime.now() - start_time).total_seconds() cursor.execute(""" UPDATE tasks SET total_duration = ? WHERE id = ? """, (duration, task_id)) conn.commit() conn.close()
Don’t try to build everything at once—start with an MVP (Minimum Viable Product):
- First: Get the basic program tracking working in a command-line script. Make sure it correctly accumulates time for active programs.
- Next: Add the category-based reporting. Let users edit a JSON config file to categorize programs, then generate a text report.
- Finally: Build a simple GUI to let users manage categories, start/stop tasks, and view visual reports.
- Data Persistence: Save tracking data to a JSON file or SQLite database so it doesn’t get lost when the app closes.
- Background Running: On desktop, you’ll want the app to run in the system tray (use
pystrayfor Python, or Electron’s tray API). - Edge Cases: Handle cases like the computer going to sleep (pause tracking) or multiple instances of the same program running.
内容的提问来源于stack exchange,提问作者Alex Fedosenko

