python 包和模块

基本概念

模块

为了使代码更容易维护,提高代码重用价值;可以将一组相关功能的代码写入一个单独的py文件中,供别人导入使用,这个py文件就被称作是一个模块

包是一个有层次的文件目录结构,它定义了由n个模块或n个子包
具体表现形式:包含__init__.py 文件的目录,这个目录下一定得有这个__init__.py文件和其它模块或子包

参照其他编程语言的一个喊法
完成一点功能的代码集合
具体表现可以是一个模块,也可以是包

框架

一个架构层面的概念
从库功能角度来看,解决一个开放性问题而设计的具有一定约束性的支撑结构
通过一个框架,可以快速实现一个问题解决的骨架;到时按照框架角色去填充,交互就可以完成一个质量好,维护性高的项目。
web框架 Flask Django

包和模块的作用

编写好一些轮子,工具代码,供其他模块调用
有效的对程序进行分解,方便代码的管理和维护
可以防止同一模块内的命名重复问题

分类

标准包模块

安装python后,自动帮我们安装好的一些模块,可以直接导入使用
特殊:内建包、模块
当我们在编码的过程中,python自动帮我们导入的模块,builtins,不需要手动的导入该模块,直接使用就可以。

import builtins

print(dir(builtins))

[‘ArithmeticError’, ‘AssertionError’, ‘AttributeError’, ‘BaseException’, ‘BlockingIOError’, ‘BrokenPipeError’, ‘BufferError’, ‘BytesWarning’, ‘ChildProcessError’, ‘ConnectionAbortedError’, ‘ConnectionError’, ‘ConnectionRefusedError’, ‘ConnectionResetError’, ‘DeprecationWarning’, ‘EOFError’, ‘Ellipsis’, ‘EnvironmentError’, ‘Exception’, ‘False’, ‘FileExistsError’, ‘FileNotFoundError’, ‘FloatingPointError’, ‘FutureWarning’, ‘GeneratorExit’, ‘IOError’, ‘ImportError’, ‘ImportWarning’, ‘IndentationError’, ‘IndexError’, ‘InterruptedError’, ‘IsADirectoryError’, ‘KeyError’, ‘KeyboardInterrupt’, ‘LookupError’, ‘MemoryError’, ‘ModuleNotFoundError’, ‘NameError’, ‘None’, ‘NotADirectoryError’, ‘NotImplemented’, ‘NotImplementedError’, ‘OSError’, ‘OverflowError’, ‘PendingDeprecationWarning’, ‘PermissionError’, ‘ProcessLookupError’, ‘RecursionError’, ‘ReferenceError’, ‘ResourceWarning’, ‘RuntimeError’, ‘RuntimeWarning’, ‘StopAsyncIteration’, ‘StopIteration’, ‘SyntaxError’, ‘SyntaxWarning’, ‘SystemError’, ‘SystemExit’, ‘TabError’, ‘TimeoutError’, ‘True’, ‘TypeError’, ‘UnboundLocalError’, ‘UnicodeDecodeError’, ‘UnicodeEncodeError’, ‘UnicodeError’, ‘UnicodeTranslateError’, ‘UnicodeWarning’, ‘UserWarning’, ‘ValueError’, ‘Warning’, ‘WindowsError’, ‘ZeroDivisionError’, ‘build_class’, ‘debug’, ‘doc’, ‘import’, ‘loader’, ‘name’, ‘package’, ‘spec’, ‘abs’, ‘all’, ‘any’, ‘ascii’, ‘bin’, ‘bool’, ‘breakpoint’, ‘bytearray’, ‘bytes’, ‘callable’, ‘chr’, ‘classmethod’, ‘compile’, ‘complex’, ‘copyright’, ‘credits’, ‘delattr’, ‘dict’, ‘dir’, ‘divmod’, ‘enumerate’, ‘eval’, ‘exec’, ‘execfile’, ‘exit’, ‘filter’, ‘float’, ‘format’, ‘frozenset’, ‘getattr’, ‘globals’, ‘hasattr’, ‘hash’, ‘help’, ‘hex’, ‘id’, ‘input’, ‘int’, ‘isinstance’, ‘issubclass’, ‘iter’, ‘len’, ‘license’, ‘list’, ‘locals’, ‘map’, ‘max’, ‘memoryview’, ‘min’, ‘next’, ‘object’, ‘oct’, ‘open’, ‘ord’, ‘pow’, ‘print’, ‘property’, ‘quit’, ‘range’, ‘repr’, ‘reversed’, ‘round’, ‘runfile’, ‘set’, ‘setattr’, ‘slice’, ‘sorted’, ‘staticmethod’, ‘str’, ‘sum’, ‘super’, ‘tuple’, ‘type’, ‘vars’, ‘zip’]

三方包和模块

其他开发人员,需要下载安装才可以

自定义包和模块

自己写的模块

创建

创建模块

直接创建.py文件即可

创建包

创建一个文件夹,文件夹内务必创建一个__init__.py这个文件
import 时会自动执行__init__.py

模块信息

查看模块路径:

import os

print(os.__file__)

C:\Users\wqr57\AppData\Local\Programs\Python\Python37\lib\os.py

查看模块内容:

import os

print(dir(os))

导入

import M
如果某个包里的模块,可以通过点语法来定位

import M1, M2

import M as 别名
导入模块时,给模块起个别名

if file_extension == 'txt':
    import txt_parse as p
else file_extension == 'doc':
    import doc_parse as p

p.open()
p.read()
p.close()

包和模块都是对象。
如果导入的是一个包,默认不会导入任何模块
解决方法:
在__init__.py, 再次导入需要的模块(import p1.Tool)

from语句导入

from A import B [as C]

可以从包中导入模块,可以从模块中导入模块资源
可以单个,多个,起别名。
有多层级时,在A处多层级,B处最简。
包里面只能看到模块,看不到模块资源。
from 包.模块 import 内容

只看import 后面的东西

模块通过__all__ 列表字符串告诉外界*可调用内容
from 模块 import *
from 包 import *

需要在模块中添加 __all__ = [‘num1’, ‘num2’],字符串来告诉外界。
需要在包的__init__.py 中添加__all__ = [‘tool1’, ‘tool2’]
变量__all__ 匹配 *
没有__all__ 则导入所有,除了_开头的私有变量

慎用,因为你无法预知到时会导入哪些内容到当前位置,容易产生变量名冲突

导入模块后具体做了什么

第一次导入:

  1. 在自己当下的命名空间中,执行所有代码
  2. 创建一个模块对象,并将模块内所有顶级变量以属性的形式绑定在模块对象上
  3. 在 import 的位置,引入import后面的变量名称到当前命名空间

第二次导入时:
直接执行上述步骤3

结论:
注意,两种导入方式都会大致执行以上的步骤
多次导入模块,该模块并不会执行多次
两种导入方式不存在哪一种更省内存,区别在于把哪一部分内容拿到当前位置来用

导入模块位置顺序

第一次导入时

按照模块检索路径顺序去找,

  1. 内置模块
  2. sys.path

sys.path 构成:

  1. 当前目录
  2. 环境变量PYTHONPATH 中指定的路径列表
  3. 特定路径下的.pth文件中的文件路径列表
  4. 在python 安装路径的lib 库中搜索
import sys

print(sys.path)

['d:\\python\\python_learn', 'C:\\Users\\wqr57\\AppData\\Local\\Programs\\Python\\Python37\\python37.zip', 'C:\\Users\\wqr57\\AppData\\Local\\Programs\\Python\\Python37\\DLLs', 'C:\\Users\\wqr57\\AppData\\Local\\Programs\\Python\\Python37\\lib', 'C:\\Users\\wqr57\\AppData\\Local\\Programs\\Python\\Python37', 'C:\\Users\\wqr57\\AppData\\Roaming\\Python\\Python37\\site-packages', 'C:\\Users\\wqr57\\AppData\\Local\\Programs\\Python\\Python37\\lib\\site-packages', 'C:\\Users\\wqr57\\AppData\\Local\\Programs\\Python\\Python37\\lib\\site-packages\\win32', 'C:\\Users\\wqr57\\AppData\\Local\\Programs\\Python\\Python37\\lib\\site-packages\\win32\\lib', 'C:\\Users\\wqr57\\AppData\\Local\\Programs\\Python\\Python37\\lib\\site-packages\\Pythonwin']

追加路径的方式

直接修改sys.path

只作用于本次

import sys

print(sys.path)
sys.path.append(r'C:\User\my_directory')
print(sys.path)
['d:\\python\\python_learn', 'C:\\Users\\wqr57\\AppData\\Local\\Programs\\Python\\Python37\\python37.zip', 'C:\\Users\\wqr57\\AppData\\Local\\Programs\\Python\\Python37\\DLLs', 'C:\\Users\\wqr57\\AppData\\Local\\Programs\\Python\\Python37\\lib', 'C:\\Users\\wqr57\\AppData\\Local\\Programs\\Python\\Python37', 'C:\\Users\\wqr57\\AppData\\Roaming\\Python\\Python37\\site-packages', 'C:\\Users\\wqr57\\AppData\\Local\\Programs\\Python\\Python37\\lib\\site-packages', 'C:\\Users\\wqr57\\AppData\\Local\\Programs\\Python\\Python37\\lib\\site-packages\\win32', 'C:\\Users\\wqr57\\AppData\\Local\\Programs\\Python\\Python37\\lib\\site-packages\\win32\\lib', 'C:\\Users\\wqr57\\AppData\\Local\\Programs\\Python\\Python37\\lib\\site-packages\\Pythonwin', 'C:\\User\\my_directory']

修改环境变量

PYTHONPATH
在这里插入图片描述
在这里插入图片描述

添加.pth文件

存放.pth文件的位置:

import site

print(site.getsitepackages())
['C:\\Users\\wqr57\\AppData\\Local\\Programs\\Python\\Python37', 'C:\\Users\\wqr57\\AppData\\Local\\Programs\\Python\\Python37\\lib\\site-packages']

第二次导入时

从已经加载过的模块中去找
查看已加载模块的方式

import sys
sys.modules

局部导入

在某个局部范围内导入模块,如果想要在全局范围都能使用,在文件顶部导入相关模块

覆盖导入

自定义模块和非内置的标准模块重名,根据前者存储位置,有可能前者会覆盖后者,自定义模块不要与标准模块重名。

使用from package import module

循环导入

模块A内导入了模块B,模块B内也导入了模块A,这样就造成了循环导入
在sys.modules 查找模块

可选导入

两个功能相近的包根据需求优先选择其中一个导入
有两个包A和B都可以实现相同的功能,想优先使用A,而且需要做的在没有A的情况下,使用B做备选

# 优先导入other2

try:
    import other2 as o
except ModuleNotFoundError:
    import other as o

print(o.o1)

包内导入

分为绝对导入和相对导入
包内导入即是包内的模块导入包内部的模块

绝对导入:参照sys.path路径进行检索
例如指明包名或模块名,import a, from a import b

相对导入:使用.来指代相对路径
. 根据模块名称所获取的当前目录
… 根据模块名称所获取的上层目录
from . import a
from … import a

当我们尝试去使用解释器去执行某一个py文件的时候,那他就会确定当前文件所在的目录,然后把这个目录添加到sys.path
添加过之后,sys.path里面的内容几经确定

如果一个py文件直接以脚本的形式进行执行python file,他的名称就是 __main__
如果是使用模块的形式进行加载,那么他的名称由加载的路径决定的,包名.子包名.模块名

print(__name__)
# __main__

正确用法:包内导入使用相对导入,保外导入使用绝对导入

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值