用python做配置文件
受zig语言启发,图灵完备的配置文件可能是个不错的选择,只要严格限制权限就行。
用importlib
目标:
- 禁止二次导入,去除import语句
- 提供模块白名单、黑名单
import ast
from sys import meta_path
from importlib.abc import Loader, MetaPathFinder
from importlib.util import spec_from_loader, find_spec
from mocap_wrapper.logger import Log
class CustomLoader(Loader):
def __init__(self, original_spec):
self.original_spec = original_spec
def create_module(self, spec):
# 使用默认模块创建逻辑
return None
def exec_module(self, module):
# 获取原始源代码
source = self.original_spec.loader.get_source(module.__name__)
if source is None:
raise ImportError(f"Can't get module {module.__name__} source code.")
# 解析为AST并删除所有import节点
tree = ast.parse(source)
transformer = ImportRemover()
modified_tree = transformer.visit(tree)
ast.fix_missing_locations(modified_tree) # 修复AST节点位置
# 编译修改后的AST
code = compile(modified_tree, module.__spec__.origin, 'exec')
# 注入system函数到模块的全局命名空间
# module.system = os.system
# 执行修改后的代码
exec(code, module.__dict__)
class ImportRemover(ast.NodeTransformer):
...
# def visit_Import(self, node):
# """删除所有Import节点"""
# return None
# def visit_ImportFrom(self, node):
# """删除所有ImportFrom节点"""
# return None
class CustomFinder(MetaPathFinder):
def find_spec(self, fullname, path, target=None):
Log.debug(fullname)
# 仅处理特定模块
# if not fullname.startswith('mocap_wrapper.config'):
# return None
# 临时移除 CustomFinder 以避免递归
meta_path.remove(self)
try:
# 查找原始模块的Spec
original_spec = find_spec(fullname)
finally:
# 重新添加 CustomFinder
meta_path.insert(0, self)
if not original_spec:
# 未找到
return None
# 使用自定义Loader替换原加载器
loader = CustomLoader(original_spec)
return spec_from_loader(
fullname,
loader,
origin=original_spec.origin
)
class Import:
singleton = None
@staticmethod
def init():
"""注册自定义Finder到meta_path"""
if not Import.singleton:
Import.singleton = CustomFinder()
if Import.singleton not in meta_path:
meta_path.insert(0, Import.singleton)
Log.debug(meta_path)
@staticmethod
def reset():
if Import.singleton in meta_path:
meta_path.remove(Import.singleton)
Import.singleton = None
Log.debug(meta_path)
def test():
Import.init()
import mocap_wrapper.config.template as c
Import.reset()
Log.debug(c.Aria2.port)
return c
if __name__ == '__main__':
c = test()

浙公网安备 33010602011771号