软件开发目录规范 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文件的两种用途 #当文件被执行时 ...
随机推荐
- 用swoole实现异步任务队列
应用场景如下: 假如要发100封邮件,for循环100遍,这种方法显然是不可取的. 在一些比较繁杂的业务里,我们很可能有超过1万的邮件要群发.那我们怎么处理这个延迟的问题? 答案就是用异步.把&quo ...
- DawgCTF wp(re和crypto)
简单写写思路,想看详解的..我脚本有些丢失了..师傅请移步. 挂了个vpn,算正式打这种国际赛,全是英文.上去打了两天,昨晚晚上划水了一晚上补作业...,re那时候写出来三道,Potentially ...
- WIN10 网卡驱动异常代码56的问题及解决方法
故障描述: 原来使用正常的一个微机室,突然一天控制端主机网络连接异常,平时的网络控制软件无法使用.检查网络配置正常,网络诊断.修复.将网卡禁用也没有效果:后来删除网卡想重装,则恶运开始,无法安装驱动: ...
- C语言:虚拟地址 和编译模式
所谓虚拟地址空间,就是程序可以使用的虚拟地址的有效范围.虚拟地址和物理地址的映射关系由操作系统决定,相应地,虚拟地址空间的大小也由操作系统决定,但还会受到编译模式的影响.这节我们先讲解CPU,再讲解编 ...
- Java之注解与反射
Java之注解与反射 注解(Annotation)简介 注解(Annotation)是从JDK5.0引入的新技术 Annotation作用:注解(Annotation)可以被其他程序如编译器等读取 A ...
- Java基础00-Debug11
1. Debug 1.1 Debug概述 1.2 Debug操作流程 1.2.1 如何加断点 1.2.2 如何运行加了断点的程序 1.2.3 看哪里 1.2.4 点哪里 1.2.5 如何删除断点 多个 ...
- 前端开发入门到进阶第三集【js进行url解析】
https://www.cnblogs.com/yuanzhiguo/p/8241644.html
- 小程序框架WePY 从入门到放弃踩坑合集
小程序框架WePY 从入门到放弃踩坑合集 一点点介绍WePY 因为小程序的语法设计略迷, 所以x1 模块化起来并不方便, 所以x2 各厂就出了不少的框架用以方便小程序的开发, 腾讯看到别人家都出了框架 ...
- BZOJ2457 双端队列 题解
本题直接求解十分困难,因为在不知道整个序列的数字规律时当前所作决策都无法保证最优性. 考虑正难则反,题目转化为将一个非降序列分成尽量少的几段,让每段对应原问题的双端队列. 先将原数组排序,由于原数组下 ...
- 前端基础html(二)
一.html的概念 1.概念:超文本标记语言. 2.超文本,超链接:超级不仅有文本,图片,还有音频,视频等. 3.html:作用: 显示服务器端的响应结果. 二.互联网三大基石 1.url:统一资 ...