一、模块
1.1、__init__.py
在每个文件夹下创建__init__.py文件,这个文件将在此包下具体的模块导入之前执行。它里面可以定义与模块相关的一些内容。比如发布:下面代码只导入spam 和 grok。如果采用from module import *则会导入所有不以下划线开头的模块。但若定义了__all__则只有被列举出的模块才会被导入,如果定义了一个空列表,则不会导入任何模块。
def spam():
pass
def grok():
pass
age = 30
# Only export 'spam' and 'grok'
__all__ = ['spam', 'grok']
重新加载,这种方式不建议在生产环境中使用。
import importlib
from chapter10 import module_split
importlib.reload(module_split)
通过字符串导入模块
req = importlib.import_module('requests')
res = req.get('http://www.python.org')
1.2、钩子函数
import importlib
import sys
from collections import defaultdict
_post_import_hooks = defaultdict(list)
class PostImportFinder:
def __init__(self):
self._skip = set()
def find_module(self, full_name, path=None):
if full_name in self._skip:
return None
self._skip.add(full_name)
return PostImportLoader(self)
class PostImportLoader:
def __init__(self, finder):
self._finder = finder
def load_module(self, full_name):
importlib.import_module(full_name)
module = sys.modules[full_name]
for func in _post_import_hooks[full_name]:
func(module)
self._finder._skip.remove(full_name)
return module
def imported_action(full_name):
def decorate(func):
if full_name in sys.modules:
func(sys.modules[full_name])
else:
_post_import_hooks[full_name].append(func)
return func
return decorate
sys.meta_path.insert(0, PostImportFinder())
('threading')
def warn_threads(mod):
print('Call Threads.')
在已存在的函数定义上添加装饰器,imported_action装饰器的作用是将导入时被激活的处理器函数进行注册。该装饰器用于检查sys.modules,以便查看模块是否已经被加载。如果是,处理器立即被调用,添加到_post_improts_hooks字典的一个列表中。一个模块可以注册多个处理器,_post_import_hooks的作用是收集所有的处理器对象。
from functools import wraps
from chapter10.modify_module import imported_action
def logged(func):
(func)
def wrapper(*args, **kwargs):
print(f'Calling {func.__name__},args: {args},kwargs: {kwargs}')
return func(*args, **kwargs)
return wrapper
('math')
def add_logging(mod):
mod.cos = logged(mod.cos)
mod.sin = logged(mod.sin)
import math
print(f'math.sin(2) = {math.sin(2)}')
二、包
2.1、常见使用
2.1.1、读取包中的数据文件
import pkgutil
data = pkgutil.get_data(__package__, 'test_data.dat') #第一个函数可以直接使用包名。
2.1.2、将文件夹加入到sys.path
这个功能类似动态添加库到path路径下。site-package目录是第三方包和模块安装的目录。如果手动安装代码,代码将被安装到site-package目录下。配置path的pth文件必须放置在site-packages里,但配置的路径可以是系统上任何希望的目录中。
import sys
print(f'sys path: {sys.path}')
import sys
sys.path.insert(0, '/test/dir')
sys.path.insert(0, '/test/dir')
import sys
from os import path
file_path = path.abspath(path.dirname(__file__))
sys.path.insert(0, path.join(file_path, 'test'))
print(f'sys path: {sys.path}')
2.2、包分发
这个功能类似java里的maven私服功能。上传模块供其它应用来dependency。
#step1:编写setup.py文件
from distutils.core import setup
setup(name='projectname',
version='1.0',
author='Your Name',
author_email='you@youraddress.com',
url='http://www.you.com/projectname',
packages=['projectname', 'projectname.utils'],
)
#setp2:创建 MANIFEST.INF文件
include *.txt
recursive-include examples *
recursive-include Doc *
#setp3:执行命令发布
python3 setup.py sdist