文件结构如下

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. C语言 | 计算器实现 version 2.

    在之前版本中使用栈结构来实现,但由于51单片机不支持malloc函数,所以使用C语言又写了一个计算器版本. 通过数组存放值和操作符模拟栈操作. 实现代码: #include <stdio.h&g ...

  2. Retrofit2和RxJava配合使用Demo

    和Retrofit2单独使用有一些区别 首先,同样写个interface,这里是GitHubService.java,我们这次要实现获取官方提供的测试接口的数据 public interface Gi ...

  3. 第四天 ThinkPHP手把手高速拼接站点(四)

    6月6日,晴天."熟梅天气豆生蛾.一见榴花感慨多. 芒种积阴凝雨润,菖蒲修剪莫蹉跎. " 九.后台编写-续-1 1.改动admin/Tpl/Login/index.html 自己改 ...

  4. MVC的设计模式在JavaWeb中的实现

    JSP开发模式 jsp开发模式的发展 1.模式1:(适合小型项目的技术的开发)     a.第一版本号,纯jsp(封装数据.处理数据,显示数据)     b.第二版本号,Jsp+JavaBean.   ...

  5. Linux Chrome Tab 标题 乱码

    1. 刚装完ubuntu 14.04 英文版, 又装了google chrome 浏览器. 2. 打开chrome浏览器,发现tab也没的标题是乱码: 3. 而系统自带的firefox却没有这个问题, ...

  6. Atitit.获得向上向下左的右的邻居的方法 软键盘的设计..

    Atitit.获得向上向下左的右的邻居的方法 软键盘的设计.. Left right可以直接使用next prev.. Up down可以使用pix 判断...获得next element的posit ...

  7. Atitit.跨语言数据库db  api兼容性 jdbc odbc ado oledb 增强方案

    Atitit.跨语言数据库db  api兼容性 jdbc odbc ado oledb 增强方案 1. 跨语言db api兼容性..1 2. 目前访问数据库的接口很多.比较常用的jdbc odbc 以 ...

  8. SDRAM驱动篇之简易SDRAM控制器的verilog代码实现

    在Kevin写的上一篇博文<SDRAM理论篇之基础知识及操作时序>中,已经把SDRAM工作的基本原理和SDRAM初始化.读.写及自动刷新操作的时序讲清楚了,在这一片博文中,Kevin来根据 ...

  9. android.app.Service-android:process=":remote"属性解说

    在学习Android Service组件的过程中碰到了一个问题,就是在Android应用的声明文件Manifest.xml中有时候会对相关的服务标签设置一个android:process=”:remo ...

  10. 没有局域网环境,全是公网IP可以做LVS吗,该如何做了!请大家赐教!

    没有局域网环境,全是公网IP可以做LVS吗,该如何做了!请大家赐教! 由 wjjava 在 周四, -- : 提交 LVS集群 现在有3台服务器,各有一个公网IP地址.IP地址形式如下: IP1:12 ...