You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用PIL开发加水印程序时修改字体大小触发OSError问题求助

图片加水印程序OSError: cannot open resource问题解决

问题描述

我正在开发一款图片加水印程序,原本功能正常,但尝试修改字体大小时,持续触发错误:OSError: cannot open resource。尝试更换字体、设置默认字体,但错误仍会不定期出现。

原代码

import tkinter as tk
from tkinter import filedialog
from tkinter.filedialog import askopenfile
from PIL import Image, ImageTk, ImageDraw, ImageFont
import matplotlib.pyplot as plt

window = tk.Tk()
window.geometry("600x500")
window.title('Upload your image')
open_file_path = None



label = tk.Label(window,text='Add Photo',width=30)
label.grid(row=0,column=0)
label.place(relx=0.25, rely=0.01)
button = tk.Button(window, text='Upload File', width=20,command = lambda:upload_file())
button.grid(row=1,column=0)
button.place(relx=0.29, rely=0.1)
text = tk.Text(width = 40,height = 5)
text.place(relx = 0.24, rely = 0.3)
button_confirm = tk.Button(window,text = "Confirm text watermark",command = lambda:retrieve_input())
button_confirm.place(relx = 0.33,rely = 0.5)

def retrieve_input():
   input_value = text.get('1.0','end-1c')
   return input_value
def upload_file():
   global open_file_path
   font_type = ImageFont.truetype("arial.ttf", 18)
   input_text = retrieve_input()
   open_file_path = filedialog.askopenfilename()
   image = Image.open(open_file_path)
   width,height = image.size
   draw_watermark = ImageDraw.Draw(image)
   fill_color = (203, 201, 201)
   x = width/2-50
   y = height/2-50
   position = (x,y)
   draw_watermark.text(xy=position, text=input_text, fill=fill_color, font=font_type)
   image.save('watermark_image.jpg')
   # plt.imshow(image)

window.mainloop()

报错堆栈

Exception in Tkinter callback
Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/tkinter/__init__.py", line 1948, in __call__
    return self.func(*args)
           ^^^^^^^^^^^^^^^^
  File "/Users/admin/Desktop/Python/watermark_gui/main.py", line 17, in <lambda>
    button = tk.Button(window, text='Upload File', width=20,command = lambda:upload_file())
                                                                             ^^^^^^^^^^^^^
  File "/Users/admin/Desktop/Python/watermark_gui/main.py", line 30, in upload_file
    font_type = ImageFont.truetype("arial.ttf", 18)
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/admin/Desktop/Python/watermark_gui/env/lib/python3.12/site-packages/PIL/ImageFont.py", line 797, in truetype
    return freetype(font)
           ^^^^^^^^^^^^^^
  File "/Users/admin/Desktop/Python/watermark_gui/env/lib/python3.12/site-packages/PIL/ImageFont.py", line 794, in freetype
    return FreeTypeFont(font, size, index, encoding, layout_engine)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/admin/Desktop/Python/watermark_gui/env/lib/python3.12/site-packages/PIL/ImageFont.py", line 226, in __init__
    self.font = core.getfont(
                ^^^^^^^^^^^^^
OSError: cannot open resource

解决方案

错误核心原因

ImageFont.truetype("arial.ttf")无法在系统中准确定位字体文件:

  • macOS系统下直接写字体文件名,PIL无法自动识别系统字体路径
  • 每次点击上传都重复加载字体,容易引发资源加载冲突

修复步骤

  1. 指定字体完整路径:直接使用系统字体的绝对路径,避免路径查找失败
  2. 提前加载字体:将字体初始化放在函数外,只加载一次
  3. 添加异常 fallback:加载失败时自动切换到PIL默认字体

修改后的代码

import tkinter as tk
from tkinter import filedialog
from PIL import Image, ImageDraw, ImageFont

window = tk.Tk()
window.geometry("600x500")
window.title('Upload your image')
open_file_path = None

# 提前加载字体并添加异常处理
try:
    # macOS下Arial字体的默认绝对路径
    font_type = ImageFont.truetype("/Library/Fonts/Arial.ttf", 18)
except OSError:
    # 加载失败时使用PIL默认字体
    font_type = ImageFont.load_default()

label = tk.Label(window,text='Add Photo',width=30)
label.place(relx=0.25, rely=0.01)

button = tk.Button(window, text='Upload File', width=20,command = lambda:upload_file())
button.place(relx=0.29, rely=0.1)

text = tk.Text(width = 40,height = 5)
text.place(relx = 0.24, rely = 0.3)

button_confirm = tk.Button(window,text = "Confirm text watermark",command = lambda:retrieve_input())
button_confirm.place(relx = 0.33,rely = 0.5)

def retrieve_input():
   input_value = text.get('1.0','end-1c')
   return input_value

def upload_file():
   global open_file_path
   input_text = retrieve_input()
   open_file_path = filedialog.askopenfilename()
   if not open_file_path:
       return  # 用户取消选择文件时直接返回,避免后续报错
   image = Image.open(open_file_path)
   width,height = image.size
   draw_watermark = ImageDraw.Draw(image)
   fill_color = (203, 201, 201)
   x = width/2 - 50
   y = height/2 - 50
   position = (x,y)
   draw_watermark.text(xy=position, text=input_text, fill=fill_color, font=font_type)
   image.save('watermark_image.jpg')

window.mainloop()

多系统兼容扩展

如果需要支持Windows/Linux,可以通过判断系统来选择对应字体路径:

import sys
if sys.platform == 'darwin':
    font_path = "/Library/Fonts/Arial.ttf"
elif sys.platform == 'win32':
    font_path = "C:/Windows/Fonts/arial.ttf"
else:
    # Linux下使用开源替代字体
    font_path = "/usr/share/fonts/truetype/freefont/FreeSans.ttf"

内容的提问来源于stack exchange,提问作者Via4eslav Tka4enko

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 05:23:27