# 模块化概述
# sys.path
包是一种管理 Python 模块命名空间的形式,采用"点模块名称"。
- 比如一个模块的名称是 A.B, 那么他表示一个包 A中的子模块 B 。
- 就好像使用模块的时候,不用担心不同模块之间的全局变量相互影响一样,采用点模块名称这种形式也不用担心不同库之间的模块重名的情况。
搜索路径是一个解释器会先进行搜索的所有目录的列表。当解释器遇到 import 语句,如果模块在当前的搜索路径就会被导入。
搜索路径被存储在sys模块的path变量中(不是windows环境变量下的那个PATH)
- Linux和Windows下都是
PYTHONPATH环境变量 - 如果设置了
PYTHONPATH环境变量,则会覆盖掉默认搜索路径
- Linux和Windows下都是
path输出是一个列表,由一系列目录名组成,第一项是一个空串表示当前目录。
sys.path.append("..") 表示将当前程序所在位置向上提了一级
可以创建一个
.pth文件访问Python安装路径下的site-packages/sitepackages目录,这样解释器启动时会自动将其中列举出的目录加入到sys.path中# myapplication.pth /some/dir /other/dir
__init__文件是Python2的要求,Python3并不强制要求一个模块只会被导入一次,不管你执行了多少次
import,这样可以防止导入模块被一遍又一遍地执行。使用reload方法重新导入
import aaa from imp import reload reload(aaa)
import 在导入文件的时候,会自动把所有暴露在外面的代码全都执行一遍(第一次导入时)。因此,如果你要把一个东西封装成模块,又想让它可以执行的话,你必须将要执行的代码放在
if __name__ == '__main__'下面。-
__name__作为Python 的魔术内置参数,本质上是模块对象的一个属性。我们使用 import 语句时,__name就会被赋值为该模块的名字,自然就不等于__main__了。 - 巧用
if __name__== '__main__'来避开 import 时执行。
-
import sys
sys.path.append("..")
from utils.class_utils import *
encoder = Encoder()
decoder = Decoder()
print(encoder.encode('abcde'))
print(decoder.decode('edcba'))
########## 输出 ##########
edcba
abcde
# 项目模块化
相对位置会使得重构既不雅观,也易出错。因此,在大型工程中尽可能使用绝对位置是第一要义。对于一个独立的项目,所有的模块的追寻方式,最好从项目的根目录开始追溯,这叫做相对的绝对路径。
- 以项目的根目录作为最基本的目录,所有的模块调用,都要通过根目录一层层向下索引的方式来 import。
# 猴子补丁
“猴子补丁”是动态类型语言的一个特性,代码运行时在不修改源代码的前提下改变代码中的方法、属性、函数等以达到热补丁(hot patch)的效果。很多系统的安全补丁也是通过猴子补丁的方式来实现的,但实际开发中应该避免对猴子补丁的使用,以免造成代码行为不一致的问题。
Monkey-patching猴子补丁这个叫法源自于Zope框架,大家在修正Zope的Bug时经常会在程序后追加更新部分,这些被称作“杂牌军补丁(guerillapatch)”,后来guerilla逐渐写成了gorllia(猩猩),再后来就写成了monkey(猴子),所以猴子补丁的叫法就这么莫名其妙的得来了。之后在动态语言中,不改变源代码而对功能进行追加和变更就统称为“猴子补丁”。所以猴子补丁并不是Python中专有的,猴子补丁充分利用了动态语言的灵活性,可以对现有语言API进行追加、替换、修改,甚至性能优化等。
在使用gevent库的时候,我们会在代码开头的地方执行gevent.monkey.patch_all(),这行代码的作用是把标准库中的socket模块给替换掉,这样我们在使用socket的时候,不用修改任何代码就可以实现对代码的协程化,达到提升性能的目的,这就是对猴子补丁的应用。
另外,如果希望用ujson三方库替换掉标准库中的json,也可以使用猴子补丁的方式,代码如下所示。
import json, ujson
json.__name__ = 'ujson'
json.dumps = ujson.dumps
json.loads = ujson.loads
单元测试中的Mock技术也是对猴子补丁的应用,Python中的unittest.mock模块就是解决单元测试中用Mock对象替代被测对象所依赖的对象的模块。