zoukankan      html  css  js  c++  java
  • 模块和包

    一、什么是模块

    模块:一个模块就是一个包含了python定义和声明的文件,文件名就是模块名字加上.py的后缀。

       但其实import加载的模块分为四个通用类别: 

      1 使用python编写的代码(.py文件)

      2 已被编译为共享库或DLL的C或C++扩展

      3 包好一组模块的包

      4 使用C编写并链接到python解释器的内置模块

    二、导入模块import

    1.import

    import 模块名
    

      

    import一个模块相当于执行了这个模块。

    不能重复导入模块

    2.如何去使用被导入模块的名字?

    import my_module
    print(my_module.name)
    name = 'zoro'
    print(name)
    

      

    3.在import模块的时候发生的事情:

    在import模块的时候发生的事情
        1.寻找模块
        2.如果找到了,就开辟一块空间,执行这个模块
        3.把这个模块中用到的名字都收录到新开辟的空间中
        4.创建一个变量来引用这个模块的空间
        
    *1.模块不会被重复导入
    *2.模块和文件之间的内存空间始终是隔离的
    *3.模块的名字必须是符合变量命名规范的。
    

      

    4.导入多个模块

    遵循pep8规范

    pep8规范
    import os
    import django
    import my_module
    顺序:内置模块,第三方模块,自定义模块
    

      

    5.给模块起别名

    import my_module as m
    m.name
    

      

    def dump(method):
        if method == 'json':
            import json as m
        elif method == 'pickle':
            import pickle as m
        with open('file', 'w') as f:
            m.dump([1, 2, 3], f)
    应用

    6.模块搜索路径

    正常的sys.path中除了内置、扩展模块所在的路径之外,只有一个路径是永远不会出问题的。就是你直接执行这个文件的目录。

    一个模块是否能被导入,就看这个模块所在的目录在不在sys.path中

    模块搜索路径
    import sys
    print(sys.path)
    import my_module
    
    正常的sys.path中除了内置、扩展模块所在的路径之外
    只有一个路径是永远不会出问题
        你直接执行的这个文件所在的目录
    一个模块是否能被导入,就看这个模块所在的目录在不在sys.path中
    

      

    7.两种运行一个py文件的方式

    我们可以通过模块的全局变量__name__来查看模块名:
    当做脚本运行:
    __name__ 等于'__main__'

    当做模块导入:
    __name__= 模块名

    作用:用来控制.py文件在不同的应用场景下执行不同的逻辑
    if __name__ == '__main__':

    两种运行一个py文件的方式
    直接运行它 : cmd python xx.py  pycharm  脚本
    __name__ == '__main__'
    导入它 : 模块
    __name__ == '模块名'

    三、from...import...

    from my_module import name
    print(name)
    

      

    在from import 的过程中发生了什么事?
      要找到my_module
      开空间,执行my_module
      所有的my_module中的名字都存储在my_module所属的空间中
      建立一个引用name,read2分别取引用my_module空间中的名字

    from my_module import *  # 与__all__配合使用
    print(name)
    read1()
    read2()
    

      

    模块的导入与修改

    # 模块的导入和修改
    # import time
    # import my_module
    # print(my_module.name)
    # time.sleep(10)
    # print(my_module.name)  # 不能重新修改
    
    # from importlib import reload
    # import time
    # import my_module
    # print(my_module.name)
    # time.sleep(10)
    # reload(my_module)  # 重新导入了
    # print(my_module.name)
    

      

    四、包

    什么是包?包是一种通过使用‘.模块名’来组织python模块名称空间的方式。

    含有一个__init__.py文件的文件夹,包里面通常含有一些py文件。

    1. 无论是import形式还是from...import形式,凡是在导入语句中(而不是在使用时)遇到带点的,都要第一时间提高警觉:这是关于包才有的导入语法

    2. 包是目录级的(文件夹级),文件夹是用来组成py文件(包的本质就是一个包含__init__.py文件的目录)

    3. import导入文件时,产生名称空间中的名字来源于文件,import 包,产生的名称空间的名字同样来源于文件,即包下的__init__.py,导入包本质就是在导入该文件

    需要注意的是,凡是在导入时带点的,点的左边都必须是一个包。

    对于导入后,在使用时就没有这种限制了,点的左边可以是包,模块,函数,类(它们都可以用点的方式调用自己的属性)。

    绝对导入和相对导入


    1.绝对导入

    glance2.api.policy.get()
    

      


    导入包的过程中发生了什么事?
      相当于执行了这个包的 __init__.py文件
      sys.path中的内容 永远是当前你执行的文件


    2.相对导入 运用了相对导入的文件不能被直接执行
      '.'表示当前目录
      '..'表示上一级目录
    凡是在导入时带点的,点的左边都必须是一个包

    绝对导入:以glance作为起始

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

    特别需要注意的是:可以用import导入内置或者第三方模块(已经在sys.path中),但是要绝对避免使用import来导入自定义包的子模块(没有在sys.path中),应该使用from... import ...的绝对或者相对导入,且包的相对导入只能用from的形式。

    五、软件开发规范

    #=============>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][用户名不存在]
    开发规范
  • 相关阅读:
    在线程中使用OpenFileDialog
    Log4net附加
    SQL表间列根据条件复制(赋值)
    DataGridView使用
    Latex使用总结及备忘
    Windows获取文件状态
    TabControl取消首次定位焦点
    C#跨线程调用
    电子词典的查寻程序,发送和接收应答程序
    电子词典的相关子函数db.c程序
  • 原文地址:https://www.cnblogs.com/eaoo/p/9606322.html
Copyright © 2011-2022 走看看