• Python 模块和包


    模块和包,from 、import 的底层到底干了啥

    模块

    函数,是对某些功能的封装,而模块是将特定函数、类、对象等封装成形式为一个独立的 .py文件。是为了更合理的规范代码,维护代码,同类型的功能封装在一起,即简单清晰,更重要的是能避免命名冲突

    模块的出现方便了代码的组织管理,但是还存在像模块名冲突,模块杂乱,功能划分不具体等问题!为了解决这些问题,合理的管理Python的各种模块,引入了包管理的机制,即一个带有__init__.py文件的文件夹就称为一个包,包通过目录来组织模块。包可以包含包,包含模块,表现形式就是特殊的文件夹!

    包的分类

    内建的包 urllibmultiprocessingjson

    第三方包 DjangoflasknumpyPilow

    用户自定义包 就是我们自己写的 带有 __init__.py 的目录了

    包和模块的用法和注意事项

    关于命名

    包名和模块名尽量避免中文出现
    包名和模块名尽量的避免和Python的内置模块名和包名冲突,尤其是包名
    包和模块的命名,遵循Python变量命名规范

    安装

    # 类UNIX/Linux/OSX
    # 语法 pip3 install 包名==版本号 如果不确定具体的版本号 可用 ~= 代替 ==
    pip3 install django~=2.0    # 安装最靠近2.0版本的django
    pip3 install pymysql==0.93    # 安装 0.93 版本的 pymysql
    
    # windows 和 Linux 没太大差别
    

    通常我们会带上一些常用参数,或直接修改配置来指定pip的行为

    换pypi源

    # 使用 -i 参数
    pip install numpy -i https://mirrors.aliyun.com/pypi/simple/
    

    从requirements.txt安装

    # 使用 -r 参数   requirements.txt 文件必须在当前目录下
    pip install -r requirements.txt
    

    本地安装

    pip install setup.py
    

    从git安装

    # pip install git+git:仓库地址
    pip install git+git://github.com/blackmonkey121/verify.git
    

    包的导入

    先看官方文档

    sys.modules

    This is a dictionary that maps module names to modules which have already been loaded. This can bemanipulated to force reloading of modules and other tricks. However, replacing the dictionary will notnecessarily work as expected and deleting essential items from the dictionary may cause Python to fail.

    sys.path

    A list of strings that specifies the search path for modules. Initialized from the environment variablePYTHONPATH, plus an installation-dependent default.As initialized upon program startup, the first item of this list, path[0], is the directory containingthe script that was used to invoke the Python interpreter. If the script directory is not available (e.g.if the interpreter is invoked interactively or if the script is read from standard input), path[0] is theempty string, which directs Python to search modules in the current directory first. Notice that the scriptdirectory is inserted before the entries inserted as a result of PYTHONPATH.A program is free to modify this list for its own purposes. Only strings and bytes should be added to sys.path; all other data types are ignored during import.See also Module site This describes how to use .pth files to extend sys.path.

    sys.modules行为

    sys.modules中保存的是内存中已加载的模块名和模块地址的映射关系,它是一个字典。字典的键就是模块名 (str)字典的值是模块对象(确切的说是它的引用)

    sys.path行为

    指定模块搜索路径的字符串列表。从环境变量初始化python.path的初始值,加上默认的安装位置。

    import sys
    
    
    for path in sys.path:
        print(path)
    
    # /Users/ms    # 脚本所在的位置
    # /Library/Frameworks/Python.framework/Versions/3.6/lib/python36.zip
    # /Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6
    # /Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/lib-dynload
    # /Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages
    

    它在程序启动时初始化,此列表的第一项sys.path[0]就是脚本文件所在的位置(当前位置)。

    如果脚本目录不可用(例如如果以交互方式调用解释器或从标准输入读取脚本,则sys.path[0]是空字符串,指示python首先搜索当前目录中的模块。

    程序可以为自己的目的自由修改这个列表。只应将字符串和字节添加到sys.path;导入期间忽略所有其他数据类型。

    from ... import ...

    你似乎很熟悉他们,但他们的行为细节可能你知道的不足够。在这之前你要做好准备,他可能有些不太好理解。

    from 做了啥

    # 以这句话为例
    from PIL.image import getmodetype
    

    1 解释器遇到from,首先去sys.modules.keys()搜索模块名PIL,匹配不上就去sys.path的每一个路径下匹配模块名PIL

    2 匹配上,就在sys.modules添加一个新的映射{‘PIL’:PIL <module 'PIL' from '/Users/ms/Virtual/test.env/lib/python3.6/site-packages/PIL/init.py'>},然后去执行包下的__init__.py文件(如果__init__.py文件中存在from 则继续递归的执行)。此时会将当前目录下的子模块全部加载到该包的命名空间中。

    3 如果后面还有. 就到PIL下查找image ,一直重复下去直到遇见 import 关键字 停止from

    4 此时from 的工作已经完成。

    tips : 在任意一步中没法找到包或模块都会报错,来终止程序。

    import 做了啥

    # 以此为例
    import PIL
    

    1 解释器拿到import后,首先去sys.modules.keys()搜索模块名,匹配不上就去sys.path的每一个路径下匹配PIL,如果匹配上,就在sys.modules创建一个新的映射, 到此时与 from 的作用是一致的。

    2 然后Python会在内部创建这个对象(开辟空间),然后在这个空间解析这个对象(这也叫命名空间,就是导入模块时创建那个全局变量了),也就是在这个空间执行PIL。也正因如此,import 后的对象我们可以直接使用。而from 不行。

    3 如果import后面跟的是个包,则会执行__init__.py。如果是模块,则会直接执行该模块。

    tips:

    如果在 import 过程中遇见 fromimport 都会按照他们各自的行为去执行。

    from ... import ...

    使用from语句可以将模块或包递归的添加到 sys.modules。注意并没有执行代码,仅仅是执行了包下的__init__.py文件。

    # 以此为例
    from matplotlib import pyplot as plt
    

    from 会找寻 sys.modules 中是否存在 matplotlib,如果没找到,将会按照 sys.path 中的路径去逐个遍历寻找 matplotlib。(sys.path 的第一项总是当前目录,也就是说如果我们在当前目录下有一个文件叫matplotlib.py或者某个包叫 matplotlib,那将不会使用我们安装的 第三方matplotlib 因此 文件命名要注意这个问题。)

    一旦找到,将不会往下寻找,直接将找到的模块或包__init__.py 添加到sys.modules中,同时将所有的子模块都添加到该包的命名空间中。如果所有sys.path的目录下都没有找到将会报错。

    遇见import后该包的命名空间中寻找pyplot是否存在。不存在则报错,存在将pyplot对象加载到当前脚本的命名空间,并在此处执行pyplot, 如果 导入语句属于全局,那么该包也会属于全局,反之,则属于局部

    __init__ 和 __all__

    关于__init__.py

    __init__.py 中可以像正常的Python文件那样写一些代码,这些会在每次导入时被默认的执行。通常不建议在 该文件下编写代码。

    __all__ 通常会被推荐写在 __init__.py 中,它能控制包的导入行为, 当使用模糊导入时,如果__init__.py 文件为空,将不会导入任何模块。如果__init__.py写了 __all__ 则只会导入 __all__ 包含的对象。

    __all__ 是一个列表,列表对象应该是字符串。

  • 相关阅读:
    python 29day--异常处理及socket简介
    python 28day--类的总结
    python 27day--类的内置函数补充
    python 26day-- 面向对象的三大特性
    python 25day--面对对象进阶
    python 24day--python面向对象编程
    python 23day--python模块的应用
    python 22day--python的模块与包
    python 21day--文件的增删改查功能实现
    虚拟机的三种模式
  • 原文地址:https://www.cnblogs.com/monkey-code/p/13158848.html
Copyright © 2020-2023  润新知