python的相对引入和绝对引入
来源:互联网 发布:linux shell expect 编辑:程序博客网 时间:2024/06/05 13:30
python的模块导入方式
import moudle:隐式相对导入,implicit relative import,从本package中寻找同名moudle。
form . import moudle:显式相对导入,explicit relative import,从指定的package中寻找同名moudle。
from package import moudle:绝对导入,absolute import,从sys.path中寻找同名moudle。
from __feature__ import absolute_import:py3之前版本声明绝对导入,实质是禁用隐式相对导入(隐式相对导入看作是绝对导入)。
文件目录结构
TestPackage1/
|----------------run.py
|----------------Package1/
|----------------------------__init__.py
|----------------------------Moudle1P1.py
|----------------------------Moudle2P1.py
|----------------------------run_P1.py
|----------------------------Package2/
|----------------------------------------__init__.py
|----------------------------------------Moudle1P2.py
|----------------------------------------Moudle2P2.py
|----------------------------------------Moudle3P2.py
|----------------------------Package3/
|----------------------------------------__init__.py
|----------------------------------------Moudle1P3.py
|----------------------------------------Moudle2P3.py
|----------------------------------------test.py
通过上面的某结构可以看到,Package1/Package2/Package3是三个包,TestPackage不是包。
test.py各个模块的代码
1 #coding=utf-8 2 #from __future__ import absolute_import 3 print ("__file__: %s" %__file__) 4 print ("__package__: %s" %__package__) 5 print ("__name__: %s" %__name__) 6 import sys 7 #del sys.path[0] 8 #sys.path.insert(0,'/mnt/disk2/zhaobin/TestPackage/Package1/Package3') 9 #sys.path.append('/mnt/disk2/zhaobin/TestPackage/Package1/Package3') 10 print ("sys.path: %s" %sys.path) 11 #from .. import Package2 12 #from . import Moudle2 13 #from ..Package2 import Moudle2P2 14 import Moudle2P3 15 #from Package3 import Moudle2P3 16 #print (Moudle2.__file__) 17 #from ..Package2 import test 18 def main(): 19 pass
runP1.py
1 #import Package3.test 2 #import Package3.test 3 from Package3 import test 4 5 if __name__=="__main__": 6 test.main()MoudlexPy
1 print ("i am Packagey moudlex")
实验中python版本为python27;python3版本为python33。关于相对引入和绝对引入的几组实验
执行python test.py的输出为:
__file__: test.py__package__: None__name__: __main__sys.path: ['/mnt/disk2/zhaobin/TestPackage/Package1/Package3', '/mnt/disk2/anaconda/lib/python27.zip', '/mnt/disk2/anaconda/lib/python2.7', '/mnt/disk2/anaconda/lib/python2.7/plat-linux2', '/mnt/disk2/anaconda/lib/python2.7/lib-tk', '/mnt/disk2/anaconda/lib/python2.7/lib-old', '/mnt/disk2/anaconda/lib/python2.7/lib-dynload', '/mnt/disk2/anaconda/lib/python2.7/site-packages', '/mnt/disk2/anaconda/lib/python2.7/site-packages/PIL', '/mnt/disk2/anaconda/lib/python2.7/site-packages/Sphinx-1.2.3-py2.7.egg', '/mnt/disk2/anaconda/lib/python2.7/site-packages/runipy-0.1.1-py2.7.egg', '/mnt/disk2/anaconda/lib/python2.7/site-packages/setuptools-5.8-py2.7.egg']i am package3 moudle2
关注输出中的以下几个方面:
__name__变量为__main__,sys.path的第一个值为脚本被执行的绝对路径,输出的最后一行为moudle2P3所在的位置。此时我们有个疑问,被引入的这个moudle2P3是绝对引入还是相对引入?只需要将sys.path列表中的第一个值去掉(也就是把test.py中的第7行注释去掉)后再运行python test.py就可以验证,如果输出的最后一行依旧是"i am package3 moudle2",则说明是相对路径引入模块,实际输出为:
__file__: test.py__package__: None__name__: __main__sys.path: ['/mnt/disk2/anaconda/lib/python27.zip', '/mnt/disk2/anaconda/lib/python2.7', '/mnt/disk2/anaconda/lib/python2.7/plat-linux2', '/mnt/disk2/anaconda/lib/python2.7/lib-tk', '/mnt/disk2/anaconda/lib/python2.7/lib-old', '/mnt/disk2/anaconda/lib/python2.7/lib-dynload', '/mnt/disk2/anaconda/lib/python2.7/site-packages', '/mnt/disk2/anaconda/lib/python2.7/site-packages/PIL', '/mnt/disk2/anaconda/lib/python2.7/site-packages/Sphinx-1.2.3-py2.7.egg', '/mnt/disk2/anaconda/lib/python2.7/site-packages/runipy-0.1.1-py2.7.egg', '/mnt/disk2/anaconda/lib/python2.7/site-packages/setuptools-5.8-py2.7.egg']i am anaconda module2可见最后一行为"i am anaconda moudle2",这是因为在目录'/mnt/disk2/anaconda/lib/python2.7'有一个Moudle2P3.py。如果把这个Moudle2P3.py删除,运行时会报错:找不到模块moudle2P3。
保持sys.path列表中第一项去掉,然后执行python runP1.py,输出为:
__file__: /mnt/disk2/zhaobin/TestPackage/Package1/Package3/test.pyc__package__: None__name__: Package3.testsys.path: ['/mnt/disk2/anaconda/lib/python27.zip', '/mnt/disk2/anaconda/lib/python2.7', '/mnt/disk2/anaconda/lib/python2.7/plat-linux2', '/mnt/disk2/anaconda/lib/python2.7/lib-tk', '/mnt/disk2/anaconda/lib/python2.7/lib-old', '/mnt/disk2/anaconda/lib/python2.7/lib-dynload', '/mnt/disk2/anaconda/lib/python2.7/site-packages', '/mnt/disk2/anaconda/lib/python2.7/site-packages/PIL', '/mnt/disk2/anaconda/lib/python2.7/site-packages/Sphinx-1.2.3-py2.7.egg', '/mnt/disk2/anaconda/lib/python2.7/site-packages/runipy-0.1.1-py2.7.egg', '/mnt/disk2/anaconda/lib/python2.7/site-packages/setuptools-5.8-py2.7.egg']i am package3 moudle2从输出中可以看到__name__的值为Package3.test,最后一行表示moudle2P3.py的位置是在Package3下面,而不是在anaconda中。为什么运行python test.py和运行python runP1.py所引用的moudle2P3不同?这是问题一。接下来看运行python3 runP1.py的输出值:
__file__: /mnt/disk2/zhaobin/TestPackage/Package1/Package3/test.py__package__: Package3__name__: Package3.testsys.path: ['/home/ndir/python3/lib/python33.zip', '/home/ndir/python3/lib/python3.3', '/home/ndir/python3/lib/python3.3/plat-linux', '/home/ndir/python3/lib/python3.3/lib-dynload', '/home/ndir/python3/lib/python3.3/site-packages']i am python3.3 moudle2可以看到,__name__值与上面的输出是相同的,而moudle2P3的位置是在~/python3/lib/python3.3中。为什么运行python runP1.py和运行python3 runP1.py所引用的moudle2P3不同?这是问题二。
下面将阐述原因所在:
先看一段话:Note that both explicit and implicit relative imports are based on the name of the current module. Since the name of the main module is always"__main__",modules intended for use as the main module of a Python application should always use absolute imports.
所谓的相对路径(显式/隐式)是相当于当前模块的路径,但是直接执行脚本会使脚本中的__name__值变成__main__而不是模块的名字,这样的话就没有层次结构,也就无从谈起相对路径了。相对引用和 if __name__ == "__main__"是不能共存的,这就说明问题一的原因。python3之前的版本虽然默认先执行相对引入,但是直接执行脚本导致相对引入无效,只能进行绝对引入,也就是从sys.path中的路径去寻找moudle(正如最开始的两个输出,moudle的位置是其在绝对路径中的位置)。如果我们运行python runP1.py时,test.py作为模块被导入到runP1.py主模块中,test.py的__name__为Package3.test。这个时候test.py中的import moudle2P3是默认先相对引入的(py3版本之前的特性),于是输出的最后一行为:i am package3 moudle2。而运行python3 runP1.py时,import moudle默认是绝对引入(py3版本的特性),于是输出的最后一行为:i am python3.3 moudle2。问题一二就都解决了。
运行代码报错
ValueError: Attempted relative import in non-package
ValueError: Attempted relative import beyond toplevel package
#import Package1.Package3.testfrom Package1.Package3 import testif __name__=="__main__": test.main()执行python run.py时,这个错误就会消失,通过输出可以看到test.py的__name__为Package1.Package3.test,通过角度二来理解就是from .. 是可以定位到Package1的。发散一下,如果test.py中改成from ... 又会报错吧。输出如下:
__file__: /mnt/disk2/zhaobin/TestPackage/Package1/Package3/test.py__package__: None__name__: Package1.Package3.testsys.path: ['/mnt/disk2/anaconda/lib/python27.zip', '/mnt/disk2/anaconda/lib/python2.7', '/mnt/disk2/anaconda/lib/python2.7/plat-linux2', '/mnt/disk2/anaconda/lib/python2.7/lib-tk', '/mnt/disk2/anaconda/lib/python2.7/lib-old', '/mnt/disk2/anaconda/lib/python2.7/lib-dynload', '/mnt/disk2/anaconda/lib/python2.7/site-packages', '/mnt/disk2/anaconda/lib/python2.7/site-packages/PIL', '/mnt/disk2/anaconda/lib/python2.7/site-packages/Sphinx-1.2.3-py2.7.egg', '/mnt/disk2/anaconda/lib/python2.7/site-packages/runipy-0.1.1-py2.7.egg', '/mnt/disk2/anaconda/lib/python2.7/site-packages/setuptools-5.8-py2.7.egg']Traceback (most recent call last): File "run.py", line 2, in <module> from Package1.Package3 import test File "/mnt/disk2/zhaobin/TestPackage/Package1/Package3/test.py", line 13, in <module> from ...Package1.Package2 import Moudle2P2ValueError: Attempted relative import beyond toplevel package
__file__: /mnt/disk2/zhaobin/TestPackage/Package1/Package3/test.py__package__: None__name__: testsys.path: ['/mnt/disk2/anaconda/lib/python27.zip', '/mnt/disk2/anaconda/lib/python2.7', '/mnt/disk2/anaconda/lib/python2.7/plat-linux2', '/mnt/disk2/anaconda/lib/python2.7/lib-tk', '/mnt/disk2/anaconda/lib/python2.7/lib-old', '/mnt/disk2/anaconda/lib/python2.7/lib-dynload', '/mnt/disk2/anaconda/lib/python2.7/site-packages', '/mnt/disk2/anaconda/lib/python2.7/site-packages/PIL', '/mnt/disk2/anaconda/lib/python2.7/site-packages/Sphinx-1.2.3-py2.7.egg', '/mnt/disk2/anaconda/lib/python2.7/site-packages/runipy-0.1.1-py2.7.egg', '/mnt/disk2/anaconda/lib/python2.7/site-packages/setuptools-5.8-py2.7.egg']Traceback (most recent call last): File "run.py", line 3, in <module> import test File "/mnt/disk2/zhaobin/TestPackage/Package1/Package3/test.py", line 12, in <module> from . import Moudle2P3ValueError: Attempted relative import in non-package
- python的相对引入和绝对引入
- python 相对路径引入包
- jsp引入js时的绝对路径和相对路径
- jsp引入js时的绝对路径和相对路径
- jsp引入js时的绝对路径和相对路径
- Python环境变量的引入
- 相对路径和绝对路径的区别以及js和css引入相对路径的区别
- 静态引入和动态引入的区别
- jsp的静态引入和动态引入
- 静态引入和动态引入的理解
- python引入
- python的package import 以及相对导入和绝对导入
- Jsp页面引入当先项目相对路径和绝对路径的方法
- 【Python】字符串的换行 和 引入其他py文件
- python新手笔记之包和模块的引入
- 包的创建和引入
- EasyUI的引入和使用
- JQuery的引入和使用
- Maven 手动添加 JAR 包到本地仓库
- 逻辑推理与判断(黑与白)
- UVA 10991 || Region(海伦公式,余弦定理,扇形面积
- Android学习笔记 - Activity篇
- 黑马程序员——Java多态、内部类、异常、包
- python的相对引入和绝对引入
- 极速双机调试VirtualKD+Windbg+vmware
- company identifier与bundle identifier
- Maven学习笔记
- Linux kernel测试初探
- FusionChart图表控件 点击事件(XML和JSON作为数据源时的分别处理方式)
- Java线程(2)--线程安全
- 由12306.cn谈谈网站性能技术
- 蓝桥-最大最小公倍数(互质) (贪心)