函数模块练习
1.logging模块有几个日志级别?
分为4个级别,分别是debug,info,warning,error,critical,默认级别是warning
2.请配置logging模块,使其在屏幕和文件里同时打印以下格式的日志
2017-10-18 15:56:26,613 - access - ERROR - account [1234] too many login attempts
import logging from logging import handlers # 2017-10-18 15:56:26,613 - access - ERROR - account [1234] too many login attempts #1.生成 logger对象 logger = logging.getLogger("account") #2.生成 handler对象 #向屏幕输出 ch = logging.StreamHandler() #向文件输出 fh = handlers.TimedRotatingFileHandler("log.log") #2.1 把 handler对象 绑定到logger logger.addHandler(ch) logger.addHandler(fh) file_formatter = logging.Formatter("%(asctime)s - accesss - %(levelname)s - %(name)s [%(thread)d] %(message)s") console_formatter = logging.Formatter("%(asctime)s - accesss - %(levelname)s - %(name)s [%(thread)d] %(message)s") #3.生成formatter对象 #3.1 把formatter对象 绑定到hander对象 ch.setFormatter(console_formatter) fh.setFormatter(file_formatter) logger.error("too many login attempts")
3.json、pickle、shelve三个区别是什么?
json 支持的序列化类型: str,int,dict,list,tuple
pickle 支持python中的所有数据类型
shelve 可以持久化python中的任何数据类型
4.json的作用是什么?
可以将内存中的数据类型 转为字符串的形式写到硬盘中, 硬盘只能接受bytes类型
5.subprocess执行命令方法有几种?
三种
第一,subprocess.run()
第二,subprocess.call()
第三,subprocess.Popen()
6.为什么要设计好目录结构?
可以让项目的可读性大大提高,有利于以后的维护
7.打印出命令行的第一个参数。例如:
python argument.py luffy
打印出 luffy
E:\Moudule_1\2.函数编程\模块基础\模块_课后练习\mod_sys\argument.py
import sys
print(sys.argv[1:])
8.
'''
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
os.path.dirname和os.path.abspath含义是什么
os.path.dirname是返回文件一层路径
os.path.abspath是返回文件的绝对路径
9.通过configparser模块完成以下功能
# #修改时区 default-time-zone = '+8:00' 为 校准的全球时间 +00:00
# #删除 explicit_defaults_for_timestamp
# #为DEFAULT增加一条 character-set-server = utf8
import configparser # # 修改时区 default-time-zone = '+8:00' 为 校准的全球时间 +00:00 # # 删除 explicit_defaults_for_timestamp # # 为DEFAULT增加一条 character-set-server = utf8 conf = configparser.ConfigParser() conf.read('my.cnf') conf.remove_option("mysqld","explicit_defaults_for_timestamp") conf.set("DEFAULT","character-set-server","utf8") conf["mysqld"]["default-time-zone"] = "+00:00" conf.write(open("my.cnf",'w'))
[DEFAULT] [client] port = 3306 socket = /data/mysql_3306/mysql.sock [mysqld] explicit_defaults_for_timestamp = 0 port = 3306 socket = /data/mysql_3306/mysql.sock back_log = 80 basedir = /usr/local/mysql tmpdir = /tmp datadir = /data/mysql_3306 default-time-zone = +00:00
10.写一个6位随机验证码程序(使用random模块),要求验证码中至少包含一个数字、一个小写字母、一个大写字母.
import string,random def func(character): return random.sample(character,2) a = string.ascii_lowercase A = string.ascii_uppercase sum = string.digits a1 = func(a) A1 = func(A) sum1 = func(sum) add = a1+A1+sum1 random.shuffle(add) print(add)
11.利用正则表达式提取到 luffycity.com ,内容如下
<!DOCTYPE html>
<html lang="en">
<head>
<meta >luffycity.com<charse>
<title>luffycity.com</title>
</head>
<body>
</body>
</html>
import re f = open("str",'r',encoding="utf-8") data = f.read() print(data) s = re.search("\w+\.com",data).group()
12.写一个用户登录验证程序,文件如下
1234.json
{"expire_date": "2021-01-01", "id": 1234, "status": 0, "pay_day": 22, "password": "abc"}
用户名为json文件名,密码为 password。
判断是否过期,与expire_date进行对比。
登陆成功后,打印“登陆成功”,三次登陆失败,status值改为1,并且锁定账号。
13把第12题三次验证的密码进行hashlib加密处理。即:json文件保存为md5的值,然后用md5的值进行验证。
import time,datetime,hashlib import json file_name = "1234.json" user_file = open(file_name,"r+",encoding="utf-8") lock_file = open("user_lock.txt","r+",encoding="utf-8") user = user_file.read()# 读取用户文件中的所有内容 lock = lock_file.read()# 读取锁定文件中的所有内容 file_dict = json.loads(user)#将json中的字符变为原有的数据类型 old_time = file_dict["expire_date"] new_time = time.strftime("%Y-%m-%d",time.localtime()) user_name = file_name.split('.')[0] #密码md5加密 def md5(str): import hashlib m = hashlib.md5() m.update(str) return m.hexdigest() if old_time < new_time: print("用户已经过期") exit() if user_name in lock: print("用户已经被锁定") exit() else: count = 0 print("---用户可以正常使用---") while count < 3: password = input("Password:") password_md5 = md5(bytes(password,encoding="utf-8")) # print(password_md5) if password_md5 == file_dict["password"]: print("登陆成功") break else: print("密码错误,请重新输入") count += 1 if count == 3: lock_file.write(user_name + ',') file_dict["status"] = "1" user_file.seek(0) user_file.truncate() new_flie_dict = json.dumps(file_dict) user_file.write(new_flie_dict) user_file.close() lock_file.close() print("用户已经被锁定")
14.最近luffy买了个tesla,通过转账的形式,并且支付了5%的手续费,tesla价格为75万。文件为json,请用程序实现该转账行为。
需求如下:
目录结构为
.
├── account
│ ├── luffy.json
│ └── tesla.json
└── bin
└── start.py
当执行start.py时,出现交互窗口
------- Luffy Bank ---------
1. 账户信息
2. 转账
选择1 账户信息 显示luffy的当前账户余额。
选择2 转账 直接扣掉75万和利息费用并且tesla账户增加75万
15对上题增加一个需求:提现。
目录结构如下
.
├── account
│ └── luffy.json
├── bin
│ └── start.py
└── core
└── withdraw.py
当执行start.py时,出现交互窗口
------- Luffy Bank ---------
1. 账户信息
2. 提现
选择1 账户信息 显示luffy的当前账户余额和信用额度。
选择2 提现 提现金额应小于等于信用额度,利息为5%,提现金额为用户自定义。
16尝试把上一章的验证用户登陆的装饰器添加到提现和转账的功能上。
17.对第15题的用户转账、登录、提现操作均通过logging模块记录日志,日志文件位置如下
.
├── account
│ └── luffy.json
├── bin
│ └── start.py
└── core
| └── withdraw.py
└── logs
└── bank.log
import os import sys import json import logging from logging import handlers logger = logging.getLogger("账户信息") user_status = False main_path = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))#获取到进程的全局变量 # print(main_path) sys.path.append(main_path) from core import withdraw json_path = os.path.join(main_path, 'account')#通过全局变量,连接目录和文件 #print(json_path)2 print("------- Luffy Bank -------") info = """ 1.账户信息 2.转账 3.提现 """ def log_file(): global logger # 可以改变logger变量 logger.setLevel(logging.DEBUG) # 设置日志的文件级别 fh = logging.handlers.TimedRotatingFileHandler(filename=os.path.join(main_path,'logs/bank.log'),encoding="utf-8") logger.addHandler(fh) # 将handler绑定到logger上 formator_file = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s',datefmt='%Y-%m-%d %I:%M:%S %p') fh.setFormatter(formator_file)# 把formator绑定到handler上 def login(user): def inner(*arg,**kwargs): _username = "yang" _password = "1234" global user_status if user_status == False: username = input("Username:") password = input("Password:") if username == _username and password == _password: print("恭喜你登陆成功") user_status = True logger.debug("恭喜你登陆成功") else: print("wrong username and password!") logger.error("wrong username and password!") else: print("用户已登陆,验证成功!") if user_status == True: user(*arg,**kwargs) return inner def user_info(): # 账户信息 luffy_data = json.load(open(os.path.join(json_path, 'luffy.json'), 'r', encoding='utf-8')) print('account_balance:', luffy_data['balance']) # print('credit_account:', luffy_data['credit_account']) @login def transfer(): #转账 luffy_file = json.load(open(os.path.join(json_path, 'luffy.json'), 'r+', encoding='utf-8')) new_tesal_file = open(os.path.join(json_path, 'tesal.json'), 'r+', encoding='utf-8') tesal_file = json.load(new_tesal_file) luffy_balance = int(luffy_file["balance"]) # 现有余额 tesal_price = int(tesal_file["price"]) new_luffy_balance = luffy_balance-luffy_balance * 0.05 - tesal_price # 购买特斯拉后剩下的余额 new_tesal_file.seek(0) new_tesal_file.truncate() tesal_file["blance"] += tesal_price json.dump(tesal_file,new_tesal_file)# 将数据类型转为字符串 print("转账成功") new_tesal_file.close() logger.debug('转账成功') @login def withdrawal_sum(): #提现 money = input("Input your money:").strip() if money.isdigit(): money = int(money) withdraw.withdraw_1(money,json_path,logger) def main(): print(info) user_chiose = input(">>:") if user_chiose.isdigit(): user_chiose = int(user_chiose) #如果不成立 则退出循环 if user_chiose == 1: user_info() elif user_chiose == 2: transfer() elif user_chiose == 3: withdrawal_sum() elif user_chiose == 'q': exit() log_file() main()
练习总结:
1.在账户信息处理的练习中,对于os模块中的os.path.dirname,os.path.abspath,os.path.join的使用不够熟练,还对于sys模块中的sys.path.append.
2.在执行start.py文件的时候,想要对别的模块中的文件进行处理,就要通过os.path.abspath获取到文件的绝对路径,并且通过os.path.dirname返回模块的上一级。
3.在对转账和提现添加装饰器的时候,应注意对标识符等于True的时候,要执行返回的函数名,对其函数进行处理
4.文件日志中在用logging.handlers.TimeRotatingFileHandler对文件进行定义的时候,要指定字符编码。