1.logging模塊有幾個日誌級別?html
#INFO,WARNING,DEBUG,CRITICAL,ERROR
2.請配置logging模塊,使其在屏幕和文件裏同時打印如下格式的日誌python
2017-10-18 15:56:26,613 - access - ERROR - account [1234] too many login attempts
代碼mysql
import logging from logging import handlers logger = logging.getLogger('access') logger.setLevel(logging.ERROR) ch = logging.StreamHandler() fh = handlers.TimedRotatingFileHandler(interval=1,when='D',filename='web.log', backupCount=10) logger.addHandler(fh) logger.addHandler(ch) file_format = logging.Formatter(fmt='%(asctime)s - %(name)s - %(levelname)s - %(message)s') ch.setFormatter(file_format) fh.setFormatter(file_format) logger.error('account [1234] too many login attempts')
3.json、pickle、shelve三個區別是什麼?
nginx
首先,這三個模塊都是序列化工具。 1. json是全部語言的序列化工具,優勢跨語言、體積小.只能序列化一些基本的數據類型。int\str\list\tuple\dict pickle是python語言特有序列化工具,全部數據都能序列化。只能在python中使用,存儲數據佔空間大. shelve模塊是一個簡單的k,v將內存數據經過文件持久化的模塊,能夠持久化任何pickle可支持的python數據格式。
4.json的做用是什麼?git
序列化,把dict,tuple,list等內存對象轉換爲字符串,持久化數據,存儲到硬盤中或網絡傳輸,由於網絡和硬盤只接受bytes
5.subprocess執行命令方法有幾種?web
run()方法
call()方法
Popen()方法
6.爲何要設計好目錄結構?正則表達式
1.可讀性高: 不熟悉這個項目的代碼的人,一眼就能看懂目錄結構,知道程序啓動腳本是哪一個,測試目錄在哪兒,配置文件在哪兒等等。從而很是快速的瞭解這個項目。 2.可維護性高: 定義好組織規則後,維護者就能很明確地知道,新增的哪一個文件和代碼應該放在什麼目錄之下。這個好處是,隨着時間的推移,代碼/配置的規模增長,項目結構不會混亂,仍然可以組織良好。
7.打印出命令行的第一個參數。例如:sql
python argument.py luffy 打印出 luffy import sys print(sys.argv[1])
8.如下代碼json
''' 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/
9.os.path.dirname和os.path.abspath含義是什麼?bash
os.path.dirname:指定文件的目錄
os.path.abspath:指定文件的絕對路徑
10.經過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')
11.寫一個6位隨機驗證碼程序(使用random模塊),要求驗證碼中至少包含一個數字、一個小寫字母、一個大寫字母.
import random import string code_li = [] code_li.append(random.choice(string.ascii_lowercase)) code_li.append(random.choice(string.digits)) code_li.append(random.choice(string.ascii_uppercase)) while len(code_li) < 6: code_li.append(random.choice(string.digits+string.ascii_lowercase+string.ascii_uppercase)) print(code_li) q_code=''.join(code_li) print(q_code)
12.利用正則表達式提取到 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])
13.寫一個用戶登陸驗證程序,文件以下 1234.json
1234.json
{"expire_date": "2021-01-01", "id": 1234, "status": 0, "pay_day": 22, "password": "abc"}
''' 寫一個用戶登陸驗證程序,文件以下 1234.json 用戶名爲json文件名,密碼爲 password。 判斷是否過時,與expire_date進行對比。 登錄成功後,打印「登錄成功」,三次登錄失敗,status值改成1,而且鎖定帳號。 ''' import json import os import time import hashlib count = 0 exit_flag =False 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('輸入密碼: ') if pwd.strip() == 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) # 寫入鎖定信息 count += 1 if exit_flag: break else: print('用戶不存在') count += 1
14. 把第13題三次驗證的密碼進行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
15.
目錄結構爲
.
├── 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%,提現金額爲用戶自定義。
嘗試把上一章的驗證用戶登錄的裝飾器添加到提現和轉帳的功能上。
對第15題的用戶轉帳、登陸、提現操做均經過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
#!/usr/bin/python # -*- coding: utf-8 -*- # @Time : 2018/4/23 8:55 # @Author : hyang # @File : my_logset.py # @Software: PyCharm 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
#!/usr/bin/env python # -*- coding: utf-8 -*- # @Time : 2018/5/14 22:57 # @Author : hyang # @Site : # @File : auth.py # @Software: PyCharm 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
#!/usr/bin/env python # -*- coding: utf-8 -*- # @Time : 2018/5/14 23:55 # @Author : hyang # @Site : # @File : main.py # @Software: PyCharm 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 = { '1': account_info, '2': withdraw, '3': transfer, '4': 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()