Python运行时通过字符串动态加载模块及访问模块变量
嘿,这个动态加载SD卡字体的需求我刚好折腾过,给你分享几个实用的实现方案,完全贴合你的场景:
1. 动态加载SD卡上的字体模块
因为字体文件存在SD卡的指定路径下,没法直接用常规的import导入,咱们可以用Python的importlib模块来动态加载外部.py文件:
import importlib.util import os def load_font_module(font_name): # 替换成你的SD卡实际挂载路径,比如'/sd/fonts/' font_dir = '/mnt/sdcard/fonts/' font_path = os.path.join(font_dir, f"{font_name}.py") # 检查文件是否存在,避免报错 if not os.path.exists(font_path): print(f"Font file {font_path} not found!") return None # 动态加载模块 spec = importlib.util.spec_from_file_location(font_name, font_path) font_module = importlib.util.module_from_spec(spec) spec.loader.exec_module(font_module) return font_module
调用的时候,只要传入字体名称(比如'arial14'),就能加载对应的arial14.py模块了。
2. 根据字符动态获取对应的字体变量
你的字体文件里用ch_(ASCII码)的格式存储字符数据,比如ch_33对应ASCII码33的!字符。这里绝对别用eval(不安全,容易触发恶意代码),用getattr函数安全获取变量:
def get_char_glyph(font_module, char): ascii_code = ord(char) var_name = f"ch_{ascii_code}" try: # 从模块中取出字符的宽度、高度和位掩码 width, height, bitmask = getattr(font_module, var_name) return (width, height, bitmask) except AttributeError: # 处理字符不存在的情况,返回默认值或者自定义fallback print(f"Character '{char}' not defined in this font") return (0, 0, [])
比如你要获取'!'的字体数据,ord('!')会得到33,函数就会自动找模块里的ch_33变量。
3. 整合显示逻辑
把上面两个函数拼起来,就能实现你要的动态加载+显示的功能了:
def display_character(font_name, char): # 加载字体模块 font_mod = load_font_module(font_name) if not font_mod: return # 获取字符的字体数据 width, height, bitmask = get_char_glyph(font_mod, char) if not bitmask: return # 这里替换成你的实际显示逻辑,比如驱动屏幕绘制像素 print(f"Rendering '{char}' (ASCII {ord(char)})") print(f"Size: {width}x{height}") print(f"Bitmask snippet: {bitmask[:15]}...")
调用示例:
display_character('arial14', '!') display_character('arial20', 'A')
几个关键注意点
- 路径正确性:一定要确认SD卡的挂载路径,不同设备可能不一样,比如有些嵌入式设备是
'/sd/'或者'/mnt/sd/'。 - 安全性:坚持用
getattr而不是eval,哪怕是自己的字体文件,也能避免潜在的风险(比如不小心写错变量名导致的意外执行)。 - 容错处理:记得处理文件不存在、字符未定义的情况,避免程序直接崩溃。
内容的提问来源于stack exchange,提问作者A. L
相关产品推荐
相关产品推荐

