• python之规范化开发


    一、规范化开发

    ​ 当前我们是将所有的代码都写到了一个py文件中,如果代码量多且都在一个py文件中,那么对于代码结构不清晰,不规范,运行起来效率也会非常低。

    1. 设计项目目录结构

      项目目录结构有以下优点:

      • 可读性高: 不熟悉这个项目的代码的人,一眼就能看懂目录结构,知道程序启动脚本是哪个,测试目录在哪儿,配置文件在哪儿等等。从而非常快速的了解这个项目。
      • 可维护性高: 定义好组织规则后,维护者就能很明确地知道,新增的哪个文件和代码应该放在什么目录之下。这个好处是,随着时间的推移,代码/配置的规模增加,项目结构不会混乱,仍然能够组织良好。

      以博客园系统为例:

    其中:

    • start.py:项目启动文件。通常将其存放在bin文件夹下。

      import sys
      import os
      BASE_PATH = os.path.dirname(os.path.dirname(__file__))#获取父级目录也就是blog的绝对路径
      sys.path.append(BASE_PATH)# 将bolg项目的路径添加到sys.path列表中,这样所有在blog目录下的py文件都可以相互调用,无需在反复添加文件路径
      from core import src
      if __name__ == '__main__': # 防止start.py文件作为模块被别人引用
          src.run()
      
    • settings.py: 配置文件,就是放置一些项目中需要的静态参数,比如文件路径,数据库配置,软件的默认设置等等。通常将其存放到conf文件夹。

      import os
      user_info_path = os.path.join(os.path.dirname(os.path.dirname(__file__)),'db','user_info') # 通过获取父级目录的绝对路径,与user_info文件路径拼接,生成user_info文件的路径,可保证只要在blog文件夹下不管项目文件被保存到什么地方都不影响user_info文件路径的获取
      
    • src.py:这个文件主要存放的就是核心逻辑功能,需要进行选择的核心功能函数,都应该放在这个文件中。通常将其存放在core文件夹下。

      import os
      from lib import common # 引用lib文件中的common模块(存放装饰器)通过common.的方式引用
      from conf import settings # 引用conf文件中的settings模块(存放user_info路径)
      
      dic_status = {'name': None, 'status': False}  # 登录状态
      
      def get_user_info():  # 用户名和密码文件
          with open(settings.user_info_path, encoding='utf-8') as f1:
              return {i.strip().split('|')[0]: i.strip().split('|')[1] for i in f1}
      
      def login(a=get_user_info):  # 登录验证
          count = 0
          dic = a()
          while count < 3:
              user_name = input('请输入用户名:').strip()
              password = input('请输入密码:').strip()
              if dic.get(user_name) == password:
                  dic_status['name'] = user_name
                  dic_status['status'] = True
                  return True
              print('用户名或密码错误,请重新输入')
              count += 1
          return quit()
      
      def register(b=get_user_info):  # 注册
          dic = b()
          while 1:
              new_name = input('请输入用户名:').strip()
              if new_name.isalnum():
                  if dic.get(new_name) == None:
                      password = input('请输入密码:').strip()
                      if 6 < len(password) < 14:
                          with open(settings.user_info_path, mode='a', encoding='utf-8') as f2:
                              f2.write(f'
      {new_name}|{password}')  # 需不需要更改登录状态?
                              dic_status['name'] = new_name
                              dic_status['status'] = True
                              return True
                      print('密码长度应在6~14个字符之间,且不能含有空格')
                  else:
                      print('用户名已存在,请重新输入')
              else:
                  print('用户名只能含有字母或者数字,不能含有特殊字符')
      
      @common.wrapper
      def article():  # 文章功能
          print(f"欢迎{dic_status['name']}进入文章界面")
          print('''1.直接写入
      2.导入md文件''')
          dic_article = {1: article_w, 2: article_im}
          user_input1 = int(input('请输入选项:').strip())
          dic_article[user_input1]()
      
      def article_w():  # 直接写
          article_content = input('请输入文件名|文件内容:')
          title = article_content.split('|', 1)
          with open(fr"{os.path.dirname(os.path.dirname(__file__))}/article/{title[0]}", mode='w', encoding='utf-8') as f3: # 通过返回其父级目录找到article文件夹,将文章写入此文件夹
              f3.write(f"文件名:{title[0]}
      文件内容:{title[1]}")
          print('文章写入成功')
      
      def article_im():  # 导入md
          article_way = input('请输入文件路径:').strip()
          with open(article_way, encoding='utf-8') as f4, 
                  open(fr'{os.path.dirname(os.path.dirname(__file__))}/article/函数的进阶.text', mode='w', encoding='utf-8') as f5:
              for i in f4:
                  f5.write(i)
          print('导入成功')
      
      @common.wrapper
      def comment():
          print(f"欢迎{dic_status['name']}进入评论界面")
          lis = os.listdir(fr'{os.path.dirname(os.path.dirname(__file__))}/article')
          for i in range(len(lis)):
              print(f'{i + 1}.{lis[i]}')
          user_input = int(input('请输入要评论的文章序号:'))
          li1 = ["苍老师", "东京热", "武藤兰", "波多野结衣"]
          with open(fr'{os.path.dirname(os.path.dirname(__file__))}/article/{lis[user_input - 1]}', mode='r+', encoding='utf-8') as f6:
              c = False
              for i in f6:
                  print(i)
                  if i == '评论区:':
                      c = True  # 判断有没有'评论区'
              user_comment = input('请输入评论内容:')
              for el in li1:
                  if el in user_comment:
                      user_comment = user_comment.replace(el, '*' * len(el))
              if c:
                  f6.write(f"{dic_status['name']}:
      {user_comment}
      ")
              else:
                  f6.write(f"评论区:
      -----------------------------------------
      {dic_status['name']}:
      {user_comment}
      ")
              print('评论成功')
      
      @common.wrapper
      def diary():
          print(f"欢迎{dic_status['name']}进入日记界面")
      
      
      @common.wrapper
      def collect():
          print(f"欢迎{dic_status['name']}进入收藏界面")
      
      
      @common.wrapper
      def logout():
          dic_status['name'] = None
          dic_status['status'] = False
      
      
      def quit_():
          quit()
      
      
      def run():
          while 1:
              print('''1.请登录
      2.请注册
      3.进入文章页面
      4.进入评论页面
      5.进入日记页面
      6.进入收藏页面
      7.注销账号
      8.退出整个程序''')
              dic = {'1': login, '2': register, '3': article, '4': comment, '5': diary, '6': collect, '7': logout, '8': quit_}
              user_input = input("请输入选项:").strip()
              if user_input.isnumeric() and 0 < int(user_input) < 9:
                  dic[user_input]()
              else:
                  print('您输入的序号有误,请重新输入')
      
    • common.py:公共组件文件,这里面放置一些常用的公共组件函数,并不是核心逻辑的函数,而更像是服务于整个程序中的公用的插件,程序中需要即调用。比如装饰器,有些函数是需要这个装饰器认证的,但是有一些是不需要这个装饰器认证的,何处需要何处调用即可。比如还有密码加密功能,序列化功能,日志功能等这些功能都可以放在这里。通常将其存放在lib文件夹。

      from core import src
      
      def wrapper(f):
          def inner(*args, **kwargs):
      
              if src.dic_status['status']:
                  ret = f(*args, **kwargs)
                  return ret
              else:
                  src.login()
                  ret = f(*args, **kwargs)
                  return ret
      
          return inner
      
    • 类似于user_info文件:这个文件文件名不固定,user_info只是此项目中用到的注册表,但是这种文件就是存储数据的文件,类似于文本数据库。有时会遇到将一些数据存储在文件中,与程序交互的情况,所以要单独设置这样的文件。通常将其存放在db文件夹中。

    • log文件:log文件顾名思义就是存储log日志的文件。日志主要是供开发人员使用。比如项目中出现一些bug问题,比如开发人员对服务器做的一些操作都会记录到日志中,以便开发者浏览,查询。

    • README文件,目的是能简要描述该项目的信息,让读者快速了解这个项目。它需要说明以下几个事项:

      1. 软件定位,软件的基本功能。
      2. 运行代码的方法: 安装环境、启动命令等。
      3. 简要的使用说明。
      4. 代码目录结构说明,更详细点可以说明软件的基本原理。
      5. 常见问题说明。
  • 相关阅读:
    python之面向对象函数与方法,反射,双下方法
    python之面向对象的成员,方法,属性,异常处理
    python之面向对象性封装,多态,以及鸭子类型
    python之面向对象三大特性: 继承(单继承)
    AMAP-TECH算法大赛开赛!基于车载视频图像的动态路况分析
    深度学习在高德ETA应用的探索与实践
    高德SD地图数据生产自动化技术的路线与实践(道路篇)
    高德前端这五年:动态化技术的研发历程和全面落地实践
    深度学习在高德POI鲜活度提升中的演进
    高德技术评测建设之路
  • 原文地址:https://www.cnblogs.com/yaoqi17/p/11128912.html
Copyright © 2020-2023  润新知