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、
最近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萬
對上題增加一個需求:提現。 目錄結構如下
.
├── 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()