软件开发目录规范 ATM框架构建
软件开发的目录规范
建立文件夹
为了提高程序的可读性与可维护性,我们应该为软件设计良好的目录结构,这与规范的编码风格同等重要。软件的目录规范并无硬性标准,只要清晰可读即可
以ATM购物车项目为例:
首先需要建立一个项目文件夹,例如项目名称ATM,这个ATM的大文件夹下需要有几个子文件夹:
bin文件夹:用于存放指令文件,可执行指令,例如:start.py
conf文件夹:配置性的文件,存放一些变量,运行软件时需要从中读取一些变量值,例如:settings.py
db文件夹:放数据库相关的操作代码,例如:db_handle.py
core文件夹:核心代码,例如:src.py
log文件夹:存放日志,查看软件运行时记录的一些日志数据,例如:access.log
lib文件夹:库目录,
db文件夹:存放数据
readme.md:类似于软件说明书
搭框架
在core文件夹下建立src.py文件
==============================在 ATM/core/src.py下================================
def login():
print('登录功能') # 简易的功能
def register():
print('注册功能')
def transfer():
print('转账功能')
function_dic = {
'1':['登录',login],
'2':['注册',register],
'3':['转账',transfer]
}
def run(): # src文件只负责功能性的定义,不负责程序的运行,到时候调用放在start.py文件里面
while True:
print('0 ️ 退出')
for k in function_dic:
print('%s ️ %s' %(k,function_dic[k][0]))
choice = input('输入功能指令>>>')
if choice == '0':
break
if choice in function_dic:
function_dic[choice][1]()
else:
print('指令不存在,重新键入')
在bin文件夹下建立start.py文件
==============================在 ATM/bin/start.py下================================
# 为了软件便于管理维护我们将软件进行拆分
# 让 start.py 能够跨文件调的到 src.py 里面的函数 run,那我们就需要将src文件的文件夹路径加入环境变量
import sys
sys.path.append(r'/Users/jessewu/PycharmProjects/pythonProject/test01/study miscellaneous/规范目录/ATM/core') # 将src文件的文件夹路径加入环境变量
import src # 这样就能正常跨文件调用src的功能了
if __name__ == '__main__': # 当这个文件作为主文件运行时就执行里面的子代码 在执行文件里面加上这个更规范一点
src.run()
但是上述代码仍是有问题的因为我们可能会导入到的文件很多,那我们每次导入都需要添加到环境变量,这样就比较麻烦,我们改进一下:
==============================在 ATM/bin/start.py下================================
import sys
sys.path.append(r'/Users/jessewu/PycharmProjects/pythonProject/test01/study miscellaneous/规范目录/ATM') # 将文件的软件根目录直接加入环境变量 这样就能用到哪个直接导入
from core import src
if __name__ == '__main__':
src.run()
这样我们又碰到另一个问题,我们写的是一个软件,当用户将这个软件安装到其它电脑的时候,文件路径和我们写的时候不一样,那这样软件就无法运行。我们需要再改动一下,将文件路径写活了,让它在别的电脑也能运行:
==============================在 ATM/bin/start.py下================================
import sys
import os # 导入os模块 调用__file__功能,它能够直接动态获取到当前文件的绝对路径
BASE_DIR = os.path.dirname(os.path.dirname(__file__)) # 获取但前文件文件夹的文件夹,也就是副副文件夹,
sys.path.append(BASE_DIR) # 这样就能够动态获取
from core import src
if __name__ == '__main__':
src.run()
但还有更省事的办法:
==============================在 ATM/start.py下================================
# 直接将start.py文件移动到项目的根目录下面,因为当前执行文件的文件夹会自动添加到环境变量中,这样我们就不用手动添加路径了
from core import src # 直接就能导入
if __name__ == '__main__':
src.run()
接下来我们有一个需求,日志需求,我们需要记录日志,日志功能不是用户需要用到的,他是一个其他功能都可能需要调用到的功能,我们将它放在lib文件夹下,创建文件common.py:
==============================在 ATM/lib/common.py下================================
import time
def logger(msg):
with open(r'/Users/jessewu/PycharmProjects/pythonProject/test01/study miscellaneous/规范目录/ATM/log/access.log',\
mode='at',encoding='utf8')as f:
f.write('%s %s\n' %(time.strftime('%Y-%m-%d %H:%M:%s'),msg))
# 简易的日志功能
==============================在 ATM/core/src.py下================================
from lib.common import logger # 需要调用到lib下common里面的logger功能,需要导入一下,需要注意的是这里的.是路径分隔符的意思
def login():
print('登录功能')
logger('登陆了')
def register():
print('注册功能')
logger('有人注册了')
def transfer():
print('转账功能')
logger('转出了一笔钱')
function_dic = {
'1': ['登录', login],
'2': ['注册', register],
'3': ['转账', transfer]
}
def run():
while True:
print('0 ️ 退出')
for k in function_dic:
print('%s ️ %s' % (k, function_dic[k][0]))
choice = input('输入功能指令>>>')
if choice == '0':
logger('下线了')
break
elif choice in function_dic:
function_dic[choice][1]()
else:
print('指令不存在,重新键入')
虽然日志功能能正常记录了,但是还是老问题,记录日志的文件路径被我们写死了,需要将路径写活,且这个路径能够让用户能够配置的,在conf文件夹下创建文件setting.py:
==============================在 ATM/conf/settings.py下================================
# 需要定义一个路径变量,让它在common模块里面能够被调用到
import os
BASE_DIR = os.path.dirname(os.path.dirname(__file__))
LOG_PATH = '%s/log/access.log' % BASE_DIR # 保证用户即自己能改,也可以不改就能用
==============================在 ATM/lib/common.py下================================import timefrom conf import settings # 调用settings里面的logger功能def logger(msg): with open('%s' %ssettings.LOG_PATH,mode='at',encoding='utf8')as f: f.write('%s %s\n' %(time.strftime('%Y-%m-%d %H:%M:%s'),msg))
升级需求,将写好的logger替换成系统里的logging模块,首先我们在settings.py里面定义好LOGGING_DIC,规定好日志的格式和打印形式,过滤级别,logger表示级别为每条日志打上标签,filters表示过滤,handlers表示将日志如何处理,是打印还是输出到终端:
==============================在 ATM/conf/settings.py下================================# 1、定义三种日志输出格式,日志中可能用到的格式化串如下# %(name)s Logger的名字# %(levelno)s 数字形式的日志级别# %(levelname)s 文本形式的日志级别# %(pathname)s 调用日志输出函数的模块的完整路径名,可能没有# %(filename)s 调用日志输出函数的模块的文件名# %(module)s 调用日志输出函数的模块名# %(funcName)s 调用日志输出函数的函数名# %(lineno)d 调用日志输出函数的语句所在的代码行# %(created)f 当前时间,用UNIX标准的表示时间的浮 点数表示# %(relativeCreated)d 输出日志信息时的,自Logger创建以 来的毫秒数# %(asctime)s 字符串形式的当前时间。默认格式是 “2003-07-08 16:49:45,896”。逗号后面的是毫秒# %(thread)d 线程ID。可能没有# %(threadName)s 线程名。可能没有# %(process)d 进程ID。可能没有# %(message)s用户输出的消息# 2、强调:其中的%(name)s为getlogger时指定的名字standard_format = '[%(asctime)s][%(threadName)s:%(thread)d][task_id:%(name)s][%(filename)s:%(lineno)d]' \ '[%(levelname)s][%(message)s]'simple_format = '[%(levelname)s][%(asctime)s][%(filename)s:%(lineno)d]%(message)s'test_format = '%(asctime)s] %(message)s'LOGGING_DIC = { 'version': 1, 'disable_existing_loggers': False, 'formatters': { 'standard': { 'format': standard_format }, 'simple': { 'format': simple_format }, 'test': { 'format': test_format }, }, 'filters': {}, 'handlers': { #打印到终端的日志 'console': { 'level': 'DEBUG', 'class': 'logging.StreamHandler', # 打印到屏幕 'formatter': 'simple' }, #打印到文件的日志,收集info及以上的日志 'default': { 'level': 'DEBUG', 'class': 'logging.handlers.RotatingFileHandler', # 保存到文件,日志轮转 'formatter': 'standard', # 可以定制日志文件路径 # BASE_DIR = os.path.dirname(os.path.abspath(__file__)) # log文件的目录 # LOG_PATH = os.path.join(BASE_DIR,'a1.log') 'filename': LOG_PATH, # 日志文件 'maxBytes': 1024*1024*5, # 日志大小 5M 'backupCount': 5, 'encoding': 'utf-8', # 日志文件的编码,再也不用担心中文log乱码了 }, 'other': { 'level': 'DEBUG', 'class': 'logging.FileHandler', # 保存到文件 'formatter': 'test', 'filename': 'a2.log', 'encoding': 'utf-8', }, }, 'loggers': { #logging.getLogger(__name__)拿到的logger配置 '用户相关日志': { 'handlers': ['default', 'console'], # 这里把上面定义的两个handler都加上,即log数据既写入文件又打印到屏幕 'level': 'DEBUG', # loggers(第一层日志级别关限制)--->handlers(第二层日志级别关卡限制) 'propagate': False, # 默认为True,向上(更高level的logger)传递,通常设置为False即可,否则会一份日志向上层层传递 }, },}
定义好之后,我们到原本的logger功能模块common.py下面将之前的蹩脚功能注释掉,重新写,定义logger函数:
==============================在 ATM/lib/common.py下================================
from conf import settings
import logging.configlogging.config.dictConfig(settings.LOGGING_DIC) # 固定用法def logger(log_name): logger1 = logging.getLogger(log_name) # log_name 使用者需要自己传日志类型名称进去 return logger1
==============================在 ATM/core/src.py下================================
import loggingfrom lib.common import loggerdef login(): print('登录功能') log = logger('用户相关日志') # 赋值给变量 log.debug('xxx登录了') # 调用级别def register(): print('注册功能') log = logger('用户相关日志') log.info('有人注册了')def transfer(): print('转账功能') log = logger('用户相关日志') log.info('转出了一笔钱')def withdraw(): print('提现功能') log = logger('用户相关日志') log.warning('提现金额过大,可能要跑')function_dic = { '1': ['登录', login], '2': ['注册', register], '3': ['转账', transfer], '4': ['提现', withdraw]}def run(): while True: print('0 ️ 退出') for k in function_dic: print('%s ️ %s' % (k, function_dic[k][0])) choice = input('输入功能指令>>>') if choice == '0': log = logger('用户相关日志') log.info('下线了') break elif choice in function_dic: function_dic[choice][1]() else: print('指令不存在,重新键入')
软件开发目录规范 ATM框架构建的更多相关文章
- Python 浅谈编程规范和软件开发目录规范的重要性
最近参加了一个比赛,然后看到队友编程的代码,我觉得真的是觉得注释和命名规范的重要性了,因为几乎每个字符都要咨询他,用老师的话来说,这就是命名不规范的后续反应.所以此时的我意识到写一篇关于注释程序的重要 ...
- python 之 软件开发目录规范 、logging模块
6.4 软件开发目录规范 软件(例如:ATM)目录应该包含: 文件名 存放 备注 bin start.py,用于起动程序 core src.py,程序核心功能代码 conf settings. ...
- python模块导入-软件开发目录规范-01
模块 模块的基本概念 模块: # 一系列功能的结合体 模块的三种来源 """ 模块的三种来源 1.python解释器内置的模块(os.sys....) 2.第三方的别人写 ...
- python浅谈编程规范和软件开发目录规范的重要性
前言 我们这些初学者,目前要做的就是遵守代码规范,这是最基本的,而且每个团队的规范可能还不一样,以后工作了,尽可能和团队保持一致,目前初学者就按照官方的要求即可 新人进入一个企业,不会接触到核心的架构 ...
- Python记录13:软件开发目录规范
软件开发目录规范 开发一个软件,一个工程项目,一般应该具备以下的几个基本的文件夹和模块,当然,这并不是一成不变的,根据项目的不同会有一定的差异,不过作为一个入门级的新手,建议暂时按照以下的规范编写: ...
- Python模块:Re模块、附软件开发目录规范
Re模块:(正则表达式) 正则表达式就是字符串的匹配规则 正则表达式在多数编程语言里都有相应的支持,Python里面对应的模块时re 常用的表达式规则:(都需要记住) “ . ” # 默认匹配除 ...
- py 包和模块,软件开发目录规范
目录 py 包和模块,软件开发目录规范 什么是包? 什么是模块? 软件开发目录规范 py 包和模块,软件开发目录规范 什么是包? 包指的是内部包__init__.py的文件夹 包的作用: 存放模块,包 ...
- python基础语法10 函数递归,模块,软件开发目录规范
函数递归: 函数递归指的是重复 “直接调用或间接调用” 函数本身, 这是一种函数嵌套调用的表现形式. 直接调用: 指的是在函数内置,直接调用函数本身. 间接调用: 两个函数之间相互调用间接造成递归. ...
- day16(软件开发目录规范)
模块的使用01 模块的循环导入问题 解决方案一: 把循环导入的语句放到名字定义的后面 解决方案二: 将循环导入语句放到函数内(先定义确定名称空间)02 区分python文件的两种用途 #当文件被执行时 ...
随机推荐
- c语言格式字符
格式说明由"%"和格式字符组成,如%d%f等.它的作用是将输出的数据转换为指定的格式输出.格式说明总是由"%"字符开始的. 格式字符有d,o,x,u,c,s,f ...
- SQLITE数据库不支持远程访问
SQLITE数据库不支持远程访问 import sqlite3 conn=sqlite3.connect("dailiaq.db") cur=conn.cursor() def c ...
- Requests方法 --- json模块
1.Json 简介:Json,全名 JavaScript Object Notation,是一种轻量级的数据交换格式,常用于 http 请求中 2.可以用 help(json),查看对应的源码注释内容 ...
- etcd学习(3)-grpc使用etcd做服务发现
grpc通过etcd实现服务发现 前言 服务注册 服务发现 负载均衡 集中式LB(Proxy Model) 进程内LB(Balancing-aware Client) 独立 LB 进程(Externa ...
- 微信小程序云开发-数据库-用户删除数据
一.在商品详情页添加[删除单条数据]按钮 进入goodDetail.wxml页面,添加[删除单条数据]按钮,绑定点击事件removeGood() 二.进入goodDetail.js文件,定义remo ...
- PAT乙级:1070 结绳 (25分)
PAT乙级:1070 结绳 (25分) 题干 给定一段一段的绳子,你需要把它们串成一条绳.每次串连的时候,是把两段绳子对折,再如下图所示套接在一起.这样得到的绳子又被当成是另一段绳子,可以再次对折去跟 ...
- tomcat默认端口
关于tomcat默认端口为8080: 网页浏览器的默认端口为80.
- odoo里面的一些ORM操作
案例0001sale_obj=self.env['sale.order'].browse(k)通过browse查找对象找到对象里面的 sale_obj.name browse 获取一个数据库id或一个 ...
- Python基础之读写xml总结
参考文章:https://blog.csdn.net/weixin_42749767/article/details/82770563 先介绍xml.dom.minidom包,有一个读写的例子 rea ...
- HCNA Routing&Switching之OSPF缺省路由发布
前文我们了解了OSPF的度量值,以及基础配置命令的总结,回顾请参考https://www.cnblogs.com/qiuhom-1874/p/15069632.html:今天我们来聊一聊在ospf里动 ...