标签:sage === .sh 配置 日志格式 append 控制 out 保存
------------README
作者:飞乐 版本:示例版本 v0.1 程序介绍: 实现ATM常用功能 功能全部用python的基础知识实现,用到了time\os\sys\open\函数\模块知识, 主要帮给大家一个简单的模块化编程的示例 注意:只实现了"认证","注册","购物"和"支付"功能 程序结构: ATM--/ ├——─ README ├── atm #ATM主程目录 │ ├── __init__.py │ ├── bin #ATM 执行文件 目录 │ │ ├── __init__.py │ │ ├── start.py #ATM 执行程序 │ │ └── manage.py #ATM 管理端,未实现 │ ├── conf #配置文件 │ │ ├── __init__.py │ │ └── settings.py #文本配置 │ ├── core #主要程序逻辑都 在这个目录 里 │ │ ├── __init__.py │ │ ├── auth.py #用户认证模块 │ │ ├── shop.py #购物商城 │ │ ├── register.py #用户注册模块 │ │ ├── src.py #主逻辑交互程序 │ ├── db #用户数据存储的地方 │ │ ├── __init__.py │ │ ├── db.py #生成一个临时的账户数据 │ │ └── error_db.py #账户锁定文本 │ ├── lib #公共程序 │ │ ├── __init__.py │ │ ├── common.py #临时获取的用户信息 │ └── log #日志目录 │ ├── __init__.py └── ── ├── access.log #用户访问和操作的相关日志
ATM
start.py
1 import sys,os 2 BASE_DIR=os.path.dirname(os.path.dirname(__file__)) 3 sys.path.append(BASE_DIR) 4 5 from core import src 6 src.run()
settings.py
import os BASE_DIR=os.path.dirname(os.path.dirname(__file__)) DB_PATH=r‘%s\db\db.txt‘%BASE_DIR#用户注册信息路径 ER_PATH=r‘%s\db\error_db.txt‘%BASE_DIR#锁定账户的信息路径
#以下内容是增加的功能
LOG_PATH=r‘%s\log\access.log‘%BASE_DIR#定义日志文件路径 BOSS_LOG_PATH=r‘%s\log\boss.log‘%BASE_DIR#定义日志文件路径 """ logging配置 """ # 定义三种日志输出格式 开始 standard_format = ‘[%(asctime)s][%(threadName)s:%(thread)d][task_id:%(name)s][%(filename)s:%(lineno)d]‘ ‘[%(levelname)s][%(message)s]‘ #其中name为getlogger指定的名字 simple_format = ‘[task_id:%(name)s][%(levelname)s][%(asctime)s][%(filename)s:%(lineno)d]%(message)s‘ id_simple_format = ‘[task_id:%(name)s][%(levelname)s][%(asctime)s] %(message)s‘ # log配置字典(字典的key不能改) LOGGING_DIC = { ‘version‘: 1, #定义的版本 ‘disable_existing_loggers‘: False,#无用 #1、定义日志的格式 ‘formatters‘: {#字典的key可以随便取 ‘standard‘: {#key是固定格式 ‘format‘: standard_format#定义的日志格式 }, ‘simple‘: { ‘format‘: simple_format }, ‘id_simple‘:{ ‘format‘:id_simple_format }, }, ‘filters‘: {}, #过滤,不用 #2、定义日志输入的目标:文件或者终端,发送给boss ‘handlers‘: {#控制文件写入 #打印到终端的日志 ‘stream‘: { ‘level‘: ‘DEBUG‘, ‘class‘: ‘logging.StreamHandler‘, # 打印到屏幕 ‘formatter‘: ‘simple‘#绑定格式 }, #打印到文件的日志,收集info及以上的日志 ‘access‘: { ‘level‘: ‘DEBUG‘, ‘class‘: ‘logging.handlers.RotatingFileHandler‘, # 保存到文件(日志轮转) ‘formatter‘: ‘standard‘,#绑定日志格式 ‘filename‘: LOG_PATH, # 日志文件 ‘maxBytes‘: 1024*1024*5, # 日志大小 5M#一份日志文件的大小 ‘backupCount‘: 5,#最多保存五份日志,写完五份时轮转 ‘encoding‘: ‘utf-8‘, # 日志文件的编码,再也不用担心中文log乱码了 }, #打印到文件的日志,收集error及以上的日志 ‘boss‘: { ‘level‘: ‘ERROR‘, ‘class‘: ‘logging.handlers.RotatingFileHandler‘, # 保存到文件(日志轮转) ‘formatter‘: ‘id_simple‘,#绑定日志格式 ‘filename‘: BOSS_LOG_PATH, # 日志文件 ‘maxBytes‘: 1024*1024*5, # 日志大小 5M#一份日志文件的大小 ‘backupCount‘: 5,#最多保存五份日志,写完五份时轮转 ‘encoding‘: ‘utf-8‘, # 日志文件的编码,再也不用担心中文log乱码了 }, }, ‘loggers‘: { #logging.getLogger(__name__)拿到的logger配置 ‘‘: {#定义日志的名字 ‘handlers‘: [‘access‘, ‘stream‘,‘boss‘], # 这里把上面定义的两个handler都加上,即log数据既写入文件又打印到屏幕 ‘level‘: ‘DEBUG‘, ‘propagate‘: False, # 向上(更高level的logger)传递 }, }, } #因为这是单独的功能,下面代码不能在这里写,要把它写在lib文件common内 # import logging.config # import logging # logging.config.dictConfig(LOGGING_DIC) # 导入上面定义的logging配置 # # l1=logging.getLogger(‘egon‘) # l1.debug(‘测试‘)
auth.py
1 import sys,os 2 BASE_DIR=os.path.dirname(os.path.dirname(__file__)) 3 sys.path.append(BASE_DIR) 4 from lib import common #导入读取到的用户信息 5 from conf import settings #导入配置模块获取文本路径,用于锁定账户写入文本 6 7 8 def outter(func): 9 def inner(*args,**kwargs): 10 user_info_dic = common.user_info() 11 while True: 12 if len(user_info_dic) == 0: 13 print(‘请先注册‘) 14 break 15 if common.current_user[‘username‘]: 16 print(‘用户已登录‘) 17 res = func(*args,**kwargs) 18 return res 19 20 uname=input(‘用户名>>:‘).strip() 21 if uname==‘q‘:break 22 if uname not in user_info_dic: 23 print(‘用户不存在。。。‘) 24 continue 25 26 if uname in common.user_error_info(): 27 print(‘此账户已被锁定‘) 28 continue 29 30 if user_info_dic[uname][‘status‘]>2: 31 with open(settings.ER_PATH,‘a‘,encoding=‘utf-8‘)as f: 32 f.write(‘%s|‘%uname) 33 user_info_dic[uname][‘status‘]=0 34 print(‘尝试次数过多,账户已被锁定‘) 35 continue 36 37 pwd=input(‘密码>>:‘).strip() 38 if pwd==‘q‘:break 39 if pwd==user_info_dic[uname][‘password‘]: 40 print(‘欢迎 %s 登录成功‘%uname) 41 common.current_user[‘username‘]=uname#将用户名存入临时字典内 42 common.current_user[‘balance‘]=int(user_info_dic[uname][‘balance‘])#将价格信息转成int存入字典内,用于购物运算 43 res=func(*args,**kwargs) 44 return res 45 else: 46 print(‘密码错误‘) 47 user_info_dic[uname][‘status‘] +=1 48 return inner 49 50 51 @outter 52 def auth1(): 53 pass
register.py
1 import sys,os 2 BASE_DIR=os.path.dirname(os.path.dirname(__file__)) 3 sys.path.append(BASE_DIR) 4 from conf import settings 5 6 def get_uname(): 7 while True: 8 uname=input(‘请输入用户名>>:‘).strip() 9 if not uname.isalpha(): 10 print(‘输入不合法‘) 11 continue 12 with open(settings.DB_PATH,‘r‘,encoding=‘utf-8‘)as f: 13 for line in f:#如果break没有运行,则运行else 14 line=line.strip(‘\n‘).split(‘,‘) 15 if uname==line[0]: 16 print(‘用户已存在‘) 17 break 18 else: 19 return uname 20 def get_pwd(): 21 while True: 22 pwd1=input(‘请输入密码>>:‘).strip() 23 if not len(pwd1) > 0: 24 print(‘输入不能为空‘) 25 continue 26 pwd2=input(‘请再次输入密码>>:‘).strip() 27 if pwd1==pwd2: 28 return pwd1 29 else: 30 print(‘两次输入密码不一致,请重新输入‘) 31 def get_bal(): 32 while True: 33 bal=input(‘请输入金额>>:‘).strip() 34 if bal.isdigit(): 35 return bal 36 else: 37 print(‘输入非法‘) 38 def uinfo_write(uname,pwd,bal): 39 with open(settings.DB_PATH,‘a‘,encoding=‘utf-8‘)as f: 40 f.write(‘%s,%s,%s\n‘%(uname,pwd,bal)) 41 print(‘注册成功‘) 42 43 #用户注册执行入口 44 def registe(): 45 print(‘\033[34;1m========注册=========\033[0m‘) 46 uname=get_uname() 47 pwd=get_pwd() 48 bal=get_bal() 49 uinfo_write(uname,pwd,bal)
shop.py
1 import sys,os 2 BASE_DIR=os.path.dirname(os.path.dirname(__file__)) 3 sys.path.append(BASE_DIR) 4 from lib import common 5 from core import auth 6 7 @auth.outter 8 def shopping(): 9 #登录成功,开始购物 10 uname_of_db=common.current_user[‘username‘]#获取用户名 11 balance_of_db=common.current_user[‘balance‘]#获取余额 12 print(‘\033[32;1m欢迎进入购物商城\n尊敬的用户 [%s] 您的余额为 [%s],祝您购物愉快\033[0m‘%( 13 uname_of_db,balance_of_db)) 14 while True: 15 goods = [ 16 {"name":"电脑","price":2000}, 17 {"name":"鼠标","price":10}, 18 {"name":"游艇","price":20}, 19 {"name":"美女","price":100}, 20 ] 21 print(‘------商品编号-------商品名称-----商品价格------‘) 22 for index,item in enumerate(goods): 23 print(‘ %s %s %s‘%( 24 index,goods[index][‘name‘],goods[index][‘price‘])) 25 print(‘--------------------end------------------------‘) 26 choice=input(‘请输入想购买的商品编号,输入"q"退出>>:‘).strip() 27 if choice.isdigit(): 28 choice=int(choice) 29 if choice < 0 or choice >= len(goods):continue#判断购买的商品是否超过可选范围 30 31 gname=goods[choice][‘name‘]#商品名 32 gprice=goods[choice][‘price‘]#商品价格 33 34 if balance_of_db >= gprice: 35 if gname in common.shopping_cart:#原来已经买过了 36 common.shopping_cart[gname][‘count‘] +=1 37 else: 38 common.shopping_cart[gname]={‘gprice‘:gprice,‘count‘:1} 39 40 balance_of_db -=gprice #扣钱 41 common.current_user[‘balance‘]=balance_of_db#更新账户余额 42 print(‘成功购买 %s 添加到购物车,价格是 %s‘%(gname,gprice)) 43 else: 44 print(‘你个穷逼买不起,产品价格是 {price} ,你还差 {lack_price}‘.format( 45 price=gprice, 46 lack_price=(gprice-balance_of_db) 47 )) 48 print(common.shopping_cart) 49 print(‘退出并支付购买的商品请输入:"b"‘) 50 elif choice==‘b‘: 51 break 52 elif choice==‘q‘: 53 common.shopping_cart={} 54 break 55 else: 56 print(‘输入非法‘)
src.py
from core import register#用户注册模块 from core import auth #导入用户注册模块 from core import shop #导入购物模块 from lib import common#导入公共模块 from conf import settings #导入配置模块 import os #支付,注册,认证等日志功能我都没有添加,想看效果的自己尝试。 logger1=common.get_logger(‘atm‘)#必须传入一个值,在lib/common中函数get_logger中有参数。 @auth.outter def pay(): print(‘------------支付---------\n‘) print(""" ---------------------------------已购买商品列表--------------------------------- id 商品 数量 单价 总价 """) total_cost=0 for i,key in enumerate(common.shopping_cart): print(‘%22s%18s%18s%18s%18s‘%( i, key, common.shopping_cart[key][‘count‘], common.shopping_cart[key][‘gprice‘], common.shopping_cart[key][‘count‘]*common.shopping_cart[key][‘gprice‘] )) total_cost +=common.shopping_cart[key][‘count‘]*common.shopping_cart[key][‘gprice‘] print(‘‘‘ 您的总花费为:%s 您的余额为:%s ---------------------------------end--------------------------------- ‘‘‘%(total_cost,common.current_user[‘balance‘])) while True: if len(common.shopping_cart) == 0: print(‘购物车为空,无需支付‘) break inp=input(‘确认购买(yes/no?)>>:‘).strip() if inp not in [‘Y‘,‘N‘,‘y‘,‘n‘,‘yes‘,‘no‘]:continue if inp in [‘Y‘,‘y‘,‘yes‘]: #将余额写入文件 src_file=settings.DB_PATH dst_file=r‘%s.swp‘%settings.DB_PATH with open(src_file,‘r‘,encoding=‘utf-8‘)as read_f, open(dst_file,‘w‘,encoding=‘utf-8‘)as write_f: for line in read_f: if line.startswith(common.current_user[‘username‘]): l=line.strip(‘\n‘).split(‘,‘) l[-1]=str(common.current_user[‘balance‘]) line=‘,‘.join(l)+‘\n‘ #在内存中修改的数据,写入到硬盘中 write_f.write(line) os.remove(src_file) os.rename(dst_file,src_file) print(‘购买成功,请耐心等待发货‘) common.shopping_cart={} common.current_user[‘username‘]=None common.current_user[‘balance‘]=None break if inp in [‘N‘,‘n‘,‘no‘]: print(‘正在退出支付平台。。。。。‘) break @auth.outter def transter(): print(‘------------转账---------‘) logger1.error(‘小明给小红转账100000,转账转错了‘) dic={ ‘1‘:auth.auth1, ‘2‘:register.registe, ‘3‘:shop.shopping, ‘4‘:pay, ‘5‘:transter, } def run(): while True: print(‘‘‘ 1 认证 2 注册 3 购物 4 支付 5 转账 ‘‘‘) choice = input(‘>>: ‘).strip() if choice in dic: dic[choice]() elif choice==‘q‘:break else: print(‘输入非法‘)
db.txt
1 alex,abc,2400
error_db.txt
alex|egon|jack|
common.py
from conf import settings #引入配置模块获取文本信息路径,用于读取用户信息 import logging.config import logging #在这里要写成单独的功能 def get_logger(name): logging.config.dictConfig(settings.LOGGING_DIC) # 导入上面定义的logging配置 l1=logging.getLogger(name) return l1 #获取用户列表信息 def user_info(): user_info_dic={} with open(settings.DB_PATH,‘r‘,encoding=‘utf-8‘)as f: for line in f: line=line.strip(‘\n‘).split(‘,‘) user_info_dic[line[0]]={ ‘password‘:line[1], ‘balance‘:line[2], ‘status‘:0, } return user_info_dic #获取被锁定的用户信息 def user_error_info(): with open(settings.ER_PATH,‘r‘,encoding=‘utf-8‘)as f: line=f.read() line=line.strip().split(‘|‘) return line #将登成功的信息保存到字典中 current_user={ ‘username‘:None, ‘balance‘:None, } shopping_cart={}
access.log(已实现)
此功能已经实现,上面展开中标记颜色的代码。
标签:sage === .sh 配置 日志格式 append 控制 out 保存
原文地址:https://www.cnblogs.com/happyfei/p/9454668.html