python的import机制-向网上翻天盖地的复制错误文说不

前言

近日,需要用python做个演示用的demo,但是项目的文件夹目录起码有3层,在子模块调用父亲模块时候卡住了,遇到了,问题,在网上找了很多文章–不是你抄我就是我抄你,很多时候只是给出代码似乎没有任何验证。而且不等用。也是6.于是这篇文章就是要彻底解决python的import问题,让你想怎么import就怎么import,而且还要给出相关验证。

网上部分参考资料

略。。。因为从中找不到解决方案,还是自己来解决一下算了。有几篇比较有意思。

实验1

顶层调用同级别模块和子目录模块

这个怎么想都觉得可以正常调用的。

看看目录结构及各个模块的内容
这里写图片描述

test_main.py

# -*- coding: utf-8 -*-
"""

作者: root 
日期: 9/13/16.


"""


##场景1,分别调同级别及低级别子目录的函数,看看能不能正常运行。

from top_class import top_function
top_function()
from folder1.folder1_classA import f1_cA
f1_cA()

top_class.py

# -*- coding: utf-8 -*-
"""

作者: root 
日期: 9/13/16.


"""
def top_function():
    print "top function 规则调用."

folder1_classA.py

# -*- coding: utf-8 -*-
"""

作者: root 
日期: 9/13/16.


"""
def f1_cA():
    print "文件夹%s 类%s 规则调用."%("1","A")

folder1_classB.py

这里写代码片# -*- coding: utf-8 -*-
"""

作者: root 
日期: 9/13/16.


"""
def f1_cB():
    print "文件夹%s 类%s 规则调用."%("1","B")

folder2_classA.py

# -*- coding: utf-8 -*-
"""

作者: root 
日期: 9/13/16.


"""
def f2_cA():
    print "文件夹%s 类%s 规则调用."%("2","A")

folder2_classB.py

# -*- coding: utf-8 -*-
"""

作者: root 
日期: 9/13/16.


"""
def f2_cB():
    print "文件夹%s 类%s 规则调用."%("2","B")

首先第一个实验很简单,就是运行一下test_main.py看看能不能调用同级别和子目录模块。

python test_main.py

结果为:

这里写图片描述

结论,正常

长话短说,我们还是来看看调用父目录模块还有兄弟目录模块还有同一目录模块的结果还有如何处理吧。

实验2

我们来看看调用父目录模块还有兄弟目录模块还有同一目录模块的结果还有如何处理吧

注意,在原本的目录基础上添加一个文件,分别注释几部分代码来进行四次实验

现在的目录结构:
这里写图片描述

新添加的test_folder1.py内容

# -*- coding: utf-8 -*-
"""

作者: root 
日期: 9/13/16.


"""

#\#-- A 先调用同级的folder1_classA吧。其他两部分请先注释。

from folder1_classA import f1_cA
f1_cA()


# #\#-- B 好了,我们调用顶层的top class。其他两部分请先注释。
# 
# from top_class import top_function
# top_function()
# 
# 
# #\#-- C 那么调用兄弟目录下面的模块呢?其他两部分请先注释。
# 
# from folder2.folder2_classA import f2_cA
# f2_cA()
# 
# #\#-- D 额外补充一个,假如用folder1.folder1_classA这种调用方式又会如何?其他两部分请先注释。
# 
# from folder1.folder1_classA import f1_cA
# f1_cA()

为什么两个#号之间要加反斜杠呢?因为markdown语法两个#号就是标题啊。。加个斜杠转义一下。
分别注释其他部分执行a、b、c、d四个部分代码,得到的结果分别是:
这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

结论:连简单的import机制都做得那么差,即使是java也比他好很多。。。至少不会因为位置不同而导致导入失败。

好了,不吐槽这个了,这个应该是因为:

总结、看看Python的包搜索路径
Python会在以下路径中搜索它想要寻找的模块:
1. 程序所在的文件夹
2. 标准库的安装路径
3. 操作系统环境变量PYTHONPATH所包含的路径

实验3以及实验4

实验2说明了必须要在安装路径或者系统变量包含路径下面有才能找到,于是,这就是一条思路啊,我们在网上可以找到这种文章,很多见得:
import sys sys.path.append(…)

里面提到了:

模块搜索路径:

当我们试图加载一个模块时,Python会在指定的路径下搜索对应的.py文件,如果找不到,就会报错
默认情况下,Python解释器会搜索当前目录、所有已安装的内置模块和第三方模块,搜索路径存放在sys模块的path变量中:

剩下的你们自己看。
于是我们有了思路,添加一个文件,然后再写一段代码,然后在不同路径下面执行看看行不行:
现在的文件结构
这里写图片描述
test_path_append.py内容

# -*- coding: utf-8 -*-



import sys
sys.path.append("..")
from folder2.folder2_classA import f2_cA
f2_cA()

分别在两个路径下面执行结果:
这里写图片描述

好了,我们在两个不同路径之下执行会有不同的结果,其中一个是正确的。所以,我们已经离答案很近了。两个不同实验之间只有相对路径不同。。。。那么,假如我们换成绝对路径呢?好了,下面查查python的获取路径的api,然后看看有哪些异同–时间关系,我已经写好代码了,看看新的结构
这里写图片描述

test_get_path.py内容

# -*- coding: utf-8 -*-
import os
import sys
ABSPATH=os.path.abspath(sys.argv[0])
ABSPATH=os.path.dirname(ABSPATH)+"/"
print "当前文件的路径是:"
print ABSPATH
print "当前__file__变量为:"
print __file__

分别在两个目录下面运行:

这里写图片描述

好了,直接说结论吧,我们获取到的绝对路径是一定的,那么只要我们在不同层次按照绝对路径反推项目根目录然后将项目根目录路径设定进我们的path里面,那么就绝对可以正常导入各种模块了。

实验5 及解决方案

实验5就是解决方案了,只是个人的解决方案,我个人感觉没问题的

现在的项目结构:
这里写图片描述

test_solution.py

# -*- coding: utf-8 -*-


import os
import sys
#----这一步是关键点,这一步是计算当文件所在根目录并且设定便利的path的,需要注意的是:
#----后面的相对路径../是根据当前文件所在目录相对根目录的层次而定的,是根目录的子目录,那么就填
#----../假如是根目录下面的,那么就为空字符从,假如是根目录下面的第二层,那么就填../../
#----请明确这一点,然后其他导入规则就跟根目录的导入规则一样了。
sys.path.append(os.path.dirname(os.path.abspath(__file__))+"/"+"../")

from folder2.folder2_classA import f2_cA
f2_cA()
from top_class import top_function
top_function()

结果

这里写图片描述

结语

一个小小的模块import问题都要查那么多资料也是醉了,更让人无语的是,网上的文章很多时候都是抄,而且解决方案也是一句话带过,也是让人不爽。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值