如何编写支持循环收集数据、校验、多字典存储及加密的Python程序
问题解答
1. 多字典存储方案合理性
- 将多个用户信息字典存入列表是完全合理的实现方案。列表作为有序可变容器,支持动态追加、遍历读取、批量处理,完美适配你先采集多份数据再统一加密的需求,后续扩展查询、导出功能也很方便。
2. 存入字典前的有效性校验实现
- 校验逻辑要遵循「单字段闭环校验」原则:每个字段的输入函数内部完成所有规则校验、异常捕获、重试逻辑,只有输入符合规则才返回合法值,从根源上避免非法值存入字典。你现有代码的校验逻辑存在多处漏洞:比如姓名只要包含空格/横杠就通过、邮箱仅校验存在@和.、地址校验不通过会返回None,都需要调整。
优化后完整实现代码
import base64 from datetime import datetime from cryptography.fernet import Fernet import pickle # 生成加密密钥,实际使用时可将密钥持久化存储,避免重启后无法解密 ENCRYPT_KEY = Fernet.generate_key() fernet = Fernet(ENCRYPT_KEY) def get_valid_username(): while True: name = input("Enter Name:").strip() # 校验规则:非空,仅允许包含中文、英文、空格、横杠 if not name: print("姓名不能为空,请重新输入") continue all_allowed = all(c.isalnum() or c in (' ', '-') for c in name) if all_allowed: return name print("姓名仅允许包含字母、数字、空格、横杠,请重新输入") def get_valid_dob(): while True: dob = input("Enter your date of birth - MM/DD/XXXX:").strip() try: date = datetime.strptime(dob, '%m/%d/%Y') # 可扩展校验出生日期不能晚于当前日期 if date > datetime.now(): print("出生日期不能晚于当前日期,请重新输入") continue print(f'校验通过:{date.month}/{date.day}/{date.year}') return dob except ValueError: print("日期格式错误,请按照MM/DD/XXXX格式重新输入") def get_valid_address(): while True: address = input("Enter The Street Address:").strip() if not address: print("地址不能为空,请重新输入") continue # 可根据需求扩展地址规则校验 return address def get_valid_email(): while True: email = input("Enter Email Address:").strip() # 简单校验包含@和.,且@不在首尾,@后有. if '@' not in email or '.' not in email.split('@')[-1] or email.startswith('@') or email.endswith('@'): print("邮箱格式错误,请重新输入") continue return email def collect_single_user(): return { 'Name': get_valid_username(), 'Date of Birth': get_valid_dob(), 'Street Address': get_valid_address(), 'Email Address': get_valid_email() } if __name__ == "__main__": user_list = [] # 循环采集用户信息 while True: print("\n=== 开始采集第{}位用户信息 ===".format(len(user_list)+1)) user_info = collect_single_user() user_list.append(user_info) # 判断是否继续采集 is_continue = input("是否继续采集下一位用户?(y/n,默认y):").strip().lower() if is_continue == 'n': break # 统一加密:先序列化列表,再用Fernet加密 serialized_data = pickle.dumps(user_list) encrypted_data = fernet.encrypt(serialized_data) print("\n加密后的数据:", encrypted_data) # 解密验证 decrypted_data = fernet.decrypt(encrypted_data) decrypted_user_list = pickle.loads(decrypted_data) print("\n解密后的用户列表:", decrypted_user_list)
代码调整说明
- 修复了所有字段的校验逻辑,每个输入函数内部完成重试,保证返回值合法
- 实现了循环采集功能,用户可主动终止采集流程
- 替换了原有的base64编码(非加密)为Fernet对称加密,符合加密需求
- 移除了风险极高的
eval方法,改用pickle做序列化/反序列化,安全性更高 - 所有用户信息字典存入
user_list列表,批量处理逻辑清晰
内容的提问来源于stack exchange,提问作者Terr McCoy
相关产品推荐
相关产品推荐

