文件结构如下

python_directory/
├── __init__.py
└── app
├── __init__.py
├── sub1
│   ├── __init__.py
│   └── mod1.py
└── sub2
├── __init__.py
├── mod2.py

除了 mod1.py,其他文件内容都为空。

mod1.py

print('__name__: {}'.format(__name__))
print('__package__: {}'.format(__package__))
from ..sub2 import mod2
print('Import Successfully!')

如果 __package__ 不为空,相对引用会根据 __package__ 而不是 __name__[2]。

Relative Import In Non-Package

如果直接执行一个模块,那么它的 __name____main__。Python 会认为这个模块是一个最顶层的模块,而不管这个模块在文件系统中的实际位置[1]。

$ pwd
/path_to/python_directory $ python app/sub1/mod1.py
__name__: __main__
__package__: None
Traceback (most recent call last):
File "app/sub1/mod1.py", line 3, in <module>
from ..sub2 import mod2
ValueError: Attempted relative import in non-package

一个最顶层的模块 -- 我理解为 Python 把这个模块复制到在一个单独的目录中然后再执行,由于该目录下只有这个一个模块,

所以它不是一个 package。

Beyond Top Level Package

$ pwd
/path_to/python_directory/app $ python -m sub1.mod1
__name__: __main__
__package__: sub1
Traceback (most recent call last):
File "/usr/local/Cellar/python/2.7.13/Frameworks/Python.framework/Versions/2.7/lib/python2.7/runpy.py", line 174, in _run_module_as_main
"__main__", fname, loader, pkg_name)
File "/usr/local/Cellar/python/2.7.13/Frameworks/Python.framework/Versions/2.7/lib/python2.7/runpy.py", line 72, in _run_code
exec code in run_globals
File "/path_to/python_directory/app/sub1/mod1.py", line 4, in <module>
from ..sub2 import mod2
ValueError: Attempted relative import beyond toplevel package

由于 -m sub1.mod1,Python 将 package 的顶层视为 sub1,而 ..sub2 位于 app/,超过了当前的最顶层 sub1,所以报错。

└── app
├── __init__.py
├── sub1
│   ├── __init__.py
│   └── mod1.py
└── sub2

正确的调用

$ pwd
/path_to/python_directory $ python -m app.sub1.mod1
__name__: __main__
__package__: app.sub1
Import Successfully!

此时 ..sub2 相当于 app.sub2

参考

  1. PEP 328 -- Imports: Multi-Line and Absolute/Relative
  2. PEP 366 -- Main module explicit relative imports

Python 模块相对引用的更多相关文章

  1. python 模块被引用多次但是里面的全局表达式总共只会执行一次

    python 模块被引用多次但是里面的全局表达式总共只会执行一次

  2. 扩展Python模块系列(四)----引用计数问题的处理

    承接上文,发现在使用Python C/C++ API扩展Python模块时,总要在各种各样的地方考虑到引用计数问题,稍不留神可能会导致扩展的模块存在内存泄漏.引用计数问题是C语言扩展Python模块最 ...

  3. python中模块的引用

    一. 模块的定义 定义 python模块(Module),是一个python文件,以.py结尾,包含了python对象定义和python语句.模块让你能够有逻辑地组织你的python代码段,把相关的代 ...

  4. Python基础篇【第5篇】: Python模块基础(一)

    模块 简介 在计算机程序的开发过程中,随着程序代码越写越多,在一个文件里代码就会越来越长,越来越不容易维护. 为了编写可维护的代码,我们把很多函数分组,分别放到不同的文件里,这样,每个文件包含的代码就 ...

  5. python模块及包的导入

    一.模块 通常模块为一个文件,直接使用import来导入就好了.可以作为module的文件类型有".py".".pyo".".pyc".&q ...

  6. Python 对象的引用计数和拷贝

    Python 对象的引用计数和拷贝 Python是一种面向对象的语言,包括变量.函数.类.模块等等一切皆对象. 在python中,每个对象有以下三个属性: 1.id,每个对象都有一个唯一的身份标识自己 ...

  7. Python模块学习

    6. Modules If you quit from the Python interpreter and enter it again, the definitions you have made ...

  8. python 模块导入

    1. 模块导入: 要使用一个模块,我们必须首先导入该模块.Python使用import语句导入一个模块.例如,导入系统自带的模块 math: import math 你可以认为math就是一个指向已导 ...

  9. python模块与包加载机制

    模块的搜索路径: When a module named spam is imported, the interpreter searches for a file named spam.py in ...

随机推荐

  1. 在Ubuntu 12.04上配置iSCSI Target服务

      今天自己按照网上搜来的教程自己在Ubuntu 12.04上配置了iSCSI Target服务,在这里简单地做个纪录.操作系统是全新安装的Ubuntu 12.04,配置一块500 GB的SATA笔记 ...

  2. 豆瓣电台笔记3:cell添加从中间向两侧放大的动画

    步骤: 1.设置动画属性的初始值 cell.layer.transform = CATransform3DMakeScale(0.1,0.1,1) 2.在指定时间内执行动画 UIView.animat ...

  3. linux入门基础——linux网络配置

    linux网络配置 以太网连接 在linux中,以太网接口被命名为:eth0.eth1等.0.1代表网卡编号 通过lspci命令能够查看网卡硬件信息(假设是usb网卡,则须要使用lsusb命令) 命令 ...

  4. javascript-ajax之json学习笔记

    ajax什么时候解析json的时候用eval 1.如果是原生js实现的ajax,就需要eval转json对象 如果使用了类似jquery的js插件,里面有些方法是不需要转的,因为jquery已经帮你处 ...

  5. 基于tornado实现web camera

    基于tornado实现web camera 近期在学习python.找了一个框架学习,我选择的是tornado.由于其不仅仅是一个web开发框架,其还是一个server,异步事件库,一举多得. 我一直 ...

  6. 获取表数据的插入SQL

    DECLARE @TABLE_NAME VARCHAR(200) SET @TABLE_NAME = 'myFunction' --表名 DECLARE @TABLE_CONDITION VARCHA ...

  7. RAD Studio XE5破解补丁及方法

    通过测试可用,RAD Studio XE5破解补丁及方法 第一步,将下载下来的“delphicbuilder_xe5_win.iso”解压到任意盘,任意目录. 第二步,将“免序列号安装授权文件”文件夹 ...

  8. Vivado 与 Modelsim 联合仿真

    1 编译库 用命令行 用vivado工具 vivado 有很多 IP核的接口 已经与 ISE的核 不太一样了,比如fir ,接口就是这样的: fir_lp fir_lp_ip(    .aclk  ( ...

  9. 557. Reverse Words in a String III【easy】

    557. Reverse Words in a String III[easy] Given a string, you need to reverse the order of characters ...

  10. C语言指针解说

    指针是C语言的一种数据类型.类似于C中的其它类型,比如int ,char 等.既然指针是一种类型,当我们定义该类型变量.该类型变量就称为指针变量. C中有了指针就有了指向. 指向:指针变量指向本身保存 ...