V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
ansheng
V2EX  ›  Python

Python 标准库系列之模块介绍

  •  
  •   ansheng ·
    anshengme · 2017-02-03 19:00:26 +08:00 · 1585 次点击
    这是一个创建于 2876 天前的主题,其中的信息可能已经有所发展或是发生改变。

    Python 的模块其实就是封装了一个或者多个功能的代码集合,以便于重用,模块可以是一个文件也可以是一个目录,目录的形式称作

    模块分类

    内置模块

    内置模块可以理解成当你安装好 python 环境之后,直接可以使用import导入的就是内置模块,默认模块路径为:C:\Python35\lib,你也可以通过以下方式获取内置模块的路径:

     # 导入 sys 模块
     >>> import sys
     # 最后一个目录就是内置模块的路径
     >>> for n in sys.path:
     ...  print(n)
     ...
    
    C:\Python35\lib\site-packages\pip-8.1.1-py3.5.egg
    C:\Python35\python35.zip
    C:\Python35\DLLs
    C:\Python35\lib
    C:\Python35
    C:\Python35\lib\site-packages
    

    第三方模块

    第三方模块通常是开发者自己编写的模块,然后提交到 python 官方的库中,这样我们就可以下载安装使用了,默认安装目录为C:\Python35\lib\site-packages

    自定义模块

    自己编写的模块

    模块的导入方式

    把一个模块当做成一个整体来进行导入

    import sys
    

    从一个模块中导入特定的变量或者是方法

    from sys import path
    

    调用的时候直接使用方法名path

    >>> path
    ['', 'C:\\Python35\\lib\\site-packages\\pip-8.1.1-py3.5.egg', 'C:\\Python35\\python35.zip', 'C:\\Python35\\DLLs', 'C:\\Python35\\lib', 'C:\\Python35', 'C:\\Python35\\lib\\site-packages']
    

    给导入的模块或者方法起一个别名

    from sys import path as path_alias
    

    调用的时候使用别名path_alias

    >>> path_alias
    ['', 'C:\\Python35\\lib\\site-packages\\pip-8.1.1-py3.5.egg', 'C:\\Python35\\python35.zip', 'C:\\Python35\\DLLs', 'C:\\Python35\\lib', 'C:\\Python35', 'C:\\Python35\\lib\\site-packages']
    

    添加默认的环境变量,当前生效

    sys.path.append("PATH_NAME")
    

    可以使用imp模块中的reload方法重新载入某个模块的方法,例如下面的实例:

    $ cat simple.py 
    #!/use/bin/env python
    
    print('Hello, World!')
    spam = 1
    
    >>> import simple
    Hello, World!
    >>> simple.spam
    1
    >>> simple.spam += 1
    >>> import simple
    >>> simple.spam
    2
    >>> import imp
    >>> imp.reload(simple)
    Hello, World!
    <module 'simple' from '/Users/ansheng/simple.py'>
    >>> simple.spam
    1
    

    模块导入顺序

    1. 先在当前脚本目录寻找有没有与导入模块名称相同的文件,如果有就把这个文件当作模块导入(据不完全统计,这是个坑,测试re模块没有问题,但是测试sys模块就有问题了)
    2. 查找模块路径下面有没有对应的模块名
    3. 如果没有找到模块名就报错

    import 是如何工作的?

    模块在被导入的时候会执行以下三个步骤:

    1. 通过环境变量找到模块文件;
    2. 编译成字节码文件,如果有字节码文件则导入字节码文件;
    3. 执行模块中的代码来创建所定义的对象;

    以上的三个步骤只有在程序运行时,模块被第一次导入时才会进行。如果已经导入了这个模块然后再次导入的时候会跳过上面的三个步骤,它会直接提取内存中已经加载的模块对象。 Python 已经导入的模块会保存在sys.modules字典中。

    _X 与__all__

    在模块中的所有变量以_开头的都不会被from *所导入

    $ cat simple.py 
    #!/use/bin/env python
    
    _spam1 = 1
    spam2 = 1
    
    >>> from simple import *
    >>> dir()
    # _spam1 没有被导入
    ['__builtins__', '__doc__', '__name__', '__package__', 'spam2']
    

    相反的__all__列表里面的变量则会被from *所导入,没有在__all__列表里面的变量则不会被导入

    $ cat simple.py
    #!/use/bin/env python
    
    __all__ = ['spam2']
    
    spam1 = 1
    spam2 = 1
    
    >>> from simple import *
    >>> dir()
    # spam1 没有被导入
    ['__builtins__', '__doc__', '__name__', '__package__', 'spam2']
    

    注意事项

    据不完全统计,如果导入的模块的名称在当前目录下有这个文件,那么只会把当前目录下的这个文件当作模块,如下演示:

    创建一个脚本文件,名称为 scripts

    [root@iZ28i253je0Z ~]# touch scripts.py
    

    内容为

    #!/usr/bin/env python
    # _*_ coding:utf-8 _*_
    # 导入一个模块 re
    import re
    # 输出匹配到的字符串 abc
    print(re.match('\w+',"abc").group())
    

    执行脚本

    [root@iZ28i253je0Z ~]# python scripts.py 
    # 把匹配到的结果 abc 输出出来
    abc
    

    创建一个.py文件,名称为re.py

    [root@iZ28i253je0Z ~]# touch re.py
    

    内容为

    #!/usr/bin/env python
    # _*_ coding:utf-8 _*_
    # 输出内容 modus
    print("Hello Word")
    

    再次执行scripts.py脚本

    [root@iZ28i253je0Z ~]# python scripts.py 
    # 先输出 Hello Word
    Hello Word
    # 然后再报错没有 match 这个方法
    Traceback (most recent call last):
      File "scripts.py", line 6, in <module>
        print(re.match('\w+',"abc").group())
    AttributeError: 'module' object has no attribute 'match'
    

    这是为什么呢?因为pythonre.py当成模块re了,继续往下看:

    更改scripts.py文件内容如下

    [root@iZ28i253je0Z ~]# cat scripts.py 
    #!/usr/bin/env python
    # _*_ coding:utf-8 _*_
    
    import re
    

    re.py文件内容不变,然后我们在执行脚本scripts.py

    [root@iZ28i253je0Z ~]# python scripts.py 
    Hello Word
    

    看到了吧,他会把re.py文件内的代码拿到scripts.py文件中去执行,这是个坑,最好别踩。

    导入当前目录下子目录下的文件

    [root@ansheng ~]# tree ./
    ./
    ├── modules
    │   ├── __init__.py
    │   ├── lib01.py
    │   └── lib02.py
    └── scripts.py
    
    1 directory, 4 files
    [root@ansheng ~]# cat scripts.py 
    #!/usr/bin/env python
    # 导入 modules 包下面的 lib01 模块
    from modules import lib01
    # 导入 modules 包下面的 lib02 模块
    from modules import lib02
    [root@ansheng ~]# cat modules/__init__.py 
    #!/usr/bin/env python
    [root@ansheng ~]# cat modules/lib01.py 
    #!/usr/bin/env python
    # lib01.py 文件会输出"Hello lib01"
    print("Hello lib01")
    [root@ansheng ~]# cat modules/lib02.py  
    #!/usr/bin/env python
    # lib02.py 文件会输出"Hello lib02"
    print("Hello lib02")
    

    执行结果

    [root@ansheng ~]# python scripts.py
    # 会执行 modules/lib02.py 与 modules/lib01.py 文件内容
    Hello lib01
    Hello lib02
    

    包含目录下的文件时需要在目录下声明一个__init__.py文件,即使这个文件是空的也可以。


    原文链接

    julyclyde
        1
    julyclyde  
       2017-02-03 22:08:52 +08:00
    这跟标题里的“标准库”有啥关系?
    billytv
        2
    billytv  
       2017-02-04 10:54:01 +08:00
    谢谢, 把旧知识重温了一遍
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1852 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 16:21 · PVG 00:21 · LAX 08:21 · JFK 11:21
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.