关于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 RossumPEP 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/

时间: 2024-10-14 13:56:26

关于Python Package下的Module import方式[转]的相关文章

python package 的两种组织方式

方式一/package1/ .../__init__.py # 空文件 .../class1.py class Class1: def __init__(self): self.name = "class one" def printInfo(self): print("i am class One!") .../class2.py class Class2: def __init__(self): self.name = "class two"

python学习笔记之module &amp;&amp; package

个人总结: import module,module就是文件名,导入那个python文件 import package,package就是一个文件夹,导入的文件夹下有一个__init__.py的文件, __init__.py可以有两种形式, 一种是直接import多个模块,例如 import fibo import abc 另外一种是 __all__ = ["A","B"] python学习笔记之module && package python的mo

Ubuntu中python环境下import requests错误的解决(学习过程问题记录)

python中导入模块:import requests提示错误,错误信息描述如下: >>>import requests Traceback (most recent last):   File "<stdin>", line 1, in <module> ImportError:No module named requests 意思就是说没有名为requests的模块,解决方案是在命令行下使用 pip install requests 来进行

python中from module import * 的一个陷阱

from module import *把module中的成员全部导到了当前的global namespace,访问起来就比较方便了.当然,python style一般不建议这么做,因为可能引起name conflict. 但还有另外一个问题 - 你以为你修改了某个变量,其实,被from module import *后的那个并没有被更新,非常危险,因为程序有可能还可以正常运行, 只不过结果错了,到了production才被发现就比较惨了. 举个例子: 你定义了一些变量在base模块中: # r

python中的字符串编码问题——3.各操作系统下的不同编码方式

各操作系统下的不同编码方式  先看一下 linux,python2.7 >>> B = b'\xc3\x84\xc3\xa8' >>> B.decode('utf-8') u'\xc4\xe8' >>> type(B) <type 'str'> >>>   windows,python2.7,python shell >>> B = b'\xc3\x84\xc3\xa8' >>> B.d

Python遇到ModuleNotFoundError: No module named &#39;email.mime&#39;; &#39;email&#39; is not a package问题的处理办法

Python遇到ModuleNotFoundError: No module named 'email.mime'; 'email' is not a package问题的处理办法 一般有以下3个可能: 一是没有导入包 二是当前文件命名和包名冲突 三是和当前文件同一路径下其他文件命名与包名冲突 Python遇到ModuleNotFoundError: No module named 'email.mime'; 'email' is not a package问题的处理办法 原文地址:https:

python 目录下的__init__.py

1 一个目录要成为一个package必须有__init__.py文件 The __init__.py files are required to make Python treat the directories as containing packages; this is done to prevent directories with a common name, such as string, from unintentionally hiding valid modules that

Python package钓鱼

Python package钓鱼 一.概述 在收录该文之后,知道创宇404安全实验室对该文中所提到的攻击方式进行跟进.整理分析原作者公布的钓鱼数据.值得一提的是,在跟进的过程中,我们发现了新的钓鱼行为. 相比于传统的钓鱼方式,上传恶意 Python 包,不通过邮件.网页等方式传播,用户很难有相关的防护意识.与此同时,由于 Pypi 源的全球性和 Python 语言的跨平台性,相关的恶意包可以在世界各国的任意操作系统上被执行.由于执行恶意包的多数是互联网从业人员,通过恶意的 Python 包钓鱼也

PyCharm中Dictionary与Python package的区别

Dictionary Dictionary在pycharm中就是一个文件夹,放置资源文件,对应于在进行JavaWeb开发时用于放置css/js文件的目录,或者说在进行物体识别时,用来存储背景图像的文件夹.该文件夹其中并不包含_ _ init.py_ _文件 Python package 对于Python package 文件夹而言,与Dictionary不同之处在于其会自动创建_ _ init.py_ _文件. 简单的说,python package就是一个目录,其中包括一组模块和一个_ _ i