zoukankan      html  css  js  c++  java
  • Python学习第二阶段,Day2,import导入模块方法和内部原理

    怎样导入模块和导入包??

    1.模块定义:代码越来越多的时候,所有代码放在一个py文件无法维护。而将代码拆分成多个py文件,同一个名字的变量互不影响,模块本质上是一个.py文件或者".py"、".pyo"、".pyc"、".pyd"、".so"、".dll"结尾的文件,使用模块可以更有逻辑地组织Python代码段。简单来说,模块就是一个保存了Python代码的文件。模块能定义函数,类和变量。模块里也能包含可执行的代码。

      如果路人甲写的模块和路人乙写的模块中都有Util.py模块怎么办呢》?可以使用包package区分。  因为路人甲(p1.util)和路人乙(p2.util)同名模块的完整模块名不同。

    2.定位模块

    当你导入一个模块,Python解析器对模块位置的搜索顺序是:
    * 当前目录
    * 如果不在当前目录,Python 则搜索在 shell 变量 PYTHONPATH 下的每个目录。
    * 如果都找不到,Python会察看默认路径。UNIX下,默认路径一般为/usr/local/lib/python/。
    模块搜索路径存储在system模块的sys.path变量中。变量里包含当前目录,PYTHONPATH和由安装过程决定的默认目录。

    2.导入模块:

    import  a,b,c,d... 从PATH路径搜索到abcd   执行的时候是a.xx

    from  p import  a,b,c.... 从PATH路径搜索到p再到它儿子 abc...   执行的时候  a.xx   b.xx

    import  p.a,p.b     执行的时候  p.a.xx    p.b.xx 

    from p import *     从PATH路径搜索到p再到它所有儿子...

    导入模块干的事可以理解为1、把模块的一坨代码用一个名字代替(后面可以引用)

                                               2、运行当前脚本的时候会依次执行模块里的代码(相当于直接把代码复制粘贴过来)

    导入模块干的事情就是:把模块的代码复制粘贴过来,然后给他们整体取个名字(这样可以避免重复的方法等),如果方法或类重名可以用模块去包装,模块重名可以用包或目录去包装

    用的时候考虑  “这样会不会引起重名”  这样的问题就可以了

    例如.../day2/core/ccc.py  中想导入.../day2/module/model1.py 模块 

    # model1.py 模块内容
    attr = "model1 attr.........."
    def md1():
    print("this is model1.md1 function")
    import os,sys
    
    DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
    sys.path.append(DIR)  #....day2绝对路径
    
    
    from module import model1   # 这里不能直接用import,因为model1不直接在day2绝对路径下 
    
    print(model1.attr)
    model1.md1()
    View Code

          A  模块与主程序在同一目录下,模块与主程序为“兄弟”关系:   直接import  modulename

      B  模块在主程序所在文件夹的子文件夹下,主程序是模块的“叔叔”:.../main.py    .../module/model.py

          直接  import  module.model  调用:module.model.func()          或者   from module import  model    调用:model.func()

      C  模块在主程序上级目录中,或者在主程序上级目录的子目录。 模块跟主程序之间的关系是 “堂/表兄弟” 关系:

         模块的init文件 import  sys

                sys.path.append("..")

    ---------------------------------------------------------------

         主程序  import __init__                       Python3  没用了

            import  suf.model

     -----------------------c第二种方式------------------------------------------------------------------

    BASE_DIR = os.path.dirname(  os.path.dirname(  os.path.abspath(__file__)  )   ) :  再上一级Atm

    sys.path.append( BASE_DIR )   添加环境变量

    ----------------------------------------

    看个例子:Python脚本是顺序执行的,程序中的路径都是该脚本所在的位置做为基准的,所以在不同的地方去执行,有的会报错:“找不到文件或路径”

    目录结构:

    | Group

      | conf

        info

      | core

        file_io

          file_io.py

        main_business

          main_bus1.py

          main_bus2.py

        main.py

    -----------main_bus1.py
    import os
    import sys
    
    BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
    sys.path.append(BASE_DIR)
    
    from file_io.file_io import read_file
    
    def main_bus1_1(str_object):
        print("main_bus1_1", str_object)
        print(read_file('../../conf/info'))
    
    def main_bus1_2(str_object):
        print("main_bus1_2", str_object)
    
    main_bus1_1("sssssssssss")  # 执行成功
    ---------main.py---
    from main_business.main_bus1 import main_bus1_1
    
    main_bus1_1("a")  # 执行错误No such file or directory: '../../conf/info' 
                        # 将上面print(read_file('../../conf/info'))改为print(read_file('../conf/info'))后执行成功

     可以看出 from import  相当于将代码原封不动的定义

    一般情况应该使用import , 但有几个例外 
    1)module文档告诉你要用from-import的 
    2)导入一个包组件。需要一个包里面的某个子模块,一般用from A.b import c比import A.b.c 更方便 且不会冒混淆的危险.这个纯属扯淡吧! 。。。。我个人还是觉得A.b.c 不会混淆

    Python中模块、库、包区别 ::

    模块,包含并且有组织的代码片段为模块。

    包是一个有层次的文件目录结构,它定义了由n个模块或n个子包组成的python应用程序执行环境。通俗一点:包是一个包含__init__.py 文件的目录,该目录下一定得有这个__init__.py文件和其它模块或子包。

    常见问题:

    引入某一特定路径下的模块

    使用sys.path.append(yourmodulepath)

    将一个路径加入到python系统路径下,避免每次通过代码指定路径

    利用系统环境变量 export PYTHONPATH=$PYTHONPATH:yourmodulepath

    直接将这个路径链接到类似/Library/Python/2.7/site-packages目录下

    好的建议:

    经常使用if __name__ == '__main__',保证写包既可以import又可以独立运行,用于test

    __name__是模块的名字, 如果该模块是被import的,__name__为模块名,如果该模块是主程序入口,调用其他模块的模块,那么它的__name__就为'__main__'

    多次import不会多次执行模块,只会执行一次。可以使用reload来强制运行模块,但不提倡。

    常见的包结构如下:

    package_a├── __init__.py├── module_a1.py└── module_a2.py  

    package_b├── __init__.py├── module_b1.py└── module_b2.py

    main.py

    如果main.py想要引用package_a中的模块module_a1,可以使用:

    from package_a import module_a1

    import package_a.module_a1

    如果package_a中的module_a1需要引用package_b,那么默认情况下,python是找不到package_b。

    我们可以在package_a中的__init__.py添加这句话sys.path.append('../'),,然后该包下得所有module都添加* import __init_即可。

    库:

     库的概念是具有相关功能模块的集合。这也是Python的一大特色之一,即具有强大的标准库、第三方库以及自定义模块。

    为什么包要有__init__.py

    在python模块的每一个包中,都有一个__init__.py文件(这个文件定义了包的属性和方法)然后是一些模块文件和子目录,假如子目录中也有__init__.py 那么它就是这个包的子包了。当你将一个包作为模块导入(不论是import  pack.mod还是from pack import mod)的时候,实际上导入了它的__init__.py 文件。    如果仅仅import  pack  而 __init__里面为空的话,那么主程序里是不能使用mod的,想使用mod 还需要在__init__里面写:import mod   现在应该明白了吧

    确实不能这样import pack  然后下面写pack.mod.func  因为调用只能是上面:命名.func

    一个包是一个带有特殊文件 __init__.py 的目录。__init__.py 文件定义了包的属性和方法。其实它可以什么也不定义;可以只是一个空文件,但是必须存在。如果 __init__.py 不存在,这个目录就仅仅是一个目录,而不是一个包,它就不能被导入或者包含其它的模块和嵌套包。可以呀!为什么不行

    __init__.py 中还有一个重要的变量,叫做__all__。

    __init__.py  的作用>>>

    1. Python中package的标识,不能删除

    2. 定义__all__用来模糊导入,包下的模块 e.g.   __all__ = ["Pack1Class","Pack1Class1"]

    3. 编写Python代码(不建议在__init__中写python模块,可以在包中在创建另外的模块来写,尽量保证__init__.py简单)

    import  和  From  .. import ..的本质区别

    使用import导入模块时,要做以下三件事:

    1.为源代码文件中定义的对象创建一个名字空间,通过这个名字空间可以访问到模块中定义的函数及变量。(为spam对象创建类似 dir(model))

      命名空间的概念:http://www.cnblogs.com/windlaughing/archive/2013/05/26/3100362.html
    2.在新创建的名字空间里执行源代码文件.
    3.创建一个名为源代码文件的对象,该对象引用模块的名字空间,这样就可以通过这个对象访问模块中的函数及变量

    1. import spam           # 导入并运行模块 spam  
    2. print (spam.a)          # 访问模块 spam 的属性  
    3. spam.foo()  
    4. c = spam.bar()  

    模块导入时可以使用 as 关键字来改变模块的引用对象名字:

    1. import spam as sp      改变spam模块的引用对象名字  
    2. print (sp.a)        
    3. sp.foo()  
    4. c = sp.bar()  
  • 相关阅读:
    小内存 linux 主机部署 mysql
    IIS enable HTTP PUT and DELETE
    使用Topshelf部署.net core windows服务 Demo
    Windows Template Studio 创建 .net core wpf应用
    vue笔记——vue生命周期
    (转)idea如何快速查看接口的实现类
    vue项目设置启动自动打开浏览器
    批量添加题目功能(正则表达式的使用案例)
    markdown的diff效果
    SVN提交时取消某个文件的提交
  • 原文地址:https://www.cnblogs.com/revo/p/7216658.html
Copyright © 2011-2022 走看看