python项目练习

时间:2023-03-09 16:45:09
python项目练习

程序框图 (消费模块暂未写入)

python项目练习

bin:程序执行


 import os
import sys
base_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
print(base_dir)
sys.path.append(base_dir) from core import main if __name__ == '__main__': #当作为脚本直接运行的时候,此时__name__等于__main__,当作为模块导入的时候,__name__为文件名但不带.py,故不运行if后语句。
main.run()

atm.py

config:配置文件


 import os
import sys
import logging
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) DATABASE = {
'engine': 'file_storage', #support mysql,postgresql in the future
'name':'accounts',
'path': "%s/db" % BASE_DIR
} LOG_LEVEL = logging.INFO
LOG_TYPES = {
'transaction': 'transactions.log',
'access': 'access.log',
'':'11111.log'
} TRANSACTION_TYPE = {
'repay':{'action':'plus', 'interest':0},
'withdraw':{'action':'minus', 'interest':0.05},
'transfer':{'action':'minus', 'interest':0.05},
'consume':{'action':'minus', 'interest':0},
}

settings

core:程序主要代码


 import json
import time
from core import db_handler
from conf import settings def load_current_balance(account_id):
'''
return account balance and other basic info
:param account_id:
:return:
'''
db_path = db_handler.db_handler(settings.DATABASE)
account_file = "%s/%s.json" %(db_path,account_id)
with open(account_file) as f:
acc_data = json.load(f)
return acc_data
def dump_account(account_data):
'''
after updated transaction or account data , dump it back to file db
:param account_data:
:return:
'''
db_path = db_handler.db_handler(settings.DATABASE)
account_file = "%s/%s.json" %(db_path,account_data['id'])
with open(account_file, 'w') as f:
acc_data = json.dump(account_data,f) return True

accounts

 import os
from core import db_handler
from conf import settings
from core import logger
import json
import time def acc_auth(account,password):
'''
account auth func
:param account: credit account number
:param password: credit card password
:return: if passed the authentication , retun the account object, otherwise ,return None
'''
db_path = db_handler.db_handler(settings.DATABASE)
account_file = "%s/%s.json" %(db_path,account)
print(account_file) #base_dir + accounts + account.json
if os.path.isfile(account_file): #判断文件名是否存在,存在执行下面语句
with open(account_file,'r') as f:
account_data = json.load(f)
if account_data['password'] == password:
exp_time_stamp = time.mktime(time.strptime(account_data['expire_date'], "%Y-%m-%d"))
if time.time() >exp_time_stamp:
print("\033[31;1mAccount [%s] has expired,please contact the back to get a new card!\033[0m" % account)
else: #passed the authentication
return account_data
else:
print("\033[31;1mAccount ID or password is incorrect!\033[0m")
else:
print("\033[31;1mAccount [%s] does not exist!\033[0m" % account) def acc_login(user_data,log_obj):
'''
account login func
:user_data: user info data , only saves in memory
:return:
'''
retry_count = 0
while user_data['is_authenticated'] is not True and retry_count < 3 :
account = input("\033[32;1maccount:\033[0m").strip()
password = input("\033[32;1mpassword:\033[0m").strip()
auth = acc_auth(account, password)
if auth: #not None means passed the authentication
user_data['is_authenticated'] = True
user_data['account_id'] = account
#print("welcome")
return auth
retry_count +=1
else:
log_obj.error("account [%s] too many login attempts" % account)
exit()

登陆认证

 def file_db_handle(conn_params):
'''
parse the db file path
:param conn_params: the db connection params set in settings
:return:
'''
print('file db:',conn_params)
db_path ='%s/%s' %(conn_params['path'],conn_params['name'])
return db_path def mysql_db_handle(conn_parms):
pass
def db_handler(conn_parms):
'''
connect to db
:param conn_parms: the db connection params set in settings
:return:a
''' if conn_parms['engine'] == 'file_storage':
return file_db_handle(conn_parms) if conn_parms['engine'] == 'mysql':
return mysql_db_handle(conn_parms)

数据存储路径

 import logging
from conf import settings def logger(log_type): #create logger
logger = logging.getLogger(log_type)
logger.setLevel(settings.LOG_LEVEL) # create console handler and set level to debug
ch = logging.StreamHandler()
ch.setLevel(settings.LOG_LEVEL) # create file handler and set level to warning
log_file = "%s/log/%s" %(settings.BASE_DIR, settings.LOG_TYPES[log_type])
fh = logging.FileHandler(log_file)
fh.setLevel(settings.LOG_LEVEL)
# create formatter
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') # add formatter to ch and fh
ch.setFormatter(formatter)
fh.setFormatter(formatter) # add ch and fh to logger
logger.addHandler(ch)
logger.addHandler(fh) return logger

日志

 from core import auth
from core import accounts
from core import logger
from core import accounts
from core import transaction
import time #transaction logger
trans_logger = logger.logger('transaction')
#access logger
access_logger = logger.logger('access') #temp account data ,only saves the data in memory
user_data = {
'account_id':None,
'is_authenticated':False,
'account_data':None } def account_info(acc_data):
print(user_data)
def repay(acc_data):
'''
print current balance and let user repay the bill
:return:
'''
account_data = accounts.load_current_balance(acc_data['account_id']) #获取用户id,就是要用实时的最新数据,为了安全
#for k,v in account_data.items():
# print(k,v )
current_balance= ''' --------- BALANCE INFO --------
Credit : %s
Balance: %s''' %(account_data['credit'],account_data['balance'])
print(current_balance)
back_flag = False
while not back_flag:
repay_amount = input("\033[33;1mInput repay amount:\033[0m").strip()
if len(repay_amount) >0 and repay_amount.isdigit():
#print('ddd 00')
new_balance = transaction.make_transaction(trans_logger,account_data,'repay', repay_amount)
if new_balance:
print('''\033[42;1mNew Balance:%s\033[0m''' %(new_balance['balance'])) else:
print('\033[31;1m[%s] is not a valid amount, only accept integer!\033[0m' % repay_amount) if repay_amount == 'b':
back_flag = True
def withdraw(acc_data):
'''
print current balance and let user do the withdraw action
:param acc_data:
:return:
'''
account_data = accounts.load_current_balance(acc_data['account_id'])
current_balance= ''' --------- BALANCE INFO --------
Credit : %s
Balance: %s''' %(account_data['credit'],account_data['balance'])
print(current_balance)
back_flag = False
while not back_flag:
withdraw_amount = input("\033[33;1mInput withdraw amount:\033[0m").strip()
if len(withdraw_amount) >0 and withdraw_amount.isdigit():
new_balance = transaction.make_transaction(trans_logger,account_data,'withdraw', withdraw_amount) # new_balance就是 函数返回值 acount_data
if new_balance:
print('''\033[42;1mNew Balance:%s\033[0m''' %(new_balance['balance'])) else:
print('\033[31;1m[%s] is not a valid amount, only accept integer!\033[0m' % withdraw_amount) if withdraw_amount == 'b':
back_flag = True def transfer(acc_data):
pass
def pay_check(acc_data):
pass
def logout(acc_data):
pass
def interactive(acc_data):
'''
interact with user
:return:
'''
menu = u'''
------- Oldboy Bank ---------
\033[32;1m1. 账户信息
2. 还款(功能已实现)
3. 取款(功能已实现)
4. 转账
5. 账单
6. 退出
\033[0m'''
menu_dic = {
'': account_info,
'': repay,
'': withdraw,
'': transfer,
'': pay_check,
'': logout,
}
exit_flag = False
while not exit_flag:
print(menu)
user_option = input(">>:").strip()
if user_option in menu_dic:
menu_dic[user_option](acc_data) #比如选择了2 ,则运行 repay(acc_data),调用repay函数 else:
print("\033[31;1mOption does not exist!\033[0m")
def run():
'''
this function will be called right a way when the program started, here handles the user interaction stuff
:return:
'''
acc_data = auth.acc_login(user_data,access_logger) #userdata作为条件,access_logger作为日志信息传入
if user_data['is_authenticated']:
user_data['account_data'] = acc_data #acc_data 即是用户信息 1234.json
interactive(user_data) #交互

主程序

 from conf import settings
from core import accounts
from core import logger
#transaction logger def make_transaction(log_obj,account_data,tran_type,amount,**others):
'''
deal all the user transactions
:param account_data: user account data
:param tran_type: transaction type
:param amount: transaction amount
:param others: mainly for logging usage
:return:
'''
amount = float(amount)
if tran_type in settings.TRANSACTION_TYPE: interest = amount * settings.TRANSACTION_TYPE[tran_type]['interest']
old_balance = account_data['balance']
if settings.TRANSACTION_TYPE[tran_type]['action'] == 'plus':
new_balance = old_balance + amount + interest
elif settings.TRANSACTION_TYPE[tran_type]['action'] == 'minus':
new_balance = old_balance - amount - interest
#check credit
if new_balance <0:
print('''\033[31;1mYour credit [%s] is not enough for this transaction [-%s], your current balance is
[%s]''' %(account_data['credit'],(amount + interest), old_balance ))
return
account_data['balance'] = new_balance
accounts.dump_account(account_data) #save the new balance back to file
log_obj.info("account:%s action:%s amount:%s interest:%s" %
(account_data['id'], tran_type, amount,interest) )
return account_data
else:
print("\033[31;1mTransaction type [%s] is not exist!\033[0m" % tran_type)

交易种类

db:用户信息存储


 {"id": "gkx", "password": "", "credit": 15000, "balance": 15000, "enroll_date": "2016-01-02", "expire_date": "2021-01-01", "pay_day": 22, "status": 0}