Jupyter Notebook无法接收util目录函数返回的PIL.Image对象问题排查
问题:PIL.Image对象返回None的排查与解决
问题场景
在pyenv管理的Python 3.10.7虚拟环境中,将函数抽象至util目录后,DownScaler类的scale方法可正常打印PIL.Image对象,但返回值始终为None,其他类型返回正常。
涉及代码
DownScaler类的scale方法:
from PIL import Image from util.functionPerformance import functionPerformance class DownScaler: @staticmethod @functionPerformance def scale(img_path:Image ,x_factor:float, y_factor:float, verbose:bool=False) -> Image: picture = Image.open(img_path) picture.resize((int(picture.width*x_factor),int(picture.height*y_factor))) # 验证对象存在 print(picture) return picture
Jupyter Notebook调用代码:
scaled_img = DownScaler.scale(image_path, .2, .2) print(scaled_img)
输出结果
<PIL.JpegImagePlugin.JpegImageFile image mode=RGB size=300x400 at 0x17EF2F4F0> None
原因分析
- resize方法的非原地特性:PIL的
Image.resize()是非原地修改方法,调用后会生成并返回一个新的缩放后Image对象,原picture对象不会被修改。但这不是返回None的直接原因,原代码中picture仍是有效的原始图片对象。 - 装饰器未传递返回值:核心问题出在
@functionPerformance装饰器上。如果该装饰器仅执行了计时等逻辑,但没有将被装饰函数的返回值传递出来,装饰后的函数会默认返回None——这就是为什么函数内部能打印出有效对象,但外部接收的返回值为None。
解决方法
1. 修正resize的使用(实现缩放逻辑)
如果需要返回缩放后的图片,必须接收resize的返回值:
picture = picture.resize((int(picture.width*x_factor), int(picture.height*y_factor)))
2. 修复装饰器的返回逻辑
检查functionPerformance装饰器的实现,确保它返回被装饰函数的执行结果。标准的计时装饰器示例:
import time def functionPerformance(func): def wrapper(*args, **kwargs): start_time = time.time() result = func(*args, **kwargs) # 保存函数执行结果 end_time = time.time() print(f"函数 {func.__name__} 执行耗时: {end_time - start_time:.4f} 秒") return result # 必须返回结果 return wrapper
内容的提问来源于stack exchange,提问作者FredNoonienSingh
相关产品推荐
相关产品推荐

