• python 模块和包的使用


    模块的定义

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

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

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

    
    

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

    
    

      3 包好一组模块的包

    
    

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

    使用模块的好处:

     如果退出python解释器然后重新进入,那么之前定义的函数或者变量都将丢失,因此通常将程序写到文件中以便永久保存下来,需要时就通过python test.py方式去执行,此时test.py被称为脚本script。

     为了方便管理越来越多的功能,我们通常将程序分成一个个的文件,这样做程序的结构更清晰,方便管理。这时我们不仅仅可以把这些文件当做脚本去执行,还可以把他们当做模块来导入到其他的模块中,实现了功能的重复利用

    模块的使用和导入:

    所有的模块导入都应该尽量往上写
        内置模块
        扩展模块
        自定义模块
    模块不会重复被导入 : sys.moudles
    从哪儿导入模块 : sys.path
    
    sys.moudles
    先从sys.modules里查看是否已经被导入
    如果没有被导入,就依据sys.path路径取寻找模块
    找到了就导入
    创建这个模块的命名空间
    执行文件,把文件中的名字都放到命名空间里
    
    import
    import 模块名
        模块名.变量名 和本文件中的变量名完全不冲突
    import 模块名 as 重命名的模块名 : 提高代码的兼容性
    import 模块1,模块2
    
    from import
    from 模块名 import 变量名
        直接使用 变量名 就可以完成操作
        如果本文件中有相同的变量名会发生冲突
    from 模块名 import 变量名字 as 重命名变量名
    from 模块名 import 变量名1,变量名2
    from 模块名 import *
        将模块中的所有变量名都放到内存中
        如果本文件中有相同的变量名会发生冲突
    from 模块名 import * 和 __all__ 是一对
        没有这个变量,就会导入所有的名字
        如果有all 只导入all列表中的名字
    __name__
    在模块中 有一个变量__name__,
    当我们直接执行这个模块的时候,__name__ == '__main__'
    当我们执行其他模块,在其他模块中引用这个模块的时候,这个模块中的__name__ == '模块的名字'
    规则import、from..import..

    总结模块的查找顺序是:内存中已经加载的模块->内置模块->sys.path路径中包含的模块

    内建函数dir是用来查找模块中定义的名字,返回一个有序字符串列表
    import my_module
    dir(my_module)
    如果没有参数,dir()列举出当前定义的名字
    
    dir()不会列举出内建函数或者变量的名字,它们都被定义到了标准模块builtin中,可以列举出它们,
    import builtins
    dir(builtins)
    dir()

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

    1. 无论是import形式还是from...import形式,凡是在导入语句中(而不是在使用时)遇到带点的,都要第一时间提高警觉:这是关于包才有的导入语法
    2. 包是目录级的(文件夹级),文件夹是用来组成py文件(包的本质就是一个包含__init__.py文件的目录)
    3. import导入文件时,产生名称空间中的名字来源于文件,import 包,产生的名称空间的名字同样来源于文件,即包下的__init__.py,导入包本质就是在导入该文件
    强调:
      1. 在python3中,即使包下没有__init__.py文件,import 包仍然不会报错,而在python2中,包下一定要有该文件,否则import 包报错
      2. 创建包的目的不是为了运行,而是被导入使用,记住,包只是模块的一种形式而已,包即模块
    1.关于包相关的导入语句也分为import和from ... import ...两种,但是无论哪种,无论在什么位置,在导入时都必须遵循一个原则:凡是在导入时带点的,点的左边都必须是一个包,否则非法。可以带有一连串的点,如item.subitem.subsubitem,但都必须遵循这个原则。
    
    2.对于导入后,在使用时就没有这种限制了,点的左边可以是包,模块,函数,类(它们都可以用点的方式调用自己的属性)。
    
    3.对比import item 和from item import name的应用场景:
    如果我们想直接使用name那必须使用后者。
    
    
    需要注意的是from后import导入的模块,必须是明确的一个不能带点,否则会有语法错误,如:from a import b.c是错误语法 

     __init__.py文件

    不管是哪种方式,只要是第一次导入包或者是包的任何其他部分,都会依次执行包下的__init__.py文件(我们可以在每个包的文件内都打印一行内容来验证一下),这个文件可以为空,但是也可以存放一些初始化包的代码。

     from glance.api import *

    在讲模块时,我们已经讨论过了从一个模块内导入所有*,此处我们研究从一个包导入所有*。

    此处是想从包api中导入所有,实际上该语句只会导入包api下__init__.py文件中定义的名字,我们可以在这个文件中定义__all___:

    #在__init__.py中定义
    x=10
    
    def func():
        print('from api.__init.py')
    
    __all__=['x','func','policy']
    View Code

     此时我们在于glance同级的文件中执行from glance.api import *就导入__all__中的内容(versions仍然不能导入)。

    glance/                   
    
    ├── __init__.py      
    
    ├── api                  
    
    │   ├── __init__.py   __all__ = ['policy','versions'] 
    
    │   ├── policy.py
    
    │   └── versions.py
    
    ├── cmd               __all__ = ['manage']    
    
    │   ├── __init__.py
    
    │   └── manage.py    
    
    └── db                __all__ = ['models']              
    
        ├── __init__.py
    
        └── models.py
    
    
    
    from glance.api import *
    policy.get()
    View Code

    绝对导入和相对导入

    在glance包内部也会有彼此之间互相导入的需求,这时候就有绝对导入和相对导入两种方式:

    绝对导入:以glance作为起始

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

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

    单独导入包名称时不会导入包中所有包含的所有子模块

    解决方法:
    
    1 #glance/__init__.py
    2 from . import cmd
    3 
    4 #glance/cmd/__init__.py
    5 from . import manage
    执行:
    
    1 #在于glance同级的test.py中
    2 import glance
    3 glance.cmd.manage.main()
    千万别问:__all__不能解决吗__all__是用于控制from...import * 

    import glance之后直接调用模块中的方法

    glance/                   
    
    ├── __init__.py     from .api import *
                        from .cmd import *
                        from .db import *    
    ├── api                  
    
    │   ├── __init__.py   __all__ = ['policy','versions'] 
    
    │   ├── policy.py
    
    │   └── versions.py
    
    ├── cmd               __all__ = ['manage']    
    
    │   ├── __init__.py
    
    │   └── manage.py    
    
    └── db                __all__ = ['models']              
    
        ├── __init__.py
    
        └── models.py
    
    
    import glance
    policy.get()
    View Code

    软件开发规范

    #=============>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][用户名不存在]
    View Code
  • 相关阅读:
    kettle excel input 利用通配符一次读入多份文件
    PowerDesigner Name、Code 映射设置
    PowerDesigner 建立约束
    PowerDesigner 创建概念模型、转换显示风格、概念模型转逻辑模型
    SQL 语言分类
    PowerDesigner 使用域、逻辑模型转物理模型、查看DDL语句
    DB、ETL、DW、OLAP、DM、BI关系结构图
    读懂BI商业智能与大数据应用的区别
    java 生成excel
    IntelliJ IDEA 2016 2.5 安装 并使用其新建一个maven web项目部署发布
  • 原文地址:https://www.cnblogs.com/olivia2018/p/8284174.html
Copyright © 2020-2023  润新知