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

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}

python项目练习的更多相关文章

  1. 给缺少Python项目实战经验的人

    我们在学习过程中最容易犯的一个错误就是:看的多动手的少,特别是对于一些项目的开发学习就更少了! 没有一个完整的项目开发过程,是不会对整个开发流程以及理论知识有牢固的认知的,对于怎样将所学的理论知识应用 ...

  2. 正确地组织python项目的结构

    统一的项目结构 写了不少python项目后, 越来越认识到python项目结构重要性. 不管项目是否要开源, 是否要提交pypi, 项目结构的一致性带来的好处还有很多: 多人合作开发大家都有个基本的g ...

  3. eclipse中建python项目并运行

    1. Help → Install New Software 2.Enter http://pydev.org/updates 3.点击Click "Next" and " ...

  4. 使用 tox flake8 pytest 规范 python 项目

    使用 tox flake8 pytest 规范 python 项目 python 中有些很好的工作来规范整个项目的开发,而其中使用较多的就是使用 tox . flake8 . pytest . tox ...

  5. 2013流行Python项目汇总

    2013流行Python项目汇总 转自:http://www.kankanews.com/ICkengine/archives/102963.shtml Python作为程序员的宠儿,越来越得到人们的 ...

  6. python项目

    python实战项目: http://www.the5fire.com/category/python实战/ python基础教程中的十个项目: python项目练习一:即时标记 python项目练习 ...

  7. Eclipse开发Python项目

    最近倒腾python自带的开发工具idle,用的很不习惯,还是用Eclipse编写python项目方便(自动补齐,智能报错,调试方便),下面就说说怎么用Eclipse编写python代码吧~ 1.安装 ...

  8. 以正确的方式开源 Python 项目

    以正确的方式开源 Python 项目 大多数Python开发者至少都写过一个像工具.脚本.库或框架等对其他人也有用的工具.我写这篇文章的目的是让现有Python代码的开源过程尽可能清 晰和无痛.我不是 ...

  9. 流行的Python项目汇总

    年有哪些流行的Python项目呢?下面,我们一起来看下. 一.测试和调试 python_koans :Python Koans 算 “Ruby Koans” 的一部分,作为交互式教程,可以学习 TDD ...

  10. 创建成功的Python项目

    创建成功的Python项目 前端开发工具技巧介绍—Sublime篇 SEO在网页制作中的应用 观察者模式 使用D3制作图表 英文原文:Create successful Python projects ...

随机推荐

  1. iPhone IOS10安装APP没提示连接网络(无法联网)的解决办法

    iPhone升级ios10之后,遇到如标题所述问题时: 1.退出APP,设置-蜂窝移动网络-无线局域网助理-开启 2.进入APP,这时候就回提示连接网络了. 提醒: 数据流量有限的朋友,平时请关闭&q ...

  2. python安装包API文档

    在python开发过程中,经常会使用第三方包,或者内置的包. 那么这些包,具体有哪些选项,有哪些方法,你知道吗?下面介绍一种万能方法. 使用命令:<注意,命令里python显示的API版本是根据 ...

  3. POJ 3080 Blue Jeans(Java暴力)

    Blue Jeans [题目链接]Blue Jeans [题目类型]Java暴力 &题意: 就是求k个长度为60的字符串的最长连续公共子串,2<=k<=10 规定: 1. 最长公共 ...

  4. 灵雀云容器PaaS平台助力知名股份制银行金融科技革新

    互联网.科技和金融的碰撞给银行业带来巨大影响.IT技术起初是传统金融提升效率的工具和方法,随着新技术的演进,技术成为驱动变革的核心要素.Fintech金融科技以技术和数据为驱动,用创新的方法改变了金融 ...

  5. Python实现链表

    1.1实现单向链表 #链表结构分成2部分 head,tail #('a',('b',('c',none))) #迭代时候 Head is a ;;;; tail is ('b',('c',none)) ...

  6. PHP 批量操作删除,支持单个删除

    PHP  执行部分: <?php include('checkadmin.php'); header('Content-Type: text/html; charset=utf-8'); if( ...

  7. 2014-2015 ACM-ICPC, Asia Xian Regional Contest GThe Problem to Slow Down You

    http://blog.csdn.net/u013368721/article/details/42100363  回文树 建立两棵回文树,然后count处理一遍就可以了,然后顺着这两棵树的边走下去就 ...

  8. IDEA中文出现乱码解决(转)

    转自:http://lcl088005.iteye.com/blog/2284696 我是个idea的忠实用户,新公司的项目都是用eclipse做的,通过svn拉下代码后发现,注释的内容里,中文内容都 ...

  9. Hdu2191 悼念512汶川大地震遇难同胞——珍惜现在,感恩生活 (多重背包)

    Problem Description 急!灾区的食物依然短缺!为了挽救灾区同胞的生命,心系灾区同胞的你准备自己采购一些粮食支援灾区,现在假设你一共有资金n元,而市场有m种大米,每种大米都是袋装产品, ...

  10. C语言实例:数组与字符串

    数组: #include <stdio.h> #include <stdlib.h> #define ARRAY_SIZE(Array) (sizeof (Array) / s ...