Python模块与包

一、模块

在python中,模块就是一个代码文件,模块中可以定义类、函数、变量,也可以包含可执行的代码。

使用Import导入。

1.1 搜索路径

搜索模块时,python会按照sys.path列表中的路径,依次进行搜索。可以通过sys.path查看搜索路径。

将模块的路径添加到sys.path路径的三种方法:

(1)动态添加

sys.path.append(模块路径),动态添加需要每次在程序启动时,向sys.path添加。

(2)若经常用到,可以在Python安装目录下的Lib\site-packages文件夹下建立一个纯文本文件,扩展名为.path。

(3)修改环境变量。

1.2 导入模块

可以一次导入多个模块

1.3 导入指定的模块属性

如:from xlutils.copy import copy

1.4 加载模块

在程序开发中,一个模块可以在多处被import,但Python只会导入一次,因为所有加载到内存的模块都会被放入到sys.modules中。

加载模块会导致这个模块被“执行”。

1.5 名称空间

Python程序执行时存在内建名称空间、全局名称空间和局部名称空间。

1.6 “编译”的Python文件

Python中一旦被引用的模块(假设为example.py)被成功编译,其对应的编译版本example.pyc就会被创建。如果创建成功,那么example.py的修改时间会记录在example.pyc中,下次载入时,如果两个文件的修改时间不匹配,则.pyc文件就会被忽略。如果有可用的.pyc文件,则会使用.pyc文件提高模块的加载速度。当程序需要加载多个模块时,.pyc文件能够有效地提高程序的启动速度。

1.7 自动导入模块

sys模块的modules变量中存储了完整且成功导入的模块信息。

1.8 循环导入

循环导入(circular import)是一种死循环,即A代码需要B才能执行,而偏偏B代码是建立在A代码基础上。

二、包

包(Package)可以看成模块的集合,只要一个文件夹下面有__init__.py文件,那么该文件夹就可以看作一个包。包下面还可以有子包。

导入包的过程与导入模块的基本一致,只是导入包的时候会执行目录下的__init__.py,而不是模块里的语句。另外,如果只是单纯地导入包,而包的__init__.py中又没有明确的其他初始化操作,那么此包下面的模块是不会自动导入的。

例如,一个简章的包目录

Pac/
        __init__.py
        Subpac1/
                __init__.py
                Modu1.py
        Subpac2/
                __init__.py
                Modu1.py

导入方法:

from Pac.Subpac1 import Modu1

import Pac.Subpac1.Modu1

三、程序打包

Python提供了Distutils、Setuptools、Py2exe、PyInstaller、cx_freeze等程序打包工具,其中,Setuptools是Distutils的增强工具,Py2exe、PyInstaller、cx_freeze是windows平台下制作exe文件的工具。Distutils包含在Python的标准版发行包中。

3.1 Distutils

例如,首先建立一个hello.py文件。

(1)建立一个setup.py文件,内容如下:
f

rom distutils.core import setup
setup(name='hello',version='1.0',description='hello ccc',author='cheng',py_modules=['hello'])

(2)执行打包命令:

   >>>python setup.py sdist

结果:该命令创建了dist目录,并将要打包的文件复制到hello-1.0.zip的压缩文件中。

3.2 py2ext

py2exe暂时到目前只支持到3.4版本(包括cxfreeze),在3.5版本中会报错。

(1)建立建立一个setup.py文件,内容如下:
from distutils.core import setup
import py2exe
setup(console=[‘hello.py’])

(2)执行命令:

>>>python setup.py py2exe

以下内容转载自:
https://blog.csdn.net/qq_33961117/article/details/81561221
‘’’
模块:包括了一系列功能的集合体

三种来源:1.内置的模块 2. 第三方的模块 3. 自定义模块
四种格式:

  1. 用python编写的.py文件
    2.已被编译为共享库或DLL的C或者C++扩展
  2. 一系列模块组织到一起的文件夹(主:文件夹下有一个__init__.py文件,该文件夹称之为包)
  3. 使用C编写并链接到python解释器的内置模块

为何要使用模块?
1、使用自定义模块的好处:从文件级别组织程序,更方便管理,减少代码冗余
2、使用内置或第三方模块的好处:拿来主义,提升开发效率
ps:
如果你退出python解释器然后重新进入,那么你之前定义的函数或者变量都将丢失,
因此我们通常将程序写到文件中以便永久保存下来,需要时就通过python test.py方式去执行,
此时test.py被称为脚本script。
‘’’

‘’’
使用模块(import的使用):
1. import 模块名 导入模块
总结:1.1在使用的时候必须以:模块名.名字的形式
1.2 优点:指名道姓的像某一个名称空间要名字,不会与当前名称空间的名字冲突
1.3 缺点:但凡调用都需要加上前缀,使用不够简洁
注:首次导入模块时:
1.产生一个模块的名称空间
2.执行模块文件,在执行过程中,将产生的名字变量传入名称空间的内存地址中
3.在执行文件中的到一个模块名,其指向模块文件的名称空间地址
之后的重复导入操作,都只是指向之前导入的结果地址,不会重新执行首次导入的三步操作4

2.在文件中访问模块名称空间中名字的语法:模块名.名字
例:time.x --------》寻找time模块文件中的x名字(或许是变量名,或许是函数名)

3.一行多个模块同时导入(不推荐)
例:import time,os.spam

4.可以为模块起别名(注:模块名应该全为小写)
例:import time as t

‘’’
‘’’
使用模块(from…import…):
1.优点,使用时不需要加前缀,使用简洁
2.缺点,易重名产生冲突,且后定义赋值 覆盖 前一个定义赋值的值
3.取模块内全部名字(不推荐) from time import *
*对于模块内__all__列表存储名字,若没有另外定义则返回所有名字(不包含_开头的变量名)
4.起别名:from time import m as m1

注:首次导入模块时:
1.产生一个模块的名称空间
2.执行模块文件,在执行过程中,将产生的名字变量传入名称空间的内存地址中
3.在执行文件中直接拿到指定模块内的名字(或变量或函数)
例: from time import x 取出了time模块的x名字
‘’’
‘’’
循环导入问题(test文件:m1,m2,run):
模块的导入会在执行文件的时候创造名称空间,且仅一次
如果执行步骤上python发现一家存在已创建的名称空间,则不会继续导入
若执行文件在导入名字的时候被模块1内的导入模块2打断,则不会导入模块1的后续变量
因为,python当检测到已经存在名称空间,则不会继续往名称空间内添加。

解决方法一:
把循环导入的语句放到名字的下方
原因:让执行文件导入模块1的时候,直接导入所有模块内名字,不会被模块1内的模块2导入打断

解决方法二:
将循环导入语句放到函数内
原因:不执行函数的时候,只检测函数语法而不运行函数
‘’’

‘’’
区别.py文件是执行文件还是模块文件(name):
即:判断文件的__name__属性
当文件被执行时(执行文件),name == ‘main
当文件被导入时(模块文件),name == ‘模块名’
注:(快捷方式) 输入main 自动提示 if name == ‘main
‘’’

‘’’
模块的搜索路径:

模块搜索路径的优先级:
    1.内存中,已经加载过的
    2.内置模块
    3.sys模块中的path列表(sys.path),以当前执行文件所在文件夹绝对路径为首

强调:sys.path(环境变量)中的路径以执行文件的路径为准,包括被导入模块的环境变量
(测试练习 环境变量测试文件夹内)

注:若找不到路径,解决方法:
1.在执行文件中的sys.path内添加模块文件所在路径(处理环境变量),可以sys.path.append(绝对路径)
2.(子文件夹)from 和执行文件同级的文件夹名 import 模块文件名
3.(二级及以上子文件夹)from dir1.dir2 import m2 ---->dir1是dir2的父文件夹,m2位于dir2文件夹中
‘’’

‘’’
绝对导入和相对导入:

绝对导入:以执行文件的sys.path为依据导入
    优点:执行文件和模块文件都可以使用
    缺点:所有导入都以sys.path为依据,导入麻烦

相对导入:参照当前文件的文件夹为起始查找文件,称为相对导入
    符号:.代表当前所在文件,..代表上级文件夹,...代表上上级文件夹
        例:from . import m2 ; from .dir1 import m2
    优点:导入更加简单
    缺点:只能在被导入的模块中使用,不能在执行文件中使用

‘’’

‘’’
软件开发的目录规范:
-ATM
-bin
-start.py

        #启动文件,即 main文件
        import sys,os
        BASE_DIR = os.path.dirname(os.path.dirname(__file__))
            #BASE_DIR 讲ATM项目文件夹路径加入环境变量
        sys.path.append(BASE_DIR)
        
        from core import db
            #导入核心逻辑模块 用于后续综合功能
        
        if __name__ = 'main' :
            db.run()
        #用于 执行判断
        
    -conf
        -setting.py
        
        #设置文件,用来保存全局使用的变量名
        import os
        BASE_DIR = os.path.DIRNAME(os.path.DIRNAME(__file__))
        DB_PATH=os.path.join(BASE_DIR,'db','db.json')
        LOG_PATH=os.path.join(BASE_DIR,'log','access.log')
        LOGIN_TIMEOUT=5
        .......
        
    -core
        -db.py
        #核心逻辑代码,不包括核心逻辑中存在的需求代码
        from conf import settings
        from lib import common
        import time
        
        def login():
            #登陆
            print('login')
            
        def register():
            #注册
            print('register')
        
        ...
        
    -db
        -db.json
        #数据库文件,用来保存用户登陆信息
        
    -lib
        -common.py
        #自定义模块,可用来辅助完成核心逻辑所需模块
        from conf import settings
        import logging
        import logging.config
        import json
        
        def get_logger(name):
            logging.config.dictConfig(settings.LOGGING_DIC)  # 导入上面定义的logging配置
            logger = logging.getLogger(name)  # 生成一个log实例
            return logger
        
        
        def conn_db():
            db_path=settings.DB_PATH
            dic=json.load(open(db_path,'r',encoding='utf-8'))
            return dic
            
            
    -log
        -access.log
        #按照setting文件中的格式,保存操作日志
        
    -readme.txt
        #项目解释文件

‘’’

‘’’
包:包就是一个包含有__init__.py文件的文件夹,本质是一种模块
创建包的目的:
为了用文件夹将文件/模块组织起来

导入包的三部曲:
1.以包下的__init__.py文件为基准来产生一个名称空间
2.执行包下的__init__.py文件的代码,将执行过程中产生的名字都丢入名称空间
3.在当前执行文件中拿到一个p1,p1指向__init__.py名称空间

导入包需要注意的问题:
1.但凡是在 导入语句 中带点的,点的左边都必须是一个包
2.包内部模块的绝对导入的起始位置都是以包的顶级目录为起始点
3.包内部模块的导入通常应该使用 相对导入 ,方便设计者对包顶级目录的修改操作
.-本级 …-上级 …-上上级
注意:
1.相对导入 只能在包内部的模块之间互相导入
2. …上一级 不能超出顶级包
注意:
1. 在python3中,即使包下没有__init__.py文件,import 包仍然不会报错
而在python2中,包下一定要有该文件,否则import 包报错
  2. 创建包的目的不是为了运行,而是被导入使用
记住,包只是模块的一种形式而已,包的本质就是一种模块

‘’’

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值