zoukankan      html  css  js  c++  java
  • 1、什么是包?

    #官网解释
    Packages are a way of structuring Python’s module namespace by using “dotted module names”
    包是一种通过使用‘.模块名’来组织python模块名称空间的方式。
    
    #具体的:包就是一个包含有__init__.py文件的文件夹,所以其实我们创建包的目的就是为了用文件夹将文件/模块组织起来
    
    #需要强调的是:
      1. 在python3中,即使包下没有__init__.py文件,import 包仍然不会报错,而在python2中,包下一定要有该文件,否则import 包报错
    
      2. 创建包的目的不是为了运行,而是被导入使用,记住,包只是模块的一种形式而已,包的本质就是一种模块

    2、为何要使用包

    包的本质就是一个文件夹,那么文件夹唯一的功能就是将文件组织起来
    随着功能越写越多,我们无法将所以功能都放到一个文件中,于是我们使用模块去组织功能,
    而随着模块越来越多,我们就需要用文件夹将模块文件组织起来,以此来提高程序的结构性和可维护性

    3、注意事项

    #1.关于包相关的导入语句也分为import和from ... import ...两种,但是无论哪种,无论在什么位置,
    在导入时都必须遵循一个原则:凡是在导入时带点的,点的左边都必须是一个包,否则非法。
    可以带有一连串的点,如item.subitem.subsubitem,但都必须遵循这个原则。但对于导入后,在使用时就没有这种限制了,
    点的左边可以是包,模块,函数,类(它们都可以用点的方式调用自己的属性)。
    #2、import导入文件时,产生名称空间中的名字来源于文件,import 包,
    产生的名称空间的名字同样来源于文件,即包下的__init__.py,导入包本质就是在导入该文件
    #3、包A和包B下有同名模块也不会冲突,如A.a与B.a来自俩个命名空间

    4、绝对导入和相对导入

    我们的最顶级包glance是写给别人用的,然后在glance包内部也会有彼此之间互相导入的需求,这时候就有绝对导入和相对导入两种方式:

    绝对导入:以glance作为起始

    相对导入:用.或者..的方式最为起始(只能在一个包中使用,不能用于不同目录内)

    例如:我们在glance/api/version.py中想要导入glance/cmd/manage.py

    在glance/api/version.py
    
    #绝对导入
    from glance.cmd import manage
    manage.main()
    
    #相对导入
    from ..cmd import manage
    manage.main()

    测试结果:注意一定要在于glance同级的文件中测试

    绝对导入与相对导入总结

    绝对导入与相对导入
    
    # 绝对导入: 以执行文件的sys.path为起始点开始导入,称之为绝对导入
    #        优点: 执行文件与被导入的模块中都可以使用
    #        缺点: 所有导入都是以sys.path为起始点,导入麻烦
    
    # 相对导入: 参照当前所在文件的文件夹为起始开始查找,称之为相对导入
    #        符号: .代表当前所在文件的文件加,..代表上一级文件夹,...代表上一级的上一级文件夹
    #        优点: 导入更加简单
    #        缺点: 只能在导入包中的模块时才能使用
          #注意:
            1. 相对导入只能用于包内部模块之间的相互导入,导入者与被导入者都必须存在于一个包内
            2. attempted relative import beyond top-level package 

    # 试图在顶级包之外使用相对导入是错误的,言外之意,必须在顶级包内使用相对导入,每增加一个.代表跳到上一级文件夹,而上一级不应该超出顶级包

    5,软件开发规范

    #=============>bin目录:存放执行脚本
    #start.py
    import sys,os
    
    BASE_DIR=os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
    sys.path.append(BASE_DIR)
    
    from core import core
    from conf import my_log_settings
    
    if __name__ == '__main__':
        my_log_settings.load_my_logging_cfg()
        core.run()
    
    #=============>conf目录:存放配置文件
    #config.ini
    [DEFAULT]
    user_timeout = 1000
    
    [egon]
    password = 123
    money = 10000000
    
    [alex]
    password = alex3714
    money=10000000000
    
    [yuanhao]
    password = ysb123
    money=10
    
    #settings.py
    import os
    config_path=r'%s\%s' %(os.path.dirname(os.path.abspath(__file__)),'config.ini')
    user_timeout=10
    user_db_path=r'%s\%s' %(os.path.dirname(os.path.dirname(os.path.abspath(__file__))),
                         'db')
    
    
    #my_log_settings.py
    """
    logging配置
    """
    
    import os
    import logging.config
    
    # 定义三种日志输出格式 开始
    
    standard_format = '[%(asctime)s][%(threadName)s:%(thread)d][task_id:%(name)s][%(filename)s:%(lineno)d]' 
                      '[%(levelname)s][%(message)s]' #其中name为getlogger指定的名字
    
    simple_format = '[%(levelname)s][%(asctime)s][%(filename)s:%(lineno)d]%(message)s'
    
    id_simple_format = '[%(levelname)s][%(asctime)s] %(message)s'
    
    # 定义日志输出格式 结束
    
    logfile_dir = r'%slog' %os.path.dirname(os.path.dirname(os.path.abspath(__file__)))  # log文件的目录
    
    logfile_name = 'all2.log'  # log文件名
    
    # 如果不存在定义的日志目录就创建一个
    if not os.path.isdir(logfile_dir):
        os.mkdir(logfile_dir)
    
    # log文件的全路径
    logfile_path = os.path.join(logfile_dir, logfile_name)
    
    # log配置字典
    LOGGING_DIC = {
        'version': 1,
        'disable_existing_loggers': False,
        'formatters': {
            'standard': {
                'format': standard_format
            },
            'simple': {
                'format': simple_format
            },
        },
        'filters': {},
        'handlers': {
            #打印到终端的日志
            'console': {
                'level': 'DEBUG',
                'class': 'logging.StreamHandler',  # 打印到屏幕
                'formatter': 'simple'
            },
            #打印到文件的日志,收集info及以上的日志
            'default': {
                'level': 'DEBUG',
                'class': 'logging.handlers.RotatingFileHandler',  # 保存到文件
                'formatter': 'standard',
                'filename': logfile_path,  # 日志文件
                'maxBytes': 1024*1024*5,  # 日志大小 5M
                'backupCount': 5,
                'encoding': 'utf-8',  # 日志文件的编码,再也不用担心中文log乱码了
            },
        },
        'loggers': {
            #logging.getLogger(__name__)拿到的logger配置
            '': {
                'handlers': ['default', 'console'],  # 这里把上面定义的两个handler都加上,即log数据既写入文件又打印到屏幕
                'level': 'DEBUG',
                'propagate': True,  # 向上(更高level的logger)传递
            },
        },
    }
    
    
    def load_my_logging_cfg():
        logging.config.dictConfig(LOGGING_DIC)  # 导入上面定义的logging配置
        logger = logging.getLogger(__name__)  # 生成一个log实例
        logger.info('It works!')  # 记录该文件的运行状态
    
    if __name__ == '__main__':
        load_my_logging_cfg()
    
    #=============>core目录:存放核心逻辑
    #core.py
    import logging
    import time
    from conf import settings
    from lib import read_ini
    
    config=read_ini.read(settings.config_path)
    logger=logging.getLogger(__name__)
    
    current_user={'user':None,'login_time':None,'timeout':int(settings.user_timeout)}
    def auth(func):
        def wrapper(*args,**kwargs):
            if current_user['user']:
                interval=time.time()-current_user['login_time']
                if interval < current_user['timeout']:
                    return func(*args,**kwargs)
            name = input('name>>: ')
            password = input('password>>: ')
            if config.has_section(name):
                if password == config.get(name,'password'):
                    logger.info('登录成功')
                    current_user['user']=name
                    current_user['login_time']=time.time()
                    return func(*args,**kwargs)
            else:
                logger.error('用户名不存在')
    
        return wrapper
    
    @auth
    def buy():
        print('buy...')
    
    @auth
    def run():
    
        print('''
    购物
    查看余额
    转账
        ''')
        while True:
            choice = input('>>: ').strip()
            if not choice:continue
            if choice == '1':
                buy()
    
    
    
    if __name__ == '__main__':
        run()
    
    #=============>db目录:存放数据库文件
    #alex_json
    #egon_json
    
    #=============>lib目录:存放自定义的模块与包
    #read_ini.py
    import configparser
    def read(config_file):
        config=configparser.ConfigParser()
        config.read(config_file)
        return config
    
    #=============>log目录:存放日志
    #all2.log
    [2017-07-29 00:31:40,272][MainThread:11692][task_id:conf.my_log_settings][my_log_settings.py:75][INFO][It works!]
    [2017-07-29 00:31:41,789][MainThread:11692][task_id:core.core][core.py:25][ERROR][用户名不存在]
    [2017-07-29 00:31:46,394][MainThread:12348][task_id:conf.my_log_settings][my_log_settings.py:75][INFO][It works!]
    [2017-07-29 00:31:47,629][MainThread:12348][task_id:core.core][core.py:25][ERROR][用户名不存在]
    [2017-07-29 00:31:57,912][MainThread:10528][task_id:conf.my_log_settings][my_log_settings.py:75][INFO][It works!]
    [2017-07-29 00:32:03,340][MainThread:12744][task_id:conf.my_log_settings][my_log_settings.py:75][INFO][It works!]
    [2017-07-29 00:32:05,065][MainThread:12916][task_id:conf.my_log_settings][my_log_settings.py:75][INFO][It works!]
    [2017-07-29 00:32:08,181][MainThread:12916][task_id:core.core][core.py:25][ERROR][用户名不存在]
    [2017-07-29 00:32:13,638][MainThread:7220][task_id:conf.my_log_settings][my_log_settings.py:75][INFO][It works!]
    [2017-07-29 00:32:23,005][MainThread:7220][task_id:core.core][core.py:20][INFO][登录成功]
    [2017-07-29 00:32:40,941][MainThread:7220][task_id:core.core][core.py:20][INFO][登录成功]
    [2017-07-29 00:32:47,222][MainThread:7220][task_id:core.core][core.py:20][INFO][登录成功]
    [2017-07-29 00:32:51,949][MainThread:7220][task_id:core.core][core.py:25][ERROR][用户名不存在]
    [2017-07-29 00:33:00,213][MainThread:7220][task_id:core.core][core.py:20][INFO][登录成功]
    [2017-07-29 00:33:50,118][MainThread:8500][task_id:conf.my_log_settings][my_log_settings.py:75][INFO][It works!]
    [2017-07-29 00:33:55,845][MainThread:8500][task_id:core.core][core.py:20][INFO][登录成功]
    [2017-07-29 00:34:06,837][MainThread:8500][task_id:core.core][core.py:25][ERROR][用户名不存在]
    [2017-07-29 00:34:09,405][MainThread:8500][task_id:core.core][core.py:25][ERROR][用户名不存在]
    [2017-07-29 00:34:10,645][MainThread:8500][task_id:core.core][core.py:25][ERROR][用户名不存在]
  • 相关阅读:
    数据库-第七章 数据库设计-7.4 逻辑结构设计
    ArrayList 一个面试题
    java 锁
    IDEA 通过插件jetty-maven-plugin使用 jetty
    Mybatis主线流程源码解析
    Springboot 报找不到对应的Mapper接口或RPC接口等问题
    Springboot启动报Multiple Dockets with the same group name are not supported. The following duplicate groups were discovered.
    Exception和Error有什么区别?
    谈谈对Java平台的理解笔记
    Spring事务控制
  • 原文地址:https://www.cnblogs.com/zwq-/p/9524933.html
Copyright © 2011-2022 走看看