如何在Windows系统中无需重启,使用Python批量安装字体?
如何在Windows系统中无需重启,使用Python批量安装字体?
我完全懂你的困扰——手动点安装字体效率太低,自己写的批量脚本虽然能把字体文件复制到系统Fonts目录、更新注册表,但必须重启电脑才能让系统认出新字体,这对要即时用字体的场景实在太不友好了。
其实问题出在:Windows不会自动监测Fonts目录和注册表的字体更新,得主动通知它刷新字体缓存才行。下面就给你解决方法,直接修改你的代码就能实现无需重启生效。
关键原理:发送系统刷新消息
Windows提供了WM_FONTCHANGE消息,只要把这个消息广播给所有顶层窗口,系统就会立刻重新加载字体列表,不用重启。另外配合AddFontResource API可以进一步确保字体被正确注册。
修改后的完整代码
我在你的代码基础上添加了字体刷新的逻辑,还补了一些细节优化(比如跳过已存在的字体文件):
from fontTools.ttLib import TTFont import winreg import os import ctypes from ctypes import wintypes def list_fonts(folder): result = {} for file in os.scandir(folder): if file.is_file() and file.name.endswith((".otf", ".ttf")): path = file.path.replace("\\", "/") try: name = TTFont(path)["name"] result.setdefault(name.getDebugName(1), {})[name.getDebugName(2)] = ( name.getDebugName(4), path, ) except Exception as e: print(f"处理字体文件失败 {file.name}: {e}") return result def refresh_font_cache(): # 广播字体更新消息给系统 HWND_BROADCAST = 0xFFFF WM_FONTCHANGE = 0x001D user32 = ctypes.WinDLL('user32', use_last_error=True) user32.SendMessageW.argtypes = (wintypes.HWND, wintypes.UINT, wintypes.WPARAM, wintypes.LPARAM) user32.SendMessageW(HWND_BROADCAST, WM_FONTCHANGE, 0, 0) # 可选:调用AddFontResource确保字体被系统识别(针对部分特殊字体) gdi32 = ctypes.WinDLL('gdi32', use_last_error=True) gdi32.AddFontResourceW.argtypes = (wintypes.LPCWSTR,) HKLM = winreg.ConnectRegistry(None, winreg.HKEY_LOCAL_MACHINE) FONTS_KEY = winreg.OpenKey( HKLM, r"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Fonts", 0, winreg.KEY_ALL_ACCESS, ) def install_fonts(folder): fonts_list = list_fonts(folder) fonts_dir = os.path.join(os.environ["WINDIR"], "Fonts") for styles in fonts_list.values(): for font_name, path in styles.values(): font_filename = os.path.basename(path) target_path = os.path.join(fonts_dir, font_filename) # 跳过已存在的字体,避免覆盖 if os.path.exists(target_path): print(f"字体 {font_filename} 已存在,跳过安装") continue # 复制字体文件到系统Fonts目录 try: with open(path, "rb") as reader, open(target_path, "wb") as writer: writer.write(reader.read()) print(f"已复制字体文件: {font_filename}") except Exception as e: print(f"复制字体文件失败 {font_filename}: {e}") continue # 更新注册表 try: reg_value_name = f"{font_name} (TrueType)" if font_filename.endswith(".ttf") else font_name winreg.SetValueEx( FONTS_KEY, reg_value_name, 0, winreg.REG_SZ, font_filename, ) print(f"已更新注册表: {reg_value_name}") except Exception as e: print(f"更新注册表失败 {reg_value_name}: {e}") # 若注册表更新失败,删除已复制的字体文件 if os.path.exists(target_path): os.remove(target_path) # 安装完成后刷新字体缓存 refresh_font_cache() print("字体缓存已刷新,无需重启即可使用新字体!")
注意事项
- 必须以管理员权限运行脚本:因为要写入系统Fonts目录和修改HKLM下的注册表,普通权限会报错。右键点击Python脚本,选择「以管理员身份运行」即可。
- 测试验证:安装完成后,打开Word、PS等软件,就能直接在字体列表里找到新安装的字体了;如果系统自带的Fonts文件夹没立刻显示,关闭再重新打开就能看到。
- 字体文件兼容性:确保你的字体文件是标准的
.ttf或.otf格式,损坏的字体文件会被脚本跳过并提示错误。
备注:内容来源于stack exchange,提问作者Ξένη Γήινος




