python購物車升級版
- 2019 年 10 月 7 日
- 筆記
各文件內容
前言
功能架構等請參考前一篇博客,此篇博客為進階版的存代碼展示。

詳細文件內容
啟動文件
starts.py啟動文件
import os import sys BASE_DIR = os.path.dirname(os.path.dirname(__file__)) sys.path.append(BASE_DIR) from core import src if __name__ == '__main__': src.run()
配置文件
logging_dict.py日誌配置字典
import os # ************************************ 日誌配置字典 ************************************************** ''' -------------------------------------------- ------------* 需要自定義的配置 *------------- -------------------------------------------- ''' # 定義三種日誌輸出格式 開始 standard_format = '[%(asctime)s][%(threadName)s:%(thread)d][task_id:%(name)s][%(filename)s:%(lineno)d]' '[%(levelname)s][%(message)s]' # 其中name為getlogger指定的名字 simple_format = '[%(levelname)s][%(asctime)s][%(filename)s:%(lineno)d]%(message)s' # 定義日誌輸出格式 結束 # 定義日誌文件的存放目錄與文件名(一般視情況選擇下面的兩個即可) logfile_dir = os.path.dirname(os.path.dirname(__file__)) # log文件的目錄 (執行文件starts.py 在bin目錄下) # logfile_dir = os.path.abspath(__file__) # log文件的目錄 (執行文件starts.py 在項目根目錄下) # 拼上 log 文件夾 logfile_dir = os.path.join(logfile_dir, 'log') logfile_name = 'ATM_Shop_Cart.log' # log文件名 # 如果不存在定義的日誌目錄就創建一個 if not os.path.isdir(logfile_dir): os.mkdir(logfile_dir) # log文件的全路徑 logfile_path = os.path.join(logfile_dir, logfile_name) # 像日誌文件的最大限度、個數限制,日誌過濾等級等也可以在下面的對應地方限制 ''' -------------------------------------------- --------------* log配置字典 *--------------- -------------------------------------------- ''' # log配置字典 LOGGING_DIC = { 'version': 1, 'disable_existing_loggers': False, 'formatters': { 'standard': { 'format': standard_format }, 'simple': { 'format': simple_format }, }, 'filters': {}, # 一般用不到過濾,所以就空在這裡了 'handlers': { 'console': { 'level': 'DEBUG', 'class': 'logging.StreamHandler', # 打印到屏幕 'formatter': 'simple' }, # 打印到文件的日誌,收集info及以上的日誌 'default': { 'level': 'DEBUG', 'class': 'logging.handlers.RotatingFileHandler', # 保存到文件 'formatter': 'standard', 'filename': logfile_path, # 日誌文件 'maxBytes': 1024 * 1024 * 5, # 日誌大小上限 5M,超過5M就會換一個日誌文件繼續記錄 'backupCount': 5, # 日誌文件的數量上限 5個,超出會把最早的刪除掉再新建記錄日誌 'encoding': 'utf-8', # 日誌文件的編碼,再也不用擔心中文log亂碼了 }, }, 'loggers': { # logging.getLogger(__name__)拿到的logger配置 '': { 'handlers': ['default', 'console'], # 這裡把上面定義的兩個handler都加上,即log數據既寫入文件又打印到屏幕 # 'handlers': ['default'], # ------------- 正式上線的時候改成這個,取消控制台打印,節省資源 ------------- 'level': 'DEBUG', 'propagate': True, # 向上(更高level的logger)傳遞 }, }, }
settings.py配置文件
import os import sys BASE_DIR = os.path.dirname(os.path.dirname(__file__)) sys.path.append(BASE_DIR)
入口文件
src.py入口文件
from interface import user_interface from lib import common from interface import bank_interface from interface import shop_interface def register(): while True: username = input("請輸入用戶名>>>:").strip() if username == 'q': return False if user_interface.check_user_exits(username): print("該用戶已存在,請換一個試試!") continue pwd = input("請輸入密碼>>>:").strip() if pwd == 'q': return False repwd = input("請再次輸入密碼>>>:").strip() if pwd == 'q': return False if repwd != pwd: print("兩次密碼不一致,請您重新輸入!") continue flag = user_interface.register(username, pwd) if not flag: print("註冊失敗,請重試!") continue else: print(f"{username}註冊成功~") return True def login(): while True: username = input("請輸入用戶名>>>:").strip() if username == 'q': return False if not user_interface.check_user_exits(username): print("該用戶不存在,請檢查輸入!") continue pwd = input("請輸入密碼>>>:").strip() if pwd == 'q': return False flag = user_interface.login(username, pwd) if not flag: print("您的密碼有誤或賬戶已被凍結,請重新登錄!") continue else: print(f"登陸成功,{username}您好~") return True @common.login_auth def logout(): user_interface.logout() print("歡迎下次登錄,祝您生活愉快~") @common.login_auth def check_balance(): username = current_user.get("username") balance = user_interface.check_balance(username) print(f"{username}您好,您的賬戶餘額為{balance}。") @common.login_auth def check_flow(): username = current_user.get('username') flow = user_interface.check_flow(username) if flow: print(f"{username}您好,您的流水如下:") for line in flow: print(line) else: print(f"{username}您好,您的賬戶暫無流水記錄~") # --------------------- # 銀行接口 @common.login_auth def repay(): username = current_user.get('username') while True: money = input('請輸入您的還款金額>>>:').strip() if money == 'q': return False elif not money.isdigit(): print("請正確輸入金額") continue else: money = int(money) bank_interface.repay(username, money) print("還款成功!") return True @common.login_auth def withdraw(): username = current_user.get('username') while True: money = input('請輸入您的提現金額>>>:').strip() if money == 'q': return False elif not money.isdigit(): print("請正確輸入金額") continue else: money = int(money) flag = bank_interface.withdraw(username, money) if flag: print("提現成功!") return True else: print("您的餘額不足提現金額(提現需包含0.05%的手續費)。") @common.login_auth def transfer(): username = current_user.get('username') while True: target_user = input("請輸入您的轉賬目標用戶>>>:").strip() if user_interface.check_user_exits(target_user): money = input('請輸入您的轉賬金額>>>:').strip() if money == 'q': return False elif not money.isdigit(): print("請正確輸入金額") continue else: money = int(money) flag = bank_interface.transfer(username, target_user, money) if not flag: print("轉賬失敗,請確認您的餘額是否充足!") continue print("轉賬成功!") return True print(f"{target_user}用戶不存在,請您重新輸入!") # --------------------- # 購物功能 @common.login_auth def shop(): username = current_user['username'] while True: print("------------- 商品列表 -------------") for key in shopping_list: print(f"{key}.{shopping_list.get(key)[0]} {shopping_list.get(key)[1]}") choice = input("請輸入商品編號>>>:").strip() if choice == 'q': return False elif choice in shopping_list: # 開始購物 is_buy = input("請選擇購買或加入購物車(y購買/n加入購物車)(q退出)").strip() if is_buy == 'q': return False good = shopping_list[choice][0] price = shopping_list[choice][1] if is_buy == 'y': flag = shop_interface.pay_good(username, good, price) if not flag: print(f"您的餘額不足以購買該商品,請換一個試試") else: print(f"{good}商品購買成功!") elif is_buy == 'n': # 加入購物車 flag = shop_interface.put_shop_cart(username, good, price) if not flag: print(f"{good}該商品已在購物車中啦~") else: print(f"{good}成功放入購物車") pass else: print("請正確輸入!") continue else: print("請輸入正確的商品編號!") continue @common.login_auth def check_shop_cart(): username = current_user['username'] shop_cart = shop_interface.get_shop_cart(username) if shop_cart: print(f"{username}您好,您的購物車商品列表如下") for shop, price in shop_cart.items(): print(shop, price) else: print(f"您的購物車裡還沒有東西哦~") # --------------------- # 管理員功能 @common.login_auth @common.admin_auth def lock_user(): username = current_user['username'] while True: target_user = input("請輸入您要凍結的目標用戶>>>:").strip() if user_interface.check_user_exits(target_user): user_interface.lock_user(username, target_user) print(f"{target_user}用戶已凍結。") return True print(f"{target_user}用戶不存在,請您重新輸入!") @common.login_auth @common.admin_auth def unlock_user(): username = current_user['username'] while True: target_user = input("請輸入您要解凍的目標用戶>>>:").strip() if user_interface.check_user_exits(target_user): user_interface.unlock_user(username, target_user) print(f"{target_user}用戶已成功解凍。") return True print(f"{target_user}用戶不存在,請您重新輸入!") @common.login_auth @common.admin_auth def change_balance(): username = current_user['username'] while True: target_user = input("請輸入您要更改的目標用戶>>>:").strip() if user_interface.check_user_exits(target_user): money = input('請輸入金額>>>:').strip() if money == 'q': return False elif not money.isdigit(): print("請正確輸入金額") continue else: money = int(money) flag = user_interface.change_balance(username, target_user, money) if not flag: print("不能設置自己的餘額,請換個用戶試試。") continue print(f"{target_user}用戶餘額成功修改為{money}元。") return True print(f"{target_user}用戶不存在,請您重新輸入!") func_list = { '1': register, '2': login, '3': logout, '4': check_balance, '5': check_flow, '6': repay, '7': withdraw, '8': transfer, '9': shop, '10': check_shop_cart, '11': lock_user, '12': unlock_user, '13': change_balance, } current_user = { 'username': '', 'pwd': None, 'balance': 0, 'lock': False, 'flow': [], 'shop_cart': {}, 'is_admin': False } shopping_list = { "1": ['廣東鳳爪', 10], "2": ['麵疙瘩', 15], "3": ['mac', 12888], "4": ['tesla', 1222222] } def run(): while True: print("""------------------------------------------------------------------ 1.註冊 2.登錄 3.註銷 4.查看餘額 5.查看流水 6.還款 7.提現 8.轉賬 9.購物 10.查看購物車 11.鎖定用戶 12.解鎖用戶 13.更改用戶餘額 11-13為管理員功能哦,只有管理員才能操作! ------------------------------------------------------------------""") choice = input("請選擇功能編號>>>:").strip() if choice == 'q': print("感謝您的使用,歡迎下次再來~") return False elif choice in func_list: func_list[choice]() else: print("您的輸入有誤,請重新輸入")
數據處理層
db_handler.py數據處理文件
import os import json BASE_DIR = os.path.dirname(os.path.dirname(__file__)) DB_DIR = os.path.join(BASE_DIR, 'db') def select(username: str): user_dir = os.path.join(DB_DIR, f"{username}.json") if not os.path.exists(user_dir): return False else: with open(user_dir, mode='r', encoding='utf-8') as f: user_dict = json.load(f) return user_dict def save(user_dict: dict): user_dir = os.path.join(DB_DIR, f"{user_dict['username']}.json") with open(user_dir, mode='w', encoding='utf-8') as f: json.dump(user_dict, f, ensure_ascii=False) return True
用戶數據信息
db/swb.json用戶信息文件1
{"username": "swb", "pwd": "59f471f262ab586fb959ded0e2c7b94f", "balance": 10, "lock": false, "flow": ["swb購買了廣東鳳爪,花費10元,現餘額為14990元", "swb購買了麵疙瘩,花費15元,現餘額為14975元", "管理員tank將您的賬戶餘額重置為10元。"], "shop_cart": {"廣東鳳爪": 10, "麵疙瘩": 15, "mac": 12888, "tesla": 1222222}, "is_admin": false}
db/tank.json用戶信息文件2
{"username": "tank", "pwd": "59f471f262ab586fb959ded0e2c7b94f", "balance": 14975, "lock": false, "flow": ["tank購買了廣東鳳爪,花費10元,現餘額為14990元", "tank購買了麵疙瘩,花費15元,現餘額為14975元"], "shop_cart": {"tesla": 1222222}, "is_admin": true}
接口層
interface/bank_interface.py銀行功能接口文件
from db import db_handler from lib import common logger = common.get_logger('bank_interface') def repay(username: str, money: float): user_dict = db_handler.select(username) user_dict['balance'] += money user_dict['flow'].append(f"{username}還款{money}元,現餘額為{user_dict['balance']}。") db_handler.save(user_dict) logger.info(f"{username}還款{money}元,現餘額為{user_dict['balance']}。") return True def withdraw(username: str, money: float): user_dict = db_handler.select(username) if money*1.05 > user_dict['balance']: return False else: user_dict['balance'] -= money*1.05 user_dict['flow'].append(f"{username}提現{money}元,手續費{money*0.05}元,現餘額為{user_dict['balance']}元") db_handler.save(user_dict) logger.info(f"{username}提現{money}元,手續費{money*0.05}元,現餘額為{user_dict['balance']}元") return True def transfer(username: str, target_username: str, money: float): user_dict = db_handler.select(username) if user_dict['balance'] < money: return False user_dict['balance'] -= money user_dict['flow'].append(f"{username}向{target_username}轉賬{money}元。") db_handler.save(user_dict) target_user_dict = db_handler.select(target_username) target_user_dict['balance'] += money target_user_dict['flow'].append(f"{target_username}收到{username}轉賬{money}元。") db_handler.save(target_user_dict) logger.info(f"{username}向{target_username}轉賬{money}元。") return True
interface/shop_interface.py購物車功能接口文件
from db import db_handler from lib import common logger = common.get_logger('shop') def get_shop_cart(username: str): user_dict = db_handler.select(username) return user_dict['shop_cart'] def put_shop_cart(username: str, good: str, price: float): user_dict = db_handler.select(username) shop_cart = user_dict['shop_cart'] if good in shop_cart: return False else: shop_cart[good] = price user_dict['shop_cart'] = shop_cart db_handler.save(user_dict) logger.info(f"商品{good},單價{price},已加入{username}的購物車~") return True def pay_good(username, good, price): user_dict = db_handler.select(username) if user_dict['balance'] <= price: return False else: user_dict['balance'] -= price user_dict['flow'].append(f"{username}購買了{good},花費{price}元,現餘額為{user_dict['balance']}元") db_handler.save(user_dict) logger.info(f"{username}購買了{good},花費{price}元,現餘額為{user_dict['balance']}元") return True
interface/user_interface.py用戶功能接口文件
from db import db_handler from lib import common logger = common.get_logger('user_interface') def check_user_exits(username: str): flag = db_handler.select(username) if not flag: return False return True def register(username: str, pwd: str, balance=15000): pwd = common.get_md5(pwd) user_dict = { 'username': username, 'pwd': pwd, 'balance': balance, 'lock': False, 'flow': [], 'shop_cart': {}, 'is_admin': False } db_handler.save(user_dict) logger.info(f"{username}用戶註冊成功,初始餘額為{balance}元。") return True def login(username: str, pwd: str): pwd = common.get_md5(pwd) user_dict = db_handler.select(username) if user_dict['pwd'] == pwd and not user_dict['lock']: from core import src src.current_user = user_dict return True else: return False def logout(): from core import src logger.info(f"{src.current_user['username']}用戶註銷登錄。") src.current_user = { 'username': None, 'pwd': None, 'balance': None, 'lock': False, 'flow': [], 'shop_cart': {}, 'is_admin': False } return True def check_balance(username: str): user_dict = db_handler.select(username) return user_dict['balance'] def check_flow(username: str): user_dict = db_handler.select(username) return user_dict['flow'] def lock_user(username: str, target_user: str): target_user_dict = db_handler.select(target_user) target_user_dict['lock'] = True db_handler.save(target_user_dict) logger.info(f"{username}將{target_user}賬戶凍結。") return True def unlock_user(username: str, target_user: str): target_user_dict = db_handler.select(target_user) target_user_dict['lock'] = False db_handler.save(target_user_dict) logger.info(f"{username}將{target_user}賬戶解凍。") return True def change_balance(username: str, target_user: str, money: float): if username == target_user: return False target_user_dict = db_handler.select(target_user) target_user_dict['balance'] = money target_user_dict['flow'].append(f"管理員{username}將您的賬戶餘額重置為{money}元。") db_handler.save(target_user_dict) logger.info(f"{username}將{target_user}的賬戶餘額改為{money}元。") return True # 這些管理員方法用裝飾器判斷他是不是管理員
通用方法
lib/common.py通用方法文件
import logging.config from conf import logging_dict import hashlib # 日誌字典使用 def get_logger(type_name: str): logging.config.dictConfig(logging_dict.LOGGING_DIC) logger = logging.getLogger(type_name) return logger # 登錄裝飾器 def login_auth(func): def inner(*args, **kwargs): from core import src if src.current_user.get('username'): # 登錄驗證 res = func(*args, **kwargs) return res else: print("請登錄後再操作!") src.login() return inner # 管理員驗證 def admin_auth(func): def inner(*args, **kwargs): from core import src if src.current_user.get('is_admin'): # 判斷是不是管理員 res = func(*args, **kwargs) return res else: print("您不是管理員,不能使用此功能哦~") return inner # md5值獲取 def get_md5(string: str) -> str: md5 = hashlib.md5() md5.update('md5_salt'.encode('utf-8')) md5.update(string.encode('utf-8')) return md5.hexdigest() if __name__ == '__main__': logger = get_logger('common') logger.info('info測試數據啦~') logger.debug('debug測試數據啦~')
日誌記錄
log/ATM_Shop_Cart.log日誌記錄文件
[2019-07-23 21:55:50,172][MainThread:2688][task_id:user_interface][user_interface.py:25][INFO][swb用戶註冊成功,初始餘額為15000元。] [2019-07-23 21:56:07,970][MainThread:2688][task_id:shop][shop_interface.py:30][INFO][swb購買了廣東鳳爪,花費10元,現餘額為14990元] [2019-07-23 21:56:11,611][MainThread:2688][task_id:shop][shop_interface.py:19][INFO][商品麵疙瘩,單價15,已加入swb的購物車~] [2019-07-23 21:56:13,812][MainThread:2688][task_id:shop][shop_interface.py:19][INFO][商品mac,單價12888,已加入swb的購物車~] [2019-07-23 21:56:54,035][MainThread:764][task_id:shop][shop_interface.py:20][INFO][商品廣東鳳爪,單價10,已加入swb的購物車~] [2019-07-23 21:56:55,516][MainThread:764][task_id:shop][shop_interface.py:20][INFO][商品麵疙瘩,單價15,已加入swb的購物車~] [2019-07-23 21:56:56,882][MainThread:764][task_id:shop][shop_interface.py:20][INFO][商品mac,單價12888,已加入swb的購物車~] [2019-07-23 21:56:58,797][MainThread:764][task_id:shop][shop_interface.py:20][INFO][商品tesla,單價1222222,已加入swb的購物車~] [2019-07-23 21:57:06,937][MainThread:764][task_id:shop][shop_interface.py:31][INFO][swb購買了廣東鳳爪,花費10元,現餘額為14990元] [2019-07-23 21:57:09,363][MainThread:764][task_id:shop][shop_interface.py:31][INFO][swb購買了麵疙瘩,花費15元,現餘額為14985元] [2019-07-23 21:57:10,666][MainThread:764][task_id:shop][shop_interface.py:31][INFO][swb購買了mac,花費12888元,現餘額為2112元] [2019-07-23 21:59:27,610][MainThread:14372][task_id:shop][shop_interface.py:31][INFO][swb購買了廣東鳳爪,花費10元,現餘額為14990元] [2019-07-23 22:00:37,898][MainThread:7112][task_id:shop][shop_interface.py:32][INFO][swb購買了廣東鳳爪,花費10元,現餘額為14990元] [2019-07-23 22:00:39,419][MainThread:7112][task_id:shop][shop_interface.py:32][INFO][swb購買了麵疙瘩,花費15元,現餘額為14975元] [2019-07-23 22:01:08,585][MainThread:1056][task_id:user_interface][user_interface.py:25][INFO][tank用戶註冊成功,初始餘額為15000元。] [2019-07-23 22:01:18,705][MainThread:1056][task_id:shop][shop_interface.py:32][INFO][tank購買了廣東鳳爪,花費10元,現餘額為14990元] [2019-07-23 22:01:23,370][MainThread:1056][task_id:shop][shop_interface.py:32][INFO][tank購買了麵疙瘩,花費15元,現餘額為14975元] [2019-07-23 22:01:29,289][MainThread:1056][task_id:shop][shop_interface.py:20][INFO][商品tesla,單價1222222,已加入tank的購物車~] [2019-07-23 22:03:05,065][MainThread:1056][task_id:user_interface][user_interface.py:42][INFO][tank用戶註銷登錄。] [2019-07-23 22:03:18,514][MainThread:1056][task_id:user_interface][user_interface.py:69][INFO][tank將swb賬戶凍結。] [2019-07-23 22:03:20,986][MainThread:1056][task_id:user_interface][user_interface.py:42][INFO][tank用戶註銷登錄。] [2019-07-23 22:03:45,178][MainThread:1056][task_id:user_interface][user_interface.py:77][INFO][tank將swb賬戶解凍。] [2019-07-23 22:04:05,704][MainThread:1056][task_id:user_interface][user_interface.py:42][INFO][swb用戶註銷登錄。] [2019-07-23 22:04:18,321][MainThread:1056][task_id:user_interface][user_interface.py:88][INFO][tank將swb的賬戶餘額改為10元。] [2019-07-23 22:04:22,425][MainThread:1056][task_id:user_interface][user_interface.py:42][INFO][tank用戶註銷登錄。]
注意: # swb 用戶為管理員用戶,可以執行管理員操作(swb 以及 tank的密碼均為 123),右鍵starts.py文件運行即可