python import上层模块

前言:

在python中其实import上层模块是不正规的写法,但是偶尔测试会用到。虽然我不提倡,但是说一下吧。而且这方法还有个很实用的地方哦!希望大家能看到最后。

网上有些教程说 from .. import xxx 就能引入上层,亲测报错,大家不用试了,本文也有测试哦

还有些教程说 “把要import的包放到python的安装目录下(类似c:/python27)就能直接import”。这可以实现的,但问题是,系统自带的和你自定义的混在一起,以后要修改很容易会改错系统文件,如果命名不好(例如,用一些什么requests.py之类的命名)有可能import会有未知错误。简单说,混乱

我不断查阅资料和专研后,想到一个神句

#-*-coding:utf-8-*-
import sys
sys.path.append('../')

实例:

1、基础

这是我的文件目录树,__init__.py是必须的,要告诉python这目录是一个模块,里面可以什么都没有。

 

 

 

 

 

 

 

#a.py
def show_a():
    print('Hi,I import a!')
#/level1/b.py
def show_b():
    print('Hi,i import b!')
#\level1\level2\c.by
def show_c():
    print('Hi,I import c!')
#\level1\level2\level3\d.by
def show_d():
    print('Hi,I import d!')

main.py是主函数。我们运行它来测试。先来简单温习下基础吧。引用同级目录和子目录的方法

#-*-coding:utf-8-*-
#同级目录
from b import show_b
#下级目录
from level2.c import show_c
#下下级目录
from level2.level3.d import show_d

def tx():
    #show_a()
    show_b()
    show_c()
    show_d()
    
if __name__ == '__main__':
    tx()

输出结果是:

Hi,i import b!
Hi,I import c!
Hi,I import d!

2、上级目录

好了我们想import上级目录的show_a。

2-1 假方法

大家可以试试网上说的from ..a import show_a【这是错的!不想看就直接跳到2-2吧。】

#-*-coding:utf-8-*-
#同级目录
from b import show_b
#下级目录
from level2.c import show_c
#下下级目录
from level2.level3.d import show_d

from ..a import show_a

def tx():
    show_a()
    show_b()
    show_c()
    show_d()
    
if __name__ == '__main__':
    tx()

会在 from ..a import show_a报错:

builtins.ValueError: attempted relative import beyond top-level package

那是因为编译器把我们的运行目录作为 根节点 了。加载模块的时候只加载了系统模块(例如c:\python27)和 目录下__init__ 文件夹的模块

2-2 真方法

研究出来的真方法是——在文件头加入

import sys
sys.path.append('../')

然后直接from xxx import xxx就好。例如我们的:

#-*-coding:utf-8-*-
import sys
sys.path.append('../')
#上级目录
from a import show_a
#同级目录
from b import show_b
#下级目录
from level2.c import show_c
#下下级目录
from level2.level3.d import show_d

#from ..a import show_a

def tx():
    show_a()
    show_b()
    show_c()
    show_d()
    
if __name__ == '__main__':
    tx()

运行结果是:

Hi,I import a!
Hi,i import b!
Hi,I import c!
Hi,I import d!
往下说之前先解答下大家问题吧。

1、有人会问“你这不是改了运行路径了吗?我是要在level2下面运行啊!怎么跑到上层了?

答:其实sys.path是搜索模块的路径。默认由系统模块、本目录下有__init__文件夹模块组成。新加的“神句”是“添加上层目录作为本程序模块之一”的意思。注意这是临时的,其他程序运行并不能使用这模块。

2、“为什么是from a而不是from ..a?不是在上级目录吗?

答:对,是在上层目录,但是上层目录已经作为类似系统模块的存在了。所以就像大家平时用的from datetime import datetime一样调用就可以了。

3*、最优化

以上方法就足够测试用了。但是,热爱测试的小伙伴们一定会发现这有个BUG。在main.py所在的文件夹运行main.py是正常的。但是在其他目录直接用python运行main.py会发现from a import show_a会提示“找不到模块a”

例如我的这测试文件夹是桌面的tree。我直接打开cmd输入

C:\Users\Administrator\Desktop>python C:\Users\Administrator\Desktop\tree\level1\main.py

就会报错。

为什么呢?

因为我们添加的是(当前目录的)上级目录 到path里面。直接运行就变成了添加的是C:\Users\Administrator进去了。

因此,我们需要添加(运行目录的)上级目录到path里面,即添加的应该是相对的绝对路径。有点难懂对吧?意思就是“添加的是绝对路径,但必须根据实际运行路径添加”。

最后贴上 真·神句!!!(笑)并测试。

感谢那些看到最后的小伙伴转载记得标明出处哦。
import sys,os
sys.path.append(os.getcwd()+'/../')

 

 

实测:

#-*-coding:utf-8-*-
import sys,os
sys.path.append(os.getcwd()+'/../')
#上级目录
from a import show_a
#同级目录
from b import show_b
#下级目录
from level2.c import show_c
#下下级目录
from level2.level3.d import show_d

def tx():
    show_a()
    show_b()
    show_c()
    show_d()
    
if __name__ == '__main__':
    tx()

直接cmd运行结果是:

C:\Users\Administrator>python C:\Users\Administrator\Desktop\tree\level1\main.py

Hi,I import a!
Hi,i import b!
Hi,I import c!
Hi,I import d!

 

附上测试代码:

GIT : https://gitee.com/kid0/tree.git

百度云 : https://pan.baidu.com/s/1zaS0jjYzjD0X3ZOmPafRsg

————————————————————————————————

附录

2018年7月11日

之前代码原本是\\的,现在修正为/。

import sys
sys.path.append(sys.path[0]+'\\..\\')

这是因为‘\\’(即\)在linux的路径下无法被识别。

在windows下,C:\ 或 C:/ 都能轻松访问到C盘。

在linux下, cd \root 是无法访问root文件夹的,只有 cd /root 才可以。

这是因为windows对路径的解释会把\自动转换成/,而linux不转换。

2018年7月17日

再更新一个版本。

之前神句是:

import sys
sys.path.append(sys.path[0]+'/../')

现在改成:

import sys,os
sys.path.append(os.getcwd()+'/../')

直接运行结果没差异的。但是在打包成exe文件后,这就不同了sys.path[0]会成了打包好库的路径,os.getcwd()才是运行路径(也就是exe的所在路径)。如何打包成exe文件以后博客说。现在为了严谨,还是修正下。不然打包好的exe会报错

[WinError 3] 系统找不到指定的路径。: 'C:\\Users\\ADMINI~1\\AppData\\Local\\Temp\
\_MEI37602\\base_library.zip\\a'

 

转载于:https://my.oschina.net/jacky326/blog/1839509

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值