文件结构如下

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. 【Java】Java_10 常量与变量

    1.变量(variable) 1.1 我们通过变量来操纵存储空间中的数据,变量就是指代这个存储空间!空间位置是确定的,但是里面放置什么值不确定! 1.2 Java是一种强类型语言,每个变量都必须声明其 ...

  2. jquery ui dialog 中使用select2 导致select2的input失去焦点的解决方法

    在jqueryUI 的dialog中使用select2,select2的input search无论怎样都获取不到焦点? 解决方法: $(document).ready(function () { $ ...

  3. 在Window系统中使用Redis缓存策略

    Redis是一个用的比较广泛的Key/Value的内存数据库,新浪微博.Github.StackOverflow 等大型应用中都用其作为缓存,Redis的官网为http://redis.io/. 最近 ...

  4. asp.net mvc 重定向

    protected override void OnActionExecuting(ActionExecutingContext filterContext) { if (Request.Cookie ...

  5. Subversion和TortoiseSVN安装与配置(转)

    Subversion为版本控制软件的服务器端. TortoiseSVN为版本控制软件的客户端. 1.下载Subversion与TortoiseSVN. Subversion的地址:http://sub ...

  6. 2. Add Two Numbers【medium】

    2. Add Two Numbers[medium] You are given two non-empty linked lists representing two non-negative in ...

  7. linu保持远程会话

    django的server启动后,若关闭ssh会就会自动切断进程,结汇对话 命令scree会保持这个会话,在关闭ssh后,仍然能访问 shell下 1screen 进入后 2启动server 关闭ss ...

  8. Android 之布局

    1.RelativeLayout相对布局 a).第一类:属性值为true或false android:layout_centerHrizontal 水平居中 android:layout_center ...

  9. 个人博客开发之 ueditor 安装

  10. Mybatis结果生成键值对

    在实际应用中我们经常会遇到这样的情况,需要给下拉框赋值,这个时候就需要键值对了,具体使用方法如下 1,在maper.xml文件中定义结果类型(resultType)定义为hashmap,如下所示 &l ...