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

Python如何单独捕获Errno13权限拒绝异常

问题原因

两个核心问题导致你无法单独捕获errno13权限错误:

  1. 异常捕获顺序错误:PermissionError是OSError(Windows平台中WindowsError是OSError的别名)的子类,如果你把父类异常的except块写在子类前面,子类异常会被父类块提前拦截,永远走不到后面的PermissionError处理分支。
  2. 捕获的异常类型不匹配:shutil.copytree复制目录时默认不会直接抛出原始的PermissionError/WindowsError,而是会收集整个复制过程中遇到的所有错误,最终抛出shutil.Error。你看到的包含三元路径元组的输出,就是shutil.Error的标准字符串格式,这个异常本身没有winerror属性,所以你在WindowsError块里判断winerror自然匹配不到errno13的权限错误。
正确实现方案

你可以根据需求二选一:

方案1:直接捕获原始权限错误(推荐)

给shutil.copytree传入错误回调,让它遇到错误时直接抛出原始异常,再按「子类在前、父类在后」的顺序捕获即可:

import shutil
import errno

def throw_original_error(func, path, exc_info):
    # 直接抛出捕获到的原始异常,不做收集
    raise exc_info[1]

try:
    print('Copying files...')
    shutil.copytree(
        'C:/Users/' + userName + '/AppData/Roaming/Test/test1/',
        'C:/Users/' + userName + '/Desktop/test',
        onerror=throw_original_error
    )
    print('Success!')
# 子类异常放最前面,优先匹配
except PermissionError as e:
    if e.errno == errno.EACCES: # errno.EACCES 就是数值13
        print('You do not have the required privileges to make changes to this file.')
        print('One of the following solutions may work:')
        print('   >The file might be open in another location, close the file and try again.')
        print('   >Try to run the program as administrator.')
except WindowsError as e:
    if e.winerror == 2 or e.winerror == 3:
        print('Requested file does not exist.')
    else:
        print('Unexpected Windows exception occurred. Please copy the following exception and send it to test at test@test.com')
        print(e)
        quit()
except Exception as e:
    print('Unexpected exception occured. Please copy the following exception and send it to test at test@test.com')
    print(e)
    quit()

方案2:保留默认错误收集逻辑,解析shutil.Error

如果你需要保留copytree收集所有错误的特性,可以直接捕获shutil.Error,遍历它携带的错误列表判断是否存在权限错误:

import shutil
import errno

try:
    print('Copying files...')
    shutil.copytree(
        'C:/Users/' + userName + '/AppData/Roaming/Test/test1/',
        'C:/Users/' + userName + '/Desktop/test'
    )
    print('Success!')
except shutil.Error as e:
    # e.args[0] 是所有错误的列表,每个元素格式为(源路径, 目标路径, 异常信息)
    has_permission_denied = False
    for src, dst, err in e.args[0]:
        # 匹配Python3环境下的PermissionError实例
        if isinstance(err, PermissionError) and err.errno == errno.EACCES:
            has_permission_denied = True
            break
        # 兼容Python2环境下错误信息为字符串的情况
        if isinstance(err, str) and 'Errno 13' in err:
            has_permission_denied = True
            break
    if has_permission_denied:
        print('You do not have the required privileges to make changes to this file.')
        print('One of the following solutions may work:')
        print('   >The file might be open in another location, close the file and try again.')
        print('   >Try to run the program as administrator.')
    else:
        print('Unexpected exception occurred. Please copy the following exception and send it to test at test@test.com')
        print(e)
        quit()
except WindowsError as e:
    if e.winerror == 2 or e.winerror == 3:
        print('Requested file does not exist.')
    else:
        print('Unexpected Windows exception occurred. Please copy the following exception and send it to test at test@test.com')
        print(e)
        quit()
except Exception as e:
    print('Unexpected exception occured. Please copy the following exception and send it to test at test@test.com')
    print(e)
    quit()
注意事项
  • 所有异常捕获必须严格遵循子类在前、父类在后的顺序,否则子类异常永远会被上层父类捕获块拦截。
  • Windows平台下winerror=5(访问拒绝)本身就属于PermissionError范畴,和errno13是同类型权限错误,不需要单独写分支判断,统一在PermissionError块处理即可。
  • 你最初代码里的except WindowsError, e是Python2专属语法,在Python3环境下会直接抛出语法错误,需要改成except WindowsError as e的写法。

内容的提问来源于stack exchange,提问作者Jatinder Brar

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.01 03:09:44