函数模块练习

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")
View Code
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'))
View Code
[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)
View Code
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("用户已经被锁定")
View Code

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()
View Code

练习总结:

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对文件进行定义的时候,要指定字符编码。



posted @ 2018-03-05 15:18  Mr。yang  阅读(465)  评论(0编辑  收藏  举报