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

使用Pillow保存图片时遇Errno 13权限错误(Python+Django)

解决Pillow保存裁剪图片时的Errno 13权限错误

错误原因分析

出现PermissionError: [Errno 13] Permission denied通常有以下几个核心原因:

  • 目录创建时机错误,导致保存时目标目录不存在或权限未正确初始化
  • 运行Python程序的用户对目标目录无读写权限
  • 路径拼接时的转义问题导致实际访问路径异常
  • 裁剪函数逻辑缺陷,返回None时仍执行保存操作

具体修复方案

1. 调整目录创建逻辑

将目录创建操作移至循环外部,确保保存前目录已存在,同时过滤掉无需裁剪的图片:

# 提前创建裁剪目录,用makedirs支持多级目录,exist_ok=True避免重复创建报错
if not os.path.exists(cropped_dir):
    os.makedirs(cropped_dir, exist_ok=True)

for each_image in os.listdir(image_dir):
    image_path = os.path.join(image_dir, each_image)
    cropping = crop_image(image_path)
    # 仅当裁剪结果有效时执行保存
    if cropping is not None:
        save_path = os.path.join(cropped_dir, each_image)
        cropping.save(save_path, 'jpeg')
        cropping.close()  # 关闭文件句柄,避免资源泄漏

2. 修复系统权限问题

  • Windows系统:右键点击blah-summer-jean目录 → 「属性」→「安全」,给当前运行Python的用户(如登录用户、PyCharm进程用户)添加「写入」「修改」权限
  • 避免将目录放在系统保护路径下(如C:\Program Files),优先选择用户目录下的非保护区域
  • 如果使用虚拟环境,确保虚拟环境进程拥有目录的读写权限

3. 用Pathlib优化路径处理

替换手动路径拼接为pathlib,避免转义字符引发的路径异常:

from pathlib import Path

# 用Path对象管理路径,自动处理系统分隔符
image_dir = Path('C:/Users/django/PycharmProjects/sassigen/csvs/photos/blah-summer-jean')
cropped_dir = image_dir / 'cropped-788x1000'

# 创建目录,parents=True自动创建上级目录
cropped_dir.mkdir(parents=True, exist_ok=True)

# 遍历目录只处理文件
for each_image in image_dir.iterdir():
    if each_image.is_file():
        cropping = crop_image(str(each_image))
        if cropping is not None:
            save_path = cropped_dir / each_image.name
            cropping.save(str(save_path), 'jpeg')
            cropping.close()

4. 完善裁剪函数逻辑

修复无需裁剪时的返回值,确保文件句柄正常关闭:

def crop_image(image):
    try:
        img = Image.open(image)
        width, height = img.size
        if width <= 788 and height <= 1000:
            # 返回原图片副本,避免原文件被占用
            result = img.copy()
            img.close()
            return result
        else:
            # 修正裁剪坐标逻辑,匹配最终788x1000的尺寸
            xcenter = img.width / 2
            ycenter = img.height / 2
            x1 = max(0, int(xcenter - 394))
            y1 = max(0, int(ycenter - 500))
            x2 = min(img.width, int(xcenter + 394))
            y2 = min(img.height, int(ycenter + 500))
            
            image_to_crop = img.crop((x1, y1, x2, y2))
            final_image = image_to_crop.resize((788, 1000))
            
            # 关闭所有临时文件句柄
            img.close()
            image_to_crop.close()
            return final_image
    except AttributeError:
        return None
    except Exception as e:
        # 异常时确保关闭已打开的文件
        if 'img' in locals():
            img.close()
        raise e

内容的提问来源于stack exchange,提问作者Vinh Nguyen

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 03:06:29