强制某些模块不能从其他模块导入。
项目描述
进口卫士
强制某些模块不能从其他模块导入。在运行时!
如果您需要静态分析工具,请查看flake8-import-graph。
特征:
- 在运行时工作
- 检查动态导入
- 可定制的规则
这个库有一些性能开销。在某些情况下,它可能会导致导入时间(和启动时间分别)降低 1.5-2 倍。建议仅在开发过程中启用 import_guard。
安装
pip install import-guard
用法
from import_guard import guard, mod
guard.set_deny_rules({
# deny `csv` import from `test_proj` and submodules
"test_proj": "csv", # the same as mod("csv")
# deny `selenium` and top_level `test_proj.tasks` imports from test_proj.api
# but allow `test_proj.tasks` import inside the function (lazy import)
# the same as mod("selenium") | (mod("test_proj.tasks") & Flags.TopLevel)
"test_proj.api": ["selenium", mod.top_level("test_proj.tasks")],
# deny `test_proj.api` and `test_proj.business_logic` imports from `test_proj.core`
"test_proj.core": mod.matches(r"test_proj\.(api|business_logic)"),
# deny all imports except `logging` and `yaml`
"test_proj.logging": ~mod.explicit(["logging", "yaml"]),
})
# raise ForbiddenImportError
guard.enable(strict=True)
规则
下面的代码可以复制粘贴到 Python 解释器中,并假定以下导入:
from importlib import reload
from import_guard import guard, mod
# enable guard in advance
guard.enable()
完全符合
guard.set_deny_rules({"<stdin>": "decimal"})
# shortcut for mod("decimal")
from decimal import Decimal # shows warning
from enum import Enum # ok
显式匹配
考虑以下代码:
guard.set_deny_rules({"<stdin>": "re"})
import csv # shows warning!
发生了什么?
csv在后台导入一些模块,例如re或io. 我们通过模块隐式地启动了re模块的加载csv(深度 = 1 的规则匹配)。这是默认行为。您只能使用mod.explicit("re")函数检查显式导入。
guard.set_deny_rules({"<stdin>": mod.explicit("re")})
reload(csv) # allowed
import re # shows warning
匹配多个模块
guard.set_deny_rules({"<stdin>": ["logging", "json"]})
# the same as mod.any(["logging", "json'])
# the same as mod("logging") | mod("json")
import json # shows warning
from logging import getLogger # shows warning
通过正则表达式匹配
guard.set_deny_rules({"<stdin>": mod.matches("log.*")})
# shows multiple warnings
from logging.config import dictConfig
倒置
guard.set_deny_rules({"<stdin>": ~mod.matches("log.*")})
import io # shows warning
仅匹配模块级导入
通常的做法是进行本地导入而不是全局导入,以中断循环导入或推迟导入,直到您运行实际需要您正在导入的模块的代码。
# deny module-level imports
guard.set_deny_rules({"<stdin>": mod.top_level("array")})
def some_function():
import array # allowed (lazy import)
some_function()
import array # shows warning
匹配明星导入
guard.set_deny_rules({"<stdin>": mod.star("csv")})
from csv import * # shows warning
复杂的规则
规则非常灵活。您可以以不同的方式将它们组合在一起并构建非常复杂的条件。
mod.explicit(
~mod.top_level(["math", "json"])
| mod.matches("log.*")
)
很好的例子:
- 拒绝某些模块中的非延迟导入:
guard.set_deny_rules({
"test_proj.business_logic": mod.top_level(mod.matches(".*")),
})
- 拒绝在项目中开始导入:
guard.set_deny_rules({
"test_proj": mod.star(mod.explicit(mod.matches(".*"))),
})
非严格模式
# not enabled for `prod`
if env == "staging":
# warn on forbidden import
guard.enable(strict=False)
elif env == "local":
# raise ForbiddenImportError
guard.enable(strict=True)
规则层次结构
模块的拒绝规则集也会影响其子模块。
guard.set_deny_rules({
"test_proj": "json",
"test_proj.api": ["selenum", "pandas"],
"test_proj.core": "celery"
})
test_proj.core禁止json和celery进口。
test_proj.api.views禁止json, selenium,pandas进口。
懒惰模块
考虑以下项目结构:
# main.py
import api
# api.py
def view():
import tasks
# tasks.py
import pandas
这里的main.pyimportsapi是tasks惰性导入,是pandas在模块级别导入。
import_guard将这种情况作为惰性模块导入处理,并且会认为熊猫被惰性导入。因此,在这种情况下,以下规则不会发出警告:
guard.set_deny_rules({"tasks": mod.top_level("pandas")})
自定义模块匹配器
def is_relative_import(import_info, caller_info):
return import_info.level > 1
# deny relative import
guard.set_deny_rules({"proj": mod.hook(is_relative_import)})
from .api import view # shows warning
from proj.api import view # ok
测试
规则
直接测试规则:
rule = mod.top_level(mod.matches(".*"))
# True; mod1 imported at the module level in mod2
rule.test("mod1", caller="mod2")
# False; mod1 doesn't match the top_level constraint
rule.test("mod1", caller="<stdin>", top_level=False)
通过守卫测试拒绝规则:
guard.is_import_allowed("csv", caller="test_proj.api") # False
guard.is_import_allowed("logging", caller="test_proj.api") # True
guard.is_import_allowed("selenium", caller="test_proj.api") # False
guard.is_import_allowed(
"test_proj.tasks", caller="test_proj.api"
) # False
guard.is_import_allowed(
"test_proj.tasks", caller="test_proj.api", top_level=False
) # True
单元测试
使用当前的 Python 解释器进行测试:
$ python -m unittest discover tests -v
使用不同的 Python 版本和解释器进行测试:
$ tox
项目详情
关
import_guard -0.1.2-py2.py3-none-any.whl 的哈希值
| 算法 | 哈希摘要 | |
|---|---|---|
| SHA256 | c24fe73152120435d29464403d80d0cd77315b4565e07573c5cd941f91c91dda |
|
| MD5 | 9cbb1896704f70db7c500f2954f9d654 |
|
| 布莱克2-256 | 2eb24991ddb748f80f112deed86873be92db32d16092d24e88c47d60fa6d67ba |