关于Python Package下的Module import方式[转]
2012年有一个目标我没有达成,那就是深入学习和使用Python语言。这个目标被其他学习任务和工作无情的抢占了,当然最主要的原因还是我重视不够^_^。
近期恰逢有一些Python工程的开发工作要做,就顺便略微深入地学习了一下Python:看了几本Python的英文大部头,比如《Learning Python 4th Edition》、《Python Essential Reference 4th Edition》、《Programming Python 4th Edition》、《Expert Python Programming》以及《The Python standard library by example》,看得我有些要吐了^_^。虽然之前用Python开发过buildc,但自我感觉依旧还是一个Python的绝对beginner,这 次通过这几本书的学习算是对Python有了个较为系统的了解了。
言归正传,今天要探讨的是一个有关Python Package下的Module import的问题,这是我在进行一个Python工程源码组织设计时遇到的。一般来说,我们的工程代码组织形式如下:
py-proj/
    main.py
    pkg1/
        __init__.py
        mod1.py
    pkg2/
        __init__.py
        mod2.py
    test/
        __init__.py
        testmod1.py
        testmod2.py
工程的dev需求如下:
* 执行main.py(其中import了各个pkg的module)
* 能够单独执行pkg下的某个module
* 兄弟pkg间可以相互import module
* 能够单独执行test下的某个module的test用例
* 能够一次执行test下的所有module的test用例
基于工程的这些dev需求,我们来看一下module import方式的选择。
Python自2.5版本之后支持两种package import方式:absolute import和relative import。不过Guido van Rossum在PEP 8中明确建议采用absolute import,理由是:more portable和more readable。经过试验,我个人觉得Guido van Rossum的建议是十分中肯的。relative import在不同版本间的支持语义有差别,且在理解方面显得有些复杂。《Learning Python 4th Edition》中花了将近一个小节来讲Package relative import,感觉复杂难懂。虽然relative import能解决一些问题,但感觉投入产出比不高。我们来看看package absolute import能否满足我们的所有工程dev需求。
* 执行main.py
无论当前工作目录(current working directory)是哪个目录,一旦执行main.py,Python就会自动将main.py所在的目录添加到sys.path中去,作为一个 module search path的entry。这样只要工程下的文件都采用了absolute import,Python就可以正确找到并import正确的module。
* 单独执行某pkg下的某个module
我们在dev时有这样的需求:单独执行某个正在编写的module的代码以获得一些执行结果的反馈。不过,以上面例子中的代码结构为例,如果我们进入到 pkg1目录下执行python mod1.py,一旦mod1.py引用了pkg2.mod2,你就会收到如下错误(前提是你使用了absolute import):
$ python mod1.py
Traceback (most recent call last):
  File "mod1.py", line 2, in <module>
    import pkg2.mod2
ImportError: No module named pkg2.mod2
因为Python只是将pkg1这个路径加入到module search path中了,这个路径下显然没有pkg2/mod2.py。不过我们可以通过在工程top-level路径下执行"python -m pkg1.mod1"来单独执行mod1的代码,这样absolute import依然生效,不会导致import error。
* 兄弟pkg间可以相互import module
这个与上面的执行方法类似,只要在top-level下通过python -m执行,那么无论pkg层次多深,无论有多少兄弟package,Python总是可以找到正确的module并导入。
* 单独执行test下的某个module的test用例
这有些类似于引用兄弟package的情况。我们通过在顶层路径下执行python -m test.testmod1即可达到此目的。
* 一次执行test下的所有module的test用例
较新的Python版本已经可以自动发现测试用例并执行。我们通过在top-level目录执行python -m unittest discover test即可执行test目录下所有符合unittest包约定要求的单元测试用例文件。在执行这个命令时,Python会将top-level路径以及 test路径都加入到module search path中。
终上,Absolute import可以满足所有需求。虽然有时候absolute import从代码上会看起来有些冗长(通过from … import …能有所缓解),但在语义理解的简单性和可读性上的优势让我更加倾向于这种方式。另外通常情况下我们是无需重新设置PYTHONPATH,也用不 到.pth文件,更不需在代码里修改sys.path来改变Python的module search path的。
注:以上测试均在Ubuntu 12.04 LTS Python 2.7.3版本下测试通过。
from:http://tonybai.com/2013/01/24/the-module-import-way-under-python-package/
关于Python Package下的Module import方式[转]的更多相关文章
- python - linux下 no module named pip
		
有网络的情况下,linux系统提示无法使用pip命令: 有两种解决方式: 第一种: =============================== 敲命令:python -m ensurepip 得到 ...
 - python package 的两种组织方式
		
方式一/package1/ .../__init__.py # 空文件 .../class1.py class Class1: def __init__(self): self.name = &quo ...
 - import module与from module import * 两种模块导入有何区别
		
#原创,转载请留言联系 区别1 import module 引用共享变量时,要使用module.变量名. 而from module import * 直接使用变量名即可 区别2(有点绕) import ...
 - python学习笔记之module && package
		
个人总结: import module,module就是文件名,导入那个python文件 import package,package就是一个文件夹,导入的文件夹下有一个__init__.py的文件, ...
 - ## Python中的Package和Jupyter中import包问题
		
前言 关于python包的一些知识 Java中的package概念 我们知道在java中的import package概念, java中的包就是一个目录,里面包含着子目录,子目录套着子目录,当需要引入 ...
 - Python: import vs from (module) import function(class) 的理解
		
Python: Import vs From (module) import function(class) 本文涉及的 Python 基本概念: Module Class import from . ...
 - python中from module import * 的一个陷阱
		
from module import *把module中的成员全部导到了当前的global namespace,访问起来就比较方便了.当然,python style一般不建议这么做,因为可能引起nam ...
 - Python遇到ModuleNotFoundError: No module named 'email.mime'; 'email' is not a package问题的处理办法
		
写Python的时候我们会遇到如下的错误: Traceback (most recent call last): File "F:/exploitation/codes/python/Jet ...
 - ubuntu下使用python3的有些库时,解决"raise ImportError(str(msg) + ', please install the python3-tk package') ImportError: No module named '_tkinter', please install the python3-tk package"的错误
		
问题: 在Ubuntu下使用matplotlib这个库时,运行时出现如下错误: raise ImportError(str(msg) + ', please install the python3-t ...
 
随机推荐
- How To Pronounce 3-Syllable Phrases
			
How To Pronounce 3-Syllable Phrases Share Tweet Share Tagged With: 3-Syllable Learn about the stress ...
 - Haskell语言学习笔记(60)Biapplicative
			
Biapplicative class Bifunctor p => Biapplicative p where bipure :: a -> b -> p a b (<< ...
 - Implementing On Item Click / Double Click for TListView
			
ListView.On Item Click & ListView.On Item Double Click To be able to locate the clicked (if ther ...
 - hibernate 1对1的关系
			
hibernate 中1对1的关系分为外键关联和主键关联 外键关联: //多方 public class Students { ...
 - STL容器的常用用法
			
STL: 1.vector: vector<int> v;vector<int> v(10);//定义大小为10的int型向量容器.vector<int> v(10 ...
 - 42. Trapping Rain Water (Array,stack; DP)
			
Given n non-negative integers representing an elevation map where the width of each bar is 1, comput ...
 - win 下 nginx 与 php的配置
			
1.下载需要的软件包 php的windows版本(*注意这里下载非线程安全的,nginx使用的是cgi) http://windows.php.net/download/ nginx的window ...
 - js 获取高度
			
网页可见区域宽 :document.body.clientWidth; 网页可见区域高:document.body.clientHeight; 网页可见区域高:document.body.offs ...
 - Laravel 开启跨域请求
			
项目中用到了接口,外部调用的时候老是请求不到,本地请求却没问题,查了下说是因为跨域的问题.根据网上所说解决方法如下: 1.建立中间件Cors.php命令:php artisan make:middle ...
 - Jmeter的一个jmx文件(备忘)
			
<?xml version="1.0" encoding="UTF-8"?> <jmeterTestPlan version="1. ...