1、json、pickle、shelve三个区别是什么?

首先,这三个模块都是序列化工具。
1. json是所有语言的序列化工具,优点跨语言、体积小.只能序列化一些基本的数据类型。int\str\list\tuple\dict
pickle是python语言特有序列化工具,所有数据都能序列化。只能在python中使用,存储数据占空间大.
shelve模块是一个简单的k,v将内存数据通过文件持久化的模块,可以持久化任何pickle可支持的python数据格式。

2、json的作用是什么?

序列化,把dict,tuple,list等内存对象转换为字符串,持久化数据,存储到硬盘中或网络传输,因为网络和硬盘只接受bytes

3、为什么要设计好目录结构?

1.可读性高: 不熟悉这个项目的代码的人,一眼就能看懂目录结构,知道程序启动脚本是哪个,测试目录在哪儿,配置文件在哪儿等等。从而非常快速的了解这个项目。
2.可维护性高: 定义好组织规则后,维护者就能很明确地知道,新增的哪个文件和代码应该放在什么目录之下。这个好处是,随着时间的推移,代码/配置的规模增加,项目结构不会混乱,仍然能够组织良好。

4、打印出命令行的第一个参数。例如:

python argument.py luffy
打印出 luffy
import sys
print(sys.argv[1])

5、

'''
Linux当前目录/usr/local/nginx/html/
文件名:index.html
'''
import os
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath('index.html')))
print(BASE_DIR) 打印
/usr/local/nginx/

6、os.path.dirname和os.path.abspath含义是什么?

os.path.dirname:指定文件的目录
os.path.abspath:指定文件的绝对路径

7、通过configparser模块完成以下功能

文件名my.cnf

[DEFAULT]

 [client]
port = 3306
socket = /data/mysql_3306/mysql.sock [mysqld]
explicit_defaults_for_timestamp = true
port = 3306
socket = /data/mysql_3306/mysql.sock
back_log = 80
basedir = /usr/local/mysql
tmpdir = /tmp
datadir = /data/mysql_3306
default-time-zone = '+8:00'

修改时区 default-time-zone = '+8:00' 为 校准的全球时间 +00:00

删除 explicit_defaults_for_timestamp = true

为DEFAULT增加一条 character-set-server = utf8

import configparser
import os
config = configparser.ConfigParser()
config.read('my.cnf')
new_file = 'my.cnf%s'%('new')
with open(new_file,'w') as new_f: print(config.sections())
print(config)
# 为DEFAULT增加一条 character-set-server = utf8
config['DEFAULT']={'character-set-server':'utf8'}
# 修改时区 default-time-zone = '+8:00' 为 校准的全球时间 +00:00
config.set('mysqld','default-time-zone','+00:00')
# 删除 explicit_defaults_for_timestamp = true
config.remove_option('mysqld','explicit_defaults_for_timestamp')
config.write(new_f)
os.remove('my.cnf')
os.rename(new_file,'my.cnf')

8、写一个6位随机验证码程序(使用random模块),要求验证码中至少包含一个数字、一个小写字母、一个大写字母.、

import random
a=list(range(48,58))+list(range(65,91))+list(range(97,123))
count=0
list_code=[]
c1=random.choice(list(range(48,58)))
list_code.append(c1)
c2=random.choice(list(range(65,91)))
list_code.append(c2)
c3=random.choice(list(range(97,123)))
list_code.append(c3)
while count<3:
c=random.choice(a)
list_code.append(c)
count+=1
random.shuffle(list_code)
str_code=""
for i in list_code:
str_code+=chr(i)
print(str_code)

9、利用正则表达式提取到 luffycity.com ,内容如下

s='''

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>luffycity.com</title>
</head>
<body>
</body>
</html>
''' import re
match_s = re.findall('<title>(.*?)</title>',s)
print(match_s[0])

10、写一个用户登录验证程序,文件如下 1234.json

import json
import time
with open("1234.json","r+",encoding="utf-8") as f1:
ret=json.load(f1)
count=0
if ret.get("status")==0:
ex_t=ret.get("expire_date")
st_t=time.strptime(ex_t,"%Y-%m-%d")
c_t=time.mktime(st_t)
g_t=c_t-time.time()
if g_t>0:
while count<3:
uname=input("pls input your username:")
pwd=input("pls input your password:")
if uname =="" and pwd==ret.get("password"):
print("登录成功")
break
else:
print("用户名或密码错误,请重新输入(%s后锁定)"%(2-count))
count+=1
if count==3:
print("账号已锁定")
ret["status"]=1
with open("1234.json","w+",encoding="utf-8") as f2:
json.dump(ret,f2)
else:
print("密码已过期")
if ret.get("status")==1:
print("账号已锁定")

11、把第上一题三次验证的密码进行hashlib加密处理。即:json文件保存为md5的值,然后用md5的值进行验证。

加密密码

f ='1234.json'
fp = open(f,'r+',encoding='utf-8')
j_user = json.load(fp)
md = hashlib.md5()
md.update('abc'.encode('utf-8'))
md_pwd = md.hexdigest()
print(md_pwd)
j_user["password"] = md_pwd
fp.seek(0)
fp.truncate() # 清空文件内容
json.dump(j_user,fp) # 写入md5密码信息
fp.close()
count = 0
exit_flag = False
md = hashlib.md5() while count < 3:
user = input('输入用户名: ')
f = user.strip()+'.json'
if os.path.exists(f):
fp = open(f,'r+',encoding='utf-8')
j_user = json.load(fp)
if j_user["status"] == 1:
print('账号已经锁定')
break
else:
expire_dt = j_user["expire_date"] current_st = time.time()
expire_st = time.mktime(time.strptime(expire_dt,'%Y-%m-%d'))
# print(expire_st,current_st)
if current_st > expire_st:
print('用户已经过期')
break
else:
while count < 3:
pwd = input('输入密码: ')
md.update(pwd.strip().encode('utf-8'))
md5_pwd = md.hexdigest()
if md5_pwd == j_user["password"]:
print('用户[%s]登录成功'%user)
exit_flag = True
break
else:
print('密码不对')
if count == 2:
print('用户登录已超过3次,锁定账号')
j_user["status"] = 1
fp.seek(0)
fp.truncate() # 清空文件内容
json.dump(j_user,fp) # 写入锁定信息
fp.close() count += 1
if exit_flag:
break
else:
print('用户不存在')
count += 1

12、

  1. 最近luffy买了个tesla,通过转账的形式,并且支付了5%的手续费,tesla价格为75万。文件为json,请用程序实现该转账行为。 需求如下:

  2. 目录结构为

      .
    ├── account
    │ ├── luffy.json
    │ └── tesla.json
    └── bin
    └── start.py

当执行start.py时,出现交互窗口

    ------- Luffy Bank ---------
1. 账户信息
2. 转账
  • 选择1 账户信息 显示luffy的当前账户余额。

  • 选择2 转账 直接扣掉75万和利息费用并且tesla账户增加75万

  • 对上题增加一个需求:提现。 目录结构如下

      .
    ├── account
    │ └── luffy.json
    ├── bin
    │ └── start.py
    └── core
    └── withdraw.py

当执行start.py时,出现交互窗口

    ------- Luffy Bank ---------
1. 账户信息
2. 提现
  • 选择1 账户信息 显示luffy的当前账户余额和信用额度。

  • 选择2 提现 提现金额应小于等于信用额度,利息为5%,提现金额为用户自定义。

  • 尝试把上一章的验证用户登陆的装饰器添加到提现和转账的功能上。

  • 对第用户转账、登录、提现操作均通过logging模块记录日志,日志文件位置如下

      .
    ├── account
    │ └── luffy.json
    ├── bin
    │ └── start.py
    └── core
    | └── withdraw.py
    └── logs
    └── bank.log

 目录结构

代码 settings.py

import os

'''
日志文件设置
'''
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
LOG_LEVEL='INFO'
LOG_FILE='bank.log' '''
交易类型
'''
TRANS_TYPE={
'withdraw':{'interest':0.05,'action':'minus'},
'transfer': {'interest': 0.05, 'action': 'minus'}
} print(BASE_DIR)

代码 my_logset.py

import logging
import os
from conf import settings # 日志格式
log_format = '[%(asctime)s - %(levelname)s - %(name)s - %(filename)s - %(lineno)d ] %(message)s ' def get_mylogger(name):
"""
get log
:param name:
:return:
"""
logger = logging.getLogger(name)
logger.setLevel(settings.LOG_LEVEL) console_handler = logging.StreamHandler()
# 文件绝对路径
logfile_path = os.path.join(settings.BASE_DIR, 'log',settings.LOG_FILE)
file_handler = logging.FileHandler(logfile_path) logger.addHandler(console_handler)
logger.addHandler(file_handler) file_format = logging.Formatter(fmt=log_format)
console_format = logging.Formatter(fmt=log_format, datefmt='%Y-%m-%d %H:%M:%S ') console_handler.setFormatter(console_format)
file_handler.setFormatter(file_format) return logger if __name__ == '__main__':
log = get_mylogger('access')
log.info('access')
log.error('Error') log1 = get_mylogger('trans')
log1.info('trans')

代码 auth.py

import json
import time
import os
from conf import settings
from log import my_logset
from functools import wraps # logger = my_logset.get_mylogger('access') def login_required(func):
"""
登录认证装饰器
:param func:
:return:
"""
@wraps(func)
def wrapper(*args,**kwargs):
# print(args[0].get('is_authenticated'))
if args[0].get('is_authenticated'):
print('execute %s'%func.__name__)
res = func(*args, **kwargs)
else:
exit('user is not authenticated')
return res return wrapper def acc_login(user, pwd,logger):
"""
用户登录
:param log_obj:
:return:
"""
# 账号文件
account_file = os.path.join(settings.BASE_DIR,'account','%s.json'%user)
if os.path.isfile(account_file):
user_fp = open(account_file,'r',encoding='utf-8')
account_data = json.load(fp=user_fp)
if account_data["password"] == pwd:
exp_time_stamp = time.mktime(time.strptime(account_data["expire_date"],'%Y-%m-%d'))
status = account_data['status']
if time.time() > exp_time_stamp:
msg = 'Account [%s] has expired,please contact the back to get a new card!' % user
logger.error(msg) elif status != 0:
msg = 'Account [%s] has frozen' % user
logger.error(msg) else:
logger.info('***********欢迎{}登录***********'.format(user))
return account_data
else:
logger.error("Account ID or password is incorrect!")
else:
msg = "Account [%s] does not exist!" % user
logger.error(msg) def auth_acc(user_data,logger):
"""
用户登录
:return:
"""
retry_count = 0
if user_data['is_authenticated'] is not True:
while retry_count < 3:
user = input('input username: ').strip()
pwd = input('input password: ').strip() acc_data = acc_login(user, pwd,logger)
if acc_data:
user_data['is_authenticated'] = True
return acc_data retry_count +=1
else:
exit("account too many login attempts" ) if __name__ == '__main__':
logger = my_logset.get_mylogger('access')
user_data = {'is_authenticated':False}
auth_acc(user_data,logger)

代码 main.py

import os
import json
from core import auth
from core.auth import login_required
from conf import settings
from log import my_logset user_data = {
'user_id':None,
'is_authenticated':False,
'user':None
} # transaction logger
trans_logger = my_logset.get_mylogger('transaction')
# access logger
access_logger = my_logset.get_mylogger('access') @login_required
def account_info(user_data):
"""
print acoount_info
:param acc_data:
:return:
"""
curr_data = user_data['user']
current_user = '''
--------- USER INFO --------
user_id: {}
Credit : {}
Balance: {}
expire_date: {}
----------------------------------
'''.format(curr_data['id'], curr_data['credit'], curr_data['balance'],curr_data['expire_date'])
access_logger.info(current_user) @login_required
def withdraw(user_data):
""" print current balance and let user do the withdraw action
:param user_data:
:return:
"""
curr_data = user_data['user']
back_flag = False
while not back_flag:
withdraw_amount = input("Input withdraw amount:").strip()
if withdraw_amount.isdigit():
old_bal = curr_data['balance']
curr_data['balance'] = old_bal - float(withdraw_amount)*settings.TRANS_TYPE['withdraw']['interest']
if curr_data['balance']:
msg = "New Balance:%s" % (curr_data['balance'])
trans_logger.info(msg)
save_data(curr_data)
elif withdraw_amount == 'b':
back_flag = True
else:
msg = "[%s] is not a valid amount, only accept integer!" % withdraw_amount
trans_logger.error(msg) @login_required
def transfer(user_data):
"""
print current balance and let user do the transfer action
:param user_data:
:return:
"""
curr_data = user_data['user']
back_flag = False
while not back_flag:
transfer_amount = input("Input transfer amount:").strip()
tesla_data = get_data('tesla') # 得到转账人的信息
if transfer_amount.isdigit():
transfer_amount = float(transfer_amount) # 转账金额转化float
old_bal = curr_data['balance']
new_tesla_bal = tesla_data['balance'] + transfer_amount # 得到转账人的余额
curr_data['balance'] = old_bal - float(transfer_amount) * settings.TRANS_TYPE['withdraw']['interest']
tesla_data['balance'] = new_tesla_bal
if curr_data['balance']:
msg = "New Balance: %s new_tesla_bal: %s " % (curr_data['balance'], new_tesla_bal)
trans_logger.info(msg)
# 保存数据
save_data(curr_data)
save_data(tesla_data)
elif transfer_amount == 'b':
back_flag = True
else:
msg = "[%s] is not a valid amount, only accept integer!" % transfer_amount
trans_logger.error(msg) def logout(user_data):
"""
user logout
:param acc_data:
:return:
"""
msg = "%s logout" % user_data['user_id']
user_data['is_authenticated']= False def save_data(acc_data):
"""
保存acc_data
:param acc_data:
:return:
"""
file = os.path.join(settings.BASE_DIR,'account',acc_data['id']+'.json')
user_fp = open(file,'w',encoding='utf-8')
print('save_data: ',file, acc_data)
json.dump(acc_data,user_fp,ensure_ascii=False)
user_fp.close() def get_data(user_id):
"""
得到acc_data
:param user_id:
:return:
"""
file = os.path.join(settings.BASE_DIR, 'account', user_id+'.json')
user_fp = open(file, 'r', encoding='utf-8')
acc_data = json.load(user_fp)
user_fp.close()
return acc_data def interactive(acc_data): '''
interact with user
:return:
'''
menu = """
------- Bank ---------
1. 账户信息(功能已实现)
2. 取款(功能已实现)
3. 转账(功能已实现)
4. 用户退出(功能已实现)
"""
menu_dic = {
'': account_info,
'': withdraw,
'': transfer,
'': logout,
}
exit_flag = False
while not exit_flag:
print(menu)
user_option = input(">>:").strip()
if user_option in menu_dic:
# print('accdata', acc_data)
# print(menu_dic[user_option], acc_data)
menu_dic[user_option](acc_data)
else:
print("Option does not exist!", "error")
exit_flag = True def run():
'''
this function will be called right a way when the program started, here handles the user interaction stuff
:return:
'''
acc_data = auth.auth_acc(user_data,access_logger)
# print(acc_data)
# 如果用户认证成功
if user_data['is_authenticated']:
user_data['user'] = acc_data
user_data['user_id'] = acc_data.get('id')
interactive(user_data) if __name__ == '__main__':
run()
# print(a[0])

代码 start.py

import sys,os

BASE_DIR=os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(BASE_DIR) # 加入环境变量 from core import main as m if __name__ == '__main__':
m.run()

 

python练习题-day20的更多相关文章

  1. Python练习题 028:求3*3矩阵对角线数字之和

    [Python练习题 028] 求一个3*3矩阵对角线元素之和 ----------------------------------------------------- 这题解倒是解出来了,但总觉得 ...

  2. Python练习题 027:对10个数字进行排序

    [Python练习题 027] 对10个数字进行排序 --------------------------------------------- 这题没什么好说的,用 str.split(' ') 获 ...

  3. Python练习题 026:求100以内的素数

    [Python练习题 026] 求100以内的素数. ------------------------------------------------- 奇怪,求解素数的题,之前不是做过了吗?难道是想 ...

  4. Python练习题 025:判断回文数

    [Python练习题 025] 一个5位数,判断它是不是回文数.即12321是回文数,个位与万位相同,十位与千位相同. ---------------------------------------- ...

  5. Python练习题 024:求位数及逆序打印

    [Python练习题 024] 给一个不多于5位的正整数,要求:一.求它是几位数,二.逆序打印出各位数字. ---------------------------------------------- ...

  6. Python练习题 004:判断某日期是该年的第几天

    [Python练习题 004]输入某年某月某日,判断这一天是这一年的第几天? ---------------------------------------------- 这题竟然写了 28 行代码! ...

  7. Python练习题-1.使用匿名函数对1~1000求和,代码力求简洁。

    Python 练习 标签(空格分隔): Python Python练习题 Python知识点 一.使用匿名函数对1~1000求和,代码力求简洁. 答案: In [1]: from functools ...

  8. PYTHON练习题 二. 使用random中的randint函数随机生成一个1~100之间的预设整数让用户键盘输入所猜的数。

    Python 练习 标签: Python Python练习题 Python知识点 二. 使用random中的randint函数随机生成一个1~100之间的预设整数让用户键盘输入所猜的数,如果大于预设的 ...

  9. python 基础 2.8 python练习题

    python 练习题:   #/usr/bin/python #coding=utf-8 #@Time   :2017/10/26 9:38 #@Auther :liuzhenchuan #@File ...

随机推荐

  1. 将DataTable转换为List<T>对象遇到问题:类型“System.Int64”的对象无法转换为类型“System.Int32”。

    可以利用反射将DataTable转换为List<T>对象:原始链接http://www.jb51.net/article/67386.htm 但是该方法在DataTable里某个字段类型是 ...

  2. bzoj 2028(会场预约)

    题目描述 PP大厦有一间空的礼堂,可以为企业或者单位提供会议场地. 这些会议中的大多数都需要连续几天的时间(个别的可能只需要一天),不过场地只有一个,所以不同的会议的时间申请不能够冲突.也就是说,前一 ...

  3. 一分30秒 kali 开机显示 a start job is running for dev-disk 处理

    在给kali虚拟机扩容后,使用fdisk  /dev/sda  更改新建分区后,重启系统出现一分30秒等待. 解决方案:    (root 权限) 第一步:sudo blkid (查看当前系统的真实的 ...

  4. CSS之分组选择器和嵌套选择器

    分组选择器, 将一个样式应用于多个类,或者标签啥的 每个选择器用逗号隔开 <!DOCTYPE html> <html> <head> <meta charse ...

  5. Win10安装java环境

    window系统安装java 一.下载JDK 1.首先需要下载java开发工具包JDK,下载地址:http://www.oracle.com/technetwork/java/javase/downl ...

  6. ansible的delegate_to、connection、和local_action

    由于工作需要,经常需要把目标节点获得的信息写入执行节点文件日志. 所以经常用到delegate_to和connection,而local_action写法难看,基本不用. delegate_to和co ...

  7. git生成ssh key步骤并添加到github网站

    0: 查看是否已经有了ssh密钥 执行命令:cd ~/.ssh 如果没有密钥则不会有此文件夹,有则备份删除 1:使用 Git Bash生成新的ssh key ssh-keygen -t rsa -C  ...

  8. MyString

    [摘自C++程序设计语言] MyString.h #include <cstring> #include <iostream> #include <stdexcept&g ...

  9. Android数据存储引擎---SQLite数据库

    目标:是否可以在PC端桌面上使用SQLite数据库制作一个财务文件? 目录: 来源: 实践: 总结和比较: SQLite数据简介 是什么,内部结构是怎样的,数据库和表的关系是什么 有什么用 常用的操作 ...

  10. VB开发类似IIS简易的WebServer,代码不到100行

    最近遇到三个人问关于VB写网页服务器的问题,所以今天抽时间写一下,演示其实没有多复杂. 代码里自定义的方法只有四个,没有公共变量绕来绕去,该注释的也都注释了. 想扩展更复杂的功能,就需要自己补脑HTT ...