小说阅读器
![](https://img2020.cnblogs.com/blog/1947364/202003/1947364-20200330082557977-1636549552.png)
启动模块bin/start.py
1 import os
2 import sys
3
4 BASE_PATH=os.path.dirname(os.path.dirname(__file__))
5 sys.path.append(BASE_PATH)
6
7
8 from core import src
9
10 if __name__== '__main__':
11 src.run()
核心代码模块core/src.py
1 from db import db_handler as db
2 from lib import common
3
4
5 login_user = None
6
7
8
9
10 def register():
11 '''
12 注册功能
13 :return:
14 '''
15 while True:
16 inp_name = input('输入用户名').strip()
17 name, psd, remind = db.getinfo(inp_name)
18 if inp_name in name:
19 print('用户已存在')
20 password = input('输入密码')
21 re_psd = input('再次输入密码')
22 if password == re_psd:
23 db.save_reg(inp_name, password)
24 print('注册成功')
25 break
26 else:
27 print('两次密码不一致,请重新输入')
28
29
30
31 def login():
32 '''
33 登录功能
34 :return:
35 '''
36 while True:
37 inp_name = input('输入用户名')
38 name, psd, remind = db.getinfo(inp_name)
39 if inp_name not in name:
40 print('用户名不存在,请先注册')
41 continue
42 password = input('输入密码').strip()
43 if password == psd:
44 global login_user
45 login_user = inp_name
46 print('登录成功,亲爱的{}用户'.format(login_user))
47 break
48 else:
49 print('账号密码错误')
50
51
52
53 @common.log
54 @common.auth
55 def add_credit():
56 '''
57 充值功能
58 :return:
59 '''
60 print('欢迎使用充值功能,亲爱的{}用户'.format(login_user))
61 while True:
62 amount = input('输入充值金额')
63 if not amount.isdigit():
64 print('请输入数字')
65 continue
66 comf = input('确定要充值{}元吗,按Y/y确认,按R/r'.format(amount))
67 if comf == 'R' or comf == 'r':
68 continue
69 if comf == 'Y' or comf == 'y':
70 name, psd, remind = db.getinfo(login_user)
71 remind=int(remind)
72 old_data = '{}:{}:{}'.format(name, psd, remind)
73 remind += int(amount)
74 new_data = '{}:{}:{}'.format(name, psd, remind)
75 db.update(old_data, new_data)
76 print('已成功充值{}'.format(amount))
77 break
78 return amount
79
80
81 @common.log
82 @common.auth
83 def reader():
84 '''
85 小说功能
86 :return:
87 '''
88 book_dic=db.get_book()
89 if not book_dic:
90 print('库存没有小说了')
91 return
92 while True:
93 print('''
94 === 欢迎来到阅读小说功能主页 ===
95 0 玄幻武侠
96 1 都市爱情
97 2 高效养猪36技
98 ============ end ============
99 ''')
100 cmd=input('输入你想阅读的小说种类编号').strip()
101 if cmd not in book_dic:
102 print('请正确输入编号')
103 second_dic =book_dic[cmd]
104 for num,booklist in second_dic.item():
105 name,price=booklist
106 print('小说编号[{}],小说名《{}》,小说价格[{}]'.format(num,name,price))
107 while True:
108 cmd = input('输入你想购买的小说编号')
109 if cmd not in second_dic:
110 print('请正确输入编号')
111 continue
112 if cmd in second_dic:
113 name=second_dic[cmd][0]
114 price=second_dic[cmd][1]
115 cmd = input('当前选择的小说名为: 《{name}》,商品单价为: [{price}], 请输入Y/y购买:'.format(name,price)).strip()
116 if cmd == 'Y' or cmd=='y':
117 name,psd,remind = db.getinfo(login_user)
118 remind=int(remind)
119 if remind<int(price):
120 price('余额不足,请先充值')
121 break
122 old_data = '{}:{}:{}'.format(name, psd, remind)
123 remind -= int(price)
124 new_data = '{}:{}:{}'.format(name, psd, remind)
125 db.update(old_data, new_data)
126 print('购买成功,请欣赏内容')
127 fictiondata=db.show(name)
128 print('''
129 -------开始阅读--------
130 {}
131 '''.format(fictiondata))
132
133
134
135 def logout():
136 '''
137 登出功能
138 :return:
139 '''
140 global login_user
141 login_user=None
142
143
144 #运行菜单
145 func_dic={
146 '0':['注册',register],
147 '1':['登录',login],
148 '2':['充值',add_credit],
149 '3':['小说',reader],
150 '4':['登出',logout],
151 }
152
153 def run():
154 while True:
155 print('''
156 ~~~~~~~欢迎来到小说世界~~~~~~~
157 0 账号注册
158 1 账号登录
159 2 充值功能
160 3 阅读小说
161 4 登出
162 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
163 ''')
164 cmd= input('请输入功能编号,按4退出').strip()
165 if cmd =='4':
166 logout()
167 break
168 if cmd not in func_dic:
169 print('请正确输入功能编号')
170 continue
171 func_dic[cmd][1]()
172
173 run()
数据库操作模块db/db_handler.py
1 from conf import settings
2 import os
3
4
5 def getinfo(username):
6 '''
7 取出文件中用户的数据
8 :param username:
9 :return:
10 '''
11 with open(settings.DB_TXT_PATH, 'rt', encoding='utf-8')as f:
12 for line in f:
13 if username in line:
14 name, psd, remind = line.strip().split(':')
15 return name, psd, remind
16
17
18 def save_reg(name, psd, balance=0):
19 '''
20 存注册用户的数据
21 :param name:
22 :param psd:
23 :param balance:
24 :return:
25 '''
26 with open(settings.DB_TXT_PATH, 'at', encoding='utf-8')as f:
27 f.write('{}:{}:{}'.format(name, psd, balance))
28
29
30
31 def update(old_data, new_data):
32 '''
33 更新用户数据
34 :param old_data:
35 :param new_data:
36 :return:
37 '''
38 with open(settings.DB_TXT_PATH, 'rt', encoding='utf-8')as rf:
39 alldata = rf.read()
40 alldata = alldata.replace(old_data, new_data)
41 with open('db.txt.swap', 'wt', encoding='utf-8')as wf:
42 wf.write(alldata)
43 os.rename('db.txt.swap', settings.DB_TXT_PATH)
44
45
46 def get_book():
47 '''
48 获取小说数据
49 :return:
50 '''
51 with open(settings.STORY_PATH,'rt',encoding='utf-8')as f:
52 book_dic=eval(f.read())
53 return book_dic
54
55
56 def show(bookname):
57 '''
58 查看小说
59 :param bookname:
60 :return:
61 '''
62 book_path = os.path.join(settings.BOOK_DIR, bookname)
63 with open(book_path,'rt',encoding='utf-8')as f:
64 data=f.read()
65 return data
公共模块(装饰器)lib/common.py
1 from conf import settings
2 import time
3 from core.src import login_user
4 from core.src import login
5
6 def auth(func):
7 '''
8 认证装饰器
9 :param func:
10 :return:
11 '''
12 def wrapper(*args, **kwargs):
13 if login_user:
14 res = func(*args, **kwargs)
15 return res
16 else:
17 print('请先登录再使用功能')
18 login()
19
20 return wrapper
21
22
23
24 def log(func):
25 '''
26 记录日志装饰器
27 :param func:
28 :return:
29 '''
30 def wrapper(*args, **kwargs):
31 res = func(*args, **kwargs)
32 now_time = time.strftime('%Y-%m-%d %X')
33 log_data = '{} {} {} {}'.format(now_time, login_user, func.__name__, res)
34 with open('time.log', 'ab')as logf:
35 logf.write(log_data.encode('utf-8'))
36
37 return res
38
39 return wrapper
配置模块conf/settings.py
import os
# 获取项目根目录reader_sys根目录
BASE_PATH = os.path.dirname(os.path.dirname(__file__))
# 获取db目录路径
DB_PATH = os.path.join(BASE_PATH, 'db')
# 获取db.txt的根目录
DB_TXT_PATH = os.path.join(DB_PATH, 'db.txt')
# story_class.txt文件目录路径
STORY_PATH = os.path.join(DB_PATH, 'story_class.txt')
# 小说存放目录
BOOK_DIR = os.path.join(DB_PATH, 'book')
# 日志文件的路径
LOG_PATH = os.path.join(BASE_PATH, 'log', 'user.log')
面条形式的一个文件下的小说阅读程序实现
1.更新了小说阅读模块
2.重写了用户存取数据的方式:将字典模式改为函数功能,方便之后规范化放入数据库操作模块中
3.独立了登录模块,将认证功能装饰器简化
import os
import time
login_user = None
# common模块
# 认证装饰器
def auth(func):
def wrapper(*args, **kwargs):
if login_user:
res = func(*args, **kwargs)
return res
else:
print('请先登录再使用功能')
login()
return wrapper
# 记录日志装饰器
def log(func):
def wrapper(*args, **kwargs):
res = func(*args, **kwargs)
now_time = time.strftime('%Y-%m-%d %X')
log_data = '{} {} {} {}'.format(now_time, login_user, func.__name__, res)
with open('time.log', 'ab')as logf:
logf.write(log_data.encode('utf-8'))
return res
return wrapper
# 数据库模块
# 取数据
def getinfo(username):
with open('db.txt', 'rt', encoding='utf-8')as f:
for line in f:
if username in line:
name, psd, remind = line.strip().split(':')
return name, psd, remind
# 存注册数据
def save_reg(name, psd, balance=0):
with open('db.txt', 'at', encoding='utf-8')as f:
f.write('{}:{}:{}'.format(name, psd, balance))
# 更新数据
def update(old_data, new_data):
with open('db.txt', 'rt', encoding='utf-8')as rf:
alldata = rf.read()
alldata = alldata.replace(old_data, new_data)
with open('db.txt.swap', 'wt', encoding='utf-8')as wf:
wf.write(alldata)
os.rename('db.txt.swap', 'db.txt')
# 注册功能
def register():
while True:
inp_name = input('输入用户名').strip()
name, psd, remind = getinfo(inp_name)
if inp_name in name:
print('用户已存在')
password = input('输入密码')
re_psd = input('再次输入密码')
if password == re_psd:
save_reg(inp_name, password)
print('注册成功')
break
else:
print('两次密码不一致,请重新输入')
# 登录功能
def login():
while True:
inp_name = input('输入用户名')
name, psd, remind = getinfo(inp_name)
if inp_name not in name:
print('用户名不存在,请先注册')
continue
password = input('输入密码').strip()
if password == psd:
global login_user
login_user = inp_name
print('登录成功,亲爱的{}用户'.format(login_user))
break
else:
print('账号密码错误')
# 充值功能
@log
@auth
def add_credit():
print('欢迎使用充值功能,亲爱的{}用户'.format(login_user))
while True:
amount = input('输入充值金额')
if not amount.isdigit():
print('请输入数字')
continue
comf = input('确定要充值{}元吗,按Y/y确认,按R/r'.format(amount))
if comf == 'R' or comf == 'r':
continue
if comf == 'Y' or comf == 'y':
name, psd, remind = getinfo(login_user)
remind=int(remind)
old_data = '{}:{}:{}'.format(name, psd, remind)
remind += int(amount)
new_data = '{}:{}:{}'.format(name, psd, remind)
update(old_data, new_data)
print('已成功充值{}'.format(amount))
break
return amount
#获取小说数据
def get_book():
with open('story_class.txt','rt',encoding='utf-8')as f:
book_dic=eval(f.read())
return story_dic
#查看小说
def show(bookname):
with open('','rt',encoding='utf-8')as f:
data=f.read()
return data
# 小说功能
@log
@auth
def reader():
book_dic=get_book()
if not book_dic:
print('库存没有小说了')
return
while True:
print('''
=== 欢迎来到阅读小说功能主页 ===
0 玄幻武侠
1 都市爱情
2 高效养猪36技
============ end ============
''')
cmd=input('输入你想阅读的小说种类编号').strip()
if cmd not in book_dic:
print('请正确输入编号')
second_dic =book_dic[cmd]
for num,booklist in second_dic.item():
name,price=booklist
print('小说编号[{}],小说名《{}》,小说价格[{}]'.format(num,name,price))
while True:
cmd = input('输入你想购买的小说编号')
if cmd not in second_dic:
print('请正确输入编号')
continue
if cmd in second_dic:
name=second_dic[cmd][0]
price=second_dic[cmd][1]
cmd = input('当前选择的小说名为: 《{name}》,商品单价为: [{price}], 请输入Y/y购买:'.format(name,price)).strip()
if cmd == 'Y' or cmd=='y':
name,psd,remind = getinfo(login_user)
remind=int(remind)
if remind<int(price):
price('余额不足,请先充值')
break
old_data = '{}:{}:{}'.format(name, psd, remind)
remind -= int(price)
new_data = '{}:{}:{}'.format(name, psd, remind)
update(old_data, new_data)
print('购买成功,请欣赏内容')
fictiondata=show(name)
print('''
-------开始阅读--------
{}
'''.format(fictiondata))
#登出功能
def logout():
global login_user
login_user=None
#运行菜单
func_dic={
'0':['注册',register],
'1':['登录',login],
'2':['充值',add_credit],
'3':['小说',reader],
'4':['登出',logout],
}
def run():
while True:
print('''
~~~~~~~欢迎来到小说世界~~~~~~~
0 账号注册
1 账号登录
2 充值功能
3 阅读小说
4 登出
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
''')
cmd= input('请输入功能编号,按4退出').strip()
if cmd =='4':
logout()
break
if cmd not in func_dic:
print('请正确输入功能编号')
continue
func_dic[cmd][1]()
run()
# 编写小说阅读程序实现下属功能
# # 一:程序运行开始时显示
# 0 账号注册
# 1 充值功能
# 2 阅读小说
#
#
# # 二: 针对文件db.txt,内容格式为:"用户名:密码:金额",完成下述功能
# 2.1、账号注册
# 2.2、充值功能
#
# # 三:文件story_class.txt存放类别与小说文件路径,如下,读出来后可用eval反解出字典
# {"0":{"0":["倚天屠狗记.txt",3],"1":["沙雕英雄转.txt",10]},"1":{"0":["令人羞耻的爱.txt",6],"1":["二狗的妻子与大草原的故事.txt",5]},}
#
# 3.1、用户登录成功后显示如下内容,根据用户选择,显示对应品类的小说编号、小说名字、以及小说的价格
# """
# 0 玄幻武侠
# 1 都市爱情
# 2 高效养猪36技
# """
#
# 3.2、用户输入具体的小说编号,提示是否付费,用户输入y确定后,扣费并显示小说内容,如果余额不足则提示余额不足
#
# # 四:为功能2.2、3.1、3.2编写认证功能装饰器,要求必须登录后才能执行操作
#
# # 五:为功能2.2、3.2编写记录日志的装饰器,日志格式为:"时间 用户名 操作(充值or消费) 金额"
#
#
#
# # 附加:
# # 可以拓展作者模块,作者可以上传自己的作品
#
#
import time
userstatus = {'username': None}
def auth(func):
'''
认证功能装饰器
:return:
'''
def wrapper(*args, **kwargs):
if userstatus['username'] is None:
inp_name = input('输入用户名')
inp_psd = input('输入密码')
with open('db.txt', 'rt', encoding='utf-8')as rf:
userinfo = {}
for line in rf:
name, psd, remind = line.strip().split(':')
userinfo[name] = [psd, int(remind)]
if inp_name not in userinfo:
print('用户不存在')
return
if inp_name in userinfo and userinfo[inp_name][0]==inp_psd:
print('登录成功,亲爱的{}用户'.format(inp_name))
userstatus['username']=inp_name
res=func(*args, **kwargs)
return res
else:
print('账号密码错误')
return
else:
res = func(*args, **kwargs)
return res
return wrapper
def record_log(func):
'''
日志记录功能装饰器
:return:
'''
def wrapper(*args, **kwargs):
res = func(*args, **kwargs)
with open('record.log', 'ab')as log_f:
op_time = time.time()
amount = func.amount
log_f.write('{} {} {} {}
'.format(op_time, userstatus['username'], func.__name__, amount).encode('utf-8'))
return res
return wrapper
def register():
'''
注册功能
:return:
'''
with open('db.txt', 'rt', encoding='utf-8')as rf:
userinfo = {}
for line in rf:
name, psd, remind = line.strip().split(':')
userinfo[name] = [psd, int(remind)]
inp_name = input('输入注册名')
inp_psd = input('输入密码')
if inp_name in userinfo:
print('用户名已存在')
return
re_psd = input('再次输入密码')
if inp_psd == re_psd:
print('注册成功')
with open('db.txt', 'at', encoding='utf-8')as af:
af.write('{}:{}:0
'.format(inp_name, inp_psd))
else:
print('两次密码不一致')
return
@record_log
@auth
def add_credit():
'''
充值功能
:return:
'''
print('欢迎使用充值功能,亲爱的{}'.format(userstatus['username']))
with open('db.txt', 'rt', encoding='utf-8')as rf:
userinfo = {}
for line in rf:
name, psd, remind = line.strip().split(':')
userinfo[name] = [psd, int(remind)]
while True:
amount = input('请输入充值的金额').strip()
conf = input('确定要向{}用户充值{}吗,确定输入Y/y,退出N/n'.format(userstatus['username'], amount))
if conf == 'Y' or conf == 'y':
print('充值成功,已为您充值{}元'.format(amount))
userinfo[userstatus['username']][1] += int(amount)
break
elif conf == 'N' or conf == 'n':
break
with open('db.txt', 'wt', encoding='utf-8')as wf:
for name in userinfo:
wf.write('{}:{}:{}
'.format(userinfo[name], userinfo[name][0], userinfo[name][1]))
@record_log
@auth
def read():
'''
阅读小说功能
:return:
'''
pass
def logout():
'''
登出
:return:
'''
userstatus['username'] = None
return
def menu():
fuc_dic = {
'0': ('注册功能', register),
'1': ('充值功能', add_credit),
'2': ('阅读小说', read),
'3': ('登出',logout)
}
tag= True
while tag:
cmd = input('''
0 账号注册
1 充值功能
2 阅读小说
3 登出
''')
int(cmd)
if not cmd.isdigit():
print('请输入数字')
if cmd.isdigit():
fuc_dic[cmd][1]()
if cmd == 3:
tag=False
menu()