从 JSON 文档导入 Python 模块
项目描述
帕克
Paker 是用于从字典和 JSON 格式的文档中导入 Python 包/模块的模块。它的灵感来自httpimporter。
重要提示:由于 v0.6.0支持直接从内存paker导入.pyd和模块。.dll这是通过使用_memimporterpy2exe项目实现的。在 Linux 上导入.so文件仍然需要将它们写入磁盘。
安装
来自 PyPI
pip install paker -U
从源头
git clone https://github.com/desty2k/paker.git
cd paker
pip install .
用法
让我们使用以下目录结构paker转储模块:print_lib
print_lib/
├── __init__.py
├── capitalize.py
└── decapitalize.py
capitalized.py包含Print函数和decapitalized.py包含pRINT函数。__init__.py文件为空。
转储到 JSON
要将库转储到文件使用paker dump命令:
paker dump print_lib --indent 4
Paker 将print_lib.json在当前目录中创建新文件。
{
"print_lib": {
"type": "package",
"extension": "py",
"code": "",
"modules": {
"capitalize": {
"type": "module",
"extension": "py",
"code": "def Print(text: str, *args, **kwargs):\n print(text.capitalize(), *args, **kwargs)\n"
},
"decapitalize": {
"type": "module",
"extension": "py",
"code": "def pRINT(text: str, *args, **kwargs):\n print(text[0].lower() + text[1:].upper(), *args, **kwargs)\n"
}
}
}
}
列出模块
要列出 JSON 使用paker list命令中的所有模块:
paker list print_lib.json
输出:
P print_lib
M print_lib.capitalize
M print_lib.decapitalize
从 JSON 重新创建包
要从 JSON 使用paker load命令重新创建包。
paker load print_lib.json
print_lib包将在当前目录中创建。设置自定义输出路径使用--output选项。
从导入.json
注意:从原始源代码导入比从 JSON 导入具有更高的优先级。请记住在使用paker.
import paker
import logging
logging.basicConfig(level=logging.NOTSET)
if __name__ == '__main__':
with open("print_lib.json", "r") as f:
with paker.load(f) as loader:
# print_lib will be available only in this context
from print_lib.capitalize import Print
from print_lib.decapitalize import pRINT
Print("hello world!")
pRINT("hello world!")
此脚本产生以下输出:
DEBUG:jsonimporter:searching for print_lib
INFO:jsonimporter:print_lib has been imported successfully
DEBUG:jsonimporter:searching for print_lib.capitalize
INFO:jsonimporter:print_lib.capitalize has been imported successfully
DEBUG:jsonimporter:searching for print_lib.decapitalize
INFO:jsonimporter:print_lib.decapitalize has been imported successfully
Hello world!
hELLO WORLD!
INFO:jsonimporter:unloaded all modules
从内存导入
您还可以直接从内存中导入 Python 模块。库不仅可以从 Python 对象加载,dict还可以从str和对象加载。bytesbytearray
import paker
import logging
# paker.loads accepts dict, str, bytes and bytearray objects
POW = {"pow": {"type": "module", "extension": "py", "code": "pow = lambda x, y: x**y"}}
SQR = '{"sqr": {"type": "module", "extension": "py", "code": "from pow import pow\\nsqr = lambda x: pow(x, 2)"}}'
TRI = b'{"tri": {"type": "module", "extension": "py", "code": "from pow import pow\\ntri = lambda x: pow(x, 3)"}}'
logging.basicConfig(level=logging.NOTSET)
if __name__ == '__main__':
# you can use nested loaders
with paker.loads(POW) as pow_loader:
# pow will be available only in this context
with paker.loads(SQR) as sqr_loader:
# sqr will be available only in this context
from sqr import sqr
assert sqr(2), 4
assert sqr(5), 25
print("6**2 is {}".format(sqr(6)))
with paker.loads(TRI) as tri_loader:
# tri will be available only in this context
from tri import tri
assert tri(2), 8
assert tri(5), 125
print("6**3 is {}".format(tri(6)))
print("It works!")
此脚本产生以下输出:
DEBUG:jsonimporter:searching for sqr
INFO:jsonimporter:sqr has been added successfully
DEBUG:jsonimporter:searching for sqr
DEBUG:jsonimporter:searching for pow
INFO:jsonimporter:pow has been imported successfully
INFO:jsonimporter:sqr has been imported successfully
6**2 is 36
INFO:jsonimporter:sqr has been unloaded successfully
DEBUG:jsonimporter:searching for tri
INFO:jsonimporter:tri has been added successfully
DEBUG:jsonimporter:searching for tri
INFO:jsonimporter:tri has been imported successfully
6**3 is 216
INFO:jsonimporter:tri has been unloaded successfully
It works!
INFO:jsonimporter:unloaded all modules
这个怎么运作
当导入模块或包时,Python 会遍历导入器并在每个对象上sys.meta_path调用方法。find_module如果importer返回自己,则表示模块可以被导入,None表示importer没有找到搜索到的包。如果任何导入器已确认能够导入模块,Python 会在其上执行另一种方法 - load_module. Paker 实现了自己的导入jsonimporter器,它不是在目录中搜索模块,而是在 Python 字典中查找它们
为了将模块或包转储到 JSON 文档,Paker 递归地迭代模块并使用每个模块和子模块的代码和类型创建字典(如果对象是包)。