如何构建我的第一个 Python PET 应用程序(以及我学到的东西)
当我决定深入学习 Python 时,我知道仅仅阅读文档和编写代码片段是不够的。我需要一个实际的项目来将所学知识串联起来。于是,我决定构建一个 PET(Personal Expense Tracker,个人支出追踪器)应用程序。这不仅是一个经典的初学者项目,而且非常实用——谁不想更好地管理自己的财务呢?
在这篇文章中,我将分享我是如何从零开始构建这个 Python PET 应用程序的,以及在这个过程中我踩过的坑和学到的重要经验。你可以访问 www.ipipp.com 查看该项目的在线演示版本。
第一步:规划应用程序
在动手写代码之前,我花了一些时间规划 PET 的核心功能。对于一个初代产品,我决定保持简单:
添加支出:记录金额、类别和描述。
查看支出:列出所有的支出记录。
数据持久化:将数据保存到本地文件中,以便下次打开时数据不会丢失。
第二步:搭建项目结构
我决定采用 MVC(模型-视图-控制器)的设计模式来组织代码,即使这是一个小型命令行应用,良好的结构也能让代码更易维护。项目结构如下:
pet_app/ │ ├── models/ │ └── expense.py # 数据模型 ├── controllers/ │ └── tracker.py # 核心业务逻辑 ├── views/ │ └── cli.py # 命令行交互界面 └── main.py # 程序入口
第三步:编写核心逻辑(模型与控制器)
首先,我定义了 Expense 类来表示一笔支出,并在 PETTracker 中实现了添加、查看和保存数据的功能。
以下是 models/expense.py 的代码:
import datetime
class Expense:
def __init__(self, amount, category, description):
self.amount = amount
self.category = category
self.description = description
self.date = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
def __str__(self):
return f"[{self.date}] {self.category}: {self.description} - ¥{self.amount:.2f}"接下来是 controllers/tracker.py,负责管理这些支出对象并处理数据的读写:
import json
import os
from models.expense import Expense
class PETTracker:
def __init__(self, filename='pet_data.json'):
self.filename = filename
self.expenses = []
self.load_expenses()
def add_expense(self, amount, category, description):
expense = Expense(amount, category, description)
self.expenses.append(expense)
self.save_expenses()
print("支出添加成功!")
def view_expenses(self):
if not self.expenses:
print("暂无支出记录。")
return
for expense in self.expenses:
print(expense)
def save_expenses(self):
data = [
{'amount': e.amount, 'category': e.category, 'description': e.description, 'date': e.date}
for e in self.expenses
]
with open(self.filename, 'w', encoding='utf-8') as f:
json.dump(data, f, ensure_ascii=False, indent=4)
def load_expenses(self):
if os.path.exists(self.filename):
with open(self.filename, 'r', encoding='utf-8') as f:
data = json.load(f)
for item in data:
self.expenses.append(Expense(item['amount'], item['category'], item['description']))第四步:构建命令行交互界面(视图)
有了核心逻辑后,我需要一种方式与用户交互。我编写了一个简单的 CLI 循环,处理用户的输入并调用相应的控制器方法。
from controllers.tracker import PETTracker
def main():
tracker = PETTracker()
while True:
print("n--- PET (Personal Expense Tracker) ---")
print("1. 添加支出")
print("2. 查看支出")
print("3. 退出")
choice = input("请选择操作 (1-3): ")
if choice == '1':
try:
amount = float(input("输入金额: "))
category = input("输入分类 (如餐饮、交通): ")
description = input("输入描述: ")
tracker.add_expense(amount, category, description)
except ValueError:
print("错误:金额必须是数字!")
elif choice == '2':
tracker.view_expenses()
elif choice == '3':
print("感谢使用 PET,再见!")
break
else:
print("无效选择,请重试。")
if __name__ == "__main__":
main()我学到的东西
虽然这只是一个简单的应用程序,但在开发过程中我遇到了不少挑战,也收获了宝贵的经验:
1. 错误处理至关重要
在最初的版本中,如果用户在输入金额时输入了字母,程序会直接崩溃。我学会了使用 try-except 块来捕获 ValueError,从而提供更友好的错误提示而不是让程序崩溃。这是提升应用健壮性的第一步。
2. 数据持久化的细节
我最初使用纯文本文件存储数据,解析起来非常痛苦且容易出错。后来我转向了 JSON 格式,发现 Python 内置的 json 模块让数据的序列化和反序列化变得异常简单。同时,我也学会了在读取文件前使用 os.path.exists() 检查文件是否存在,以避免 FileNotFoundError。
3. 关注点分离让代码更清晰
将数据模型、业务逻辑和用户界面分离,让我在修改某一部分时不用担心破坏其他部分。例如,如果以后我想把 CLI 界面改成 Web 界面,我的模型和控制器代码几乎不需要改动。
4. 迭代开发是王道
不要试图一次性写出所有功能。我的第一个版本只能在内存中保存数据,第二个版本加入了 JSON 文件存储,第三个版本才完善了错误处理。一步一步来,每次只关注一个功能,这样不仅压力小,而且更容易定位 Bug。
总结
构建这个 Python PET 应用程序是一次极好的学习经历。它不仅巩固了我对 Python 基础语法的理解,还让我接触了面向对象编程、文件 I/O 和异常处理等核心概念。如果你也是 Python 初学者,我强烈建议你从构建一个属于自己的 PET 应用开始,你一定会从中受益匪浅!