zoukankan      html  css  js  c++  java
  • python 子包调用 跨目录调用

    1. python3中的模块和包

    简单来讲,模块是一个包含Python定义和语句的文件,包是一种通过用“带点号的模块名”来构造 Python 模块命名空间的方法。

    详细可以参考廖雪峰的:python教程-模块

    本文以以下的项目结构,对python3的子包之间的调用进行探索:

    python模块 (1)

    使用的python版本:3.7.0

    平台:win10


    2. python的模块搜索路径

    当一个名为 spam 的模块被导入的时候,解释器首先寻找具有该名称的内置模块。如果没有找到,然后解释器从 sys.path 变量给出的目录列表里寻找名为 spam.py 的文件。sys.path 初始有这些目录地址:

    • 包含输入脚本的目录(或者未指定文件时的当前目录);
    • PYTHONPATH (一个包含目录名称的列表,它和shell变量 PATH 有一样的语法);
    • 取决于安装的默认设置;


    3. 调用子包与调用兄弟包

    假如在main.py中调用pack.mod1.py中的函数func1,而func1又调用pack2.mod2.py中的func2函数,各个文件中的代码如下:

    main.py:
    import sys
    print("file:{},sys.path:{}".format(__file__, sys.path))
    from pack1 import mod1
    
    if __name__ == "__main__":
        mod1.func1()
    
    
    pack1/mod1.py:
    from pack2 import mod2
    
    def func1():
        print("this is pack1.mod1")
        mod2.func2()
    

    
    pack2/mod2.py:
    def func2():
        print("this is pack2.mod2")

    进入test_mod目录,执行命令:

    python main.py

    输出:

    file:main.py,sys.path:['D:\1-Work\python_src\test_mod', 
    'C:\Users\xxx\AppData\Local\Programs\Python\Python37\python37.zip', 'C:\Users\xxx\AppData\Local\Programs\Python\Python37\DLLs', 'C:\Users\xxx\AppData\Local\Programs\Python\Python37\lib', 
    'C:\Users\xxx\AppData\Local\Programs\Python\Python37', 'C:\Users\xxx\AppData\Roaming\Python\Python37\site-packages', 'C:\Users\xxx\AppData\Local\Programs\Python\Python37\lib\site-packages']
    this is pack1.mod1
    this is pack2.mod2

    可以看出sys.path中的第一个元素,就是main.py所在的目录,因为包pack1和pack2都在这个目录下,所以它们能够互相发现。

    假如这个时候,你想单独调试一下pack1.mod1.func1函数,将mod1.py修改如下:

    import sys
    print("file:{},sys.path:{}".format(__file__, sys.path))
    from pack2 import mod2
    
    def func1():
        print("this is pack1.mod1")
        mod2.func2()
    
    if __name__ == "__main__":
        func1()

    进入pack1目录运行:

    python mod1.py

    输出如下:

    file:mod1.py,sys.path:['D:\1-Work\python_src\test_mod\pack1', 
    'C:\Users\xxx\AppData\Local\Programs\Python\Python37\python37.zip', 'C:\Users\xxx\AppData\Local\Programs\Python\Python37\DLLs', 'C:\Users\xxx\AppData\Local\Programs\Python\Python37\lib', 'C:\Users\xxx\AppData\Local\Programs\Python\Python37', 'C:\Users\xxx\AppData\Roaming\Python\Python37\site-packages', 'C:\Users\xxx\AppData\Local\Programs\Python\Python37\lib\site-packages']
    Traceback (most recent call last):
      File "mod1.py", line 3, in <module>
        from pack2 import mod2
    ModuleNotFoundError: No module named 'pack2'

    发现sys.path的第一个路径已经是test_mod/pack1了,在这个目录下面解释器无法找到pack2这个包。

    如果需要发现这个包,按照python搜索路径的规则,需要将test_mod这个目录加入到sys.path中,一般来说可以:

    • 通过环境变量PYTHONPATH进行设置;
    • 也可以将路径写入.pth文件,Python在遍历已知的库文件目录过程中,如果见到一个.pth 文件,就会将文件中所记录的路径加入到 sys.path 中;
    • 最简单的是使用sys.path.append函数将路径加入。

    使用最后一种办法,将pack1.mod1.py修改为:

    import sys
    sys.path.append("D:\1-Work\python_src\test_mod")
    print("file:{},sys.path:{}".format(__file__, sys.path))
    from pack2 import mod2
    
    def func1():
        print("this is pack1.mod1")
        mod2.func2()
    
    if __name__ == "__main__":
        func1()

    结果输出:

    file:mod1.py,sys.path:['D:\1-Work\python_src\test_mod\pack1', 'C:\Users\xxx\AppData\Local\Programs\Python\Python37\python37.zip', 'C:\Users\xxx\AppData\Local\Programs\Python\Python37\DLLs', 'C:\Users\xxx\AppData\Local\Programs\Python\Python37\lib', 'C:\Users\xxx\AppData\Local\Programs\Python\Python37', 'C:\Users\xxx\AppData\Roaming\Python\Python37\site-packages', 'C:\Users\xxx\AppData\Local\Programs\Python\Python37\lib\site-packages', 'D:\1-Work\python_src\test_mod']

    为什么使用绝对路径呢,因为如果使用相对路径的话,当前工作路径一变就不行了,不信在test_mod目录执行

    python pack1/mod1.py

    或者用vscode等文本编辑器打开test_mod目录,然后直接F5运行,工作目录就是test_mod,而不是pack1,这个时候添加的”../”路径就会变成目录python_src。

    这也是为什么很多文章使用sys.path.append(“../”),然后很多人在留言区说在他们本地运行的时候根本不行。

    所以一切的关键还是模块搜索路径。

    回到解决方式上面,或者将项目的路径加到PYTHONPATH环境变量,或者写入.pth并放在搜索路径中才是一劳永逸的方式。


    4. 参考

    (1) python3文档-模块

    (2) 廖雪峰:python教程-模块

    (完)

  • 相关阅读:
    118/119. Pascal's Triangle/II
    160. Intersection of Two Linked Lists
    168. Excel Sheet Column Title
    167. Two Sum II
    172. Factorial Trailing Zeroes
    169. Majority Element
    189. Rotate Array
    202. Happy Number
    204. Count Primes
    MVC之Model元数据
  • 原文地址:https://www.cnblogs.com/harrymore/p/12292278.html
Copyright © 2011-2022 走看看