番外:跨目录导入模块

Posted jevious

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了番外:跨目录导入模块相关的知识,希望对你有一定的参考价值。

进击のpython


包&跨模块代码调用


  • 包(Package)

    当你的模块文件越来越多,就需要对模块文件进行划分,比如把负责跟数据库交互的都放一个文件夹,把与页面交互相关的放一个文件夹,

    my_proj/
    ├── apeland_web  #代码目录
    │   ├── __init__.py
    │   ├── admin.py
    │   ├── apps.py
    │   ├── models.py
    │   ├── tests.py
    │   └── views.py
    ├── manage.py
    └── my_proj    #配置文件目录
        ├── __init__.py
        ├── settings.py
        ├── urls.py
        └── wsgi.py

    像上面这样,一个文件夹管理多个模块文件,这个文件夹就被称为包

    一个包就是一个文件夹,但该文件夹下必须存在 __init__.py文件, 该文件的内容可以为空, __init__.py用于标识当前文件夹是一个包。

    这个 __init__.py的文件主要是用来对包进行一些初始化的,当当前这个package被别的程序调用时 __init__.py文件会先执行,一般为空, 一些你希望只要package被调用就立刻执行的代码可以放在 __init__.py里,一会后面会演示。


  • 跨模块导入

    目录结构如下

    my_proj
    ├── apeland_web
    │   ├── __init__.py
    │   ├── admin.py
    │   ├── apps.py
    │   ├── models.py
    │   ├── tests.py
    │   └── views.py
    ├── manage.py
    └── my_proj
        ├── settings.py
        ├── urls.py
        └── wsgi.py

    根据上面的结构,我怎么样可以在apeland_web/views.py里导入my_proj/settings.py模块呢?

    直接导入????

    技术图片

    是会报错的,因为这两个模块,不在同一路径,所以找不到这个settings模块

    my_proj/settings.py 相当于是apeland_web/views.py的父亲(apeland_web)的兄弟(my_proj)的儿子(settings.py),settings.py算是views.py的表弟啦

    在views.py里只能导入同级别兄弟模块代码,或者子级别包里的模块,根本不知道表弟表哥的存在。这可怎么办呢?

    添加环境变量,把父亲级的路径添加到sys.path中,就可以了,这样导入就相当于从父亲级开始找模块了。

    技术图片

    (标红是因为解释器的问题,不用管!强迫症去死!)

    那么问题来了!

    这是我的电脑,这是我的文件存放路径

    那到你电脑上,还是D盘????那不一定吧

    那怎么才能自动配置呢???

    还记得我们的os模块吗?

    是不是说用哪个记哪个?

    现在开始了奥!

    技术图片

    这个方法,可以获取当前文件的相对路径

    但是为什么打印的是绝对路径呢?

    这是因为pycharm是从底层开始调用的,所以没有打印相对路径

    正常是相对路径:my_proj1/apeland_web/views.py

    然后我们只想要前面的my_proj1

    怎么做呢??????????

    利用os模块

    import sys
    import os
    
    # base = "D:/xiangmu/my_proj1"
    
    # sys.path.append(base)
    
    # from my_proj import settings
    
    s = __file__
    # my_proj1/apeland_web/views.py
    
    print(os.path.dirname(s))
    # my_proj1/apeland_web

    去掉了一层!但是我只想要my_proj1,怎么办??

    再来一遍呗!

    import sys
    import os
    
    # base = "D:/xiangmu/my_proj1"
    
    # sys.path.append(base)
    
    # from my_proj import settings
    
    s = __file__
    # my_proj1/apeland_web/views.py
    
    print(os.path.dirname(s))
    # my_proj1/apeland_web
    print(os.path.dirname(os.path.dirname(s)))
    # my_proj1

    目的达到了吧!那我们怎么把它变成绝对路径呢???

    import sys
    import os
    
    base = r"D:\\xiangmu\\my_proj1"
    
    sys.path.append(base)
    
    from my_proj import settings
    
    s = __file__
    # my_proj1/apeland_web/views.py
    
    print(os.path.dirname(s))
    # my_proj1/apeland_web
    print(os.path.dirname(os.path.dirname(s)))
    # my_proj1
    print(os.path.abspath(os.path.dirname(os.path.dirname(s))))
    # D:\\xiangmu\\my_proj1

    这样,因为你用的是动态的路径拼接,所以,即使放到你的电脑上

    这段程序也是能够使用的!


  • 官方推荐的跨目录导入方法

    虽然通过添加环境变量的方式可以实现跨模块导入

    但是官方不推荐这么干

    因为这样就需要在每个目录下的每个程序里都写一遍添加环境变量的代码

    官方推荐的玩法是,在项目里创建个入口程序,整个程序调用的开始应该是从入口程序发起,这个入口程序一般放在项目的顶级目录

    这样做的好处是,项目中的二级目录 apeland_web/views.py中再调用他表亲my_proj/settings.py时就不用再添加环境变量了

    原因是由于manage.py在顶层,manage.py启动时项目的环境变量路径就会自动变成….xxx/my_proj/这一级别

    技术图片

    这样,就十分的简单啦!

    主要就是因为当你程序执行的时候

    就默认以你程序执行文件的位置作为起点

    所以才可以这么玩!


*这个很重要*
*必须仔细瞧*

以上是关于番外:跨目录导入模块的主要内容,如果未能解决你的问题,请参考以下文章

导入模块方式(尽量少用from xx import *)以及包的定义,跨目录运行包和模块(未完)

Python全栈之路----常用模块----包及跨模块导入

包及跨模块导入

跨模块和全局变量的 Python 导入

我可以跨同一个 python 包的模块重用导入吗?

第二模块:函数编程 常用模块