首页 > 解决方案 > 如何同时捕获 OSError 和 FileNotFoundError

问题描述

在我正在处理的代码中,当用户输入文件名以从中加载数据或将数据保存到时,我发现了一些异常。我想要的是在 Windows 上的文件名无效(例如“///”)和请求的文件不存在的情况下显示不同的消息。

问题:如果我尝试在OSError输入无效文件名时捕获触发它会覆盖FileNotFoundError例如:

filename = input('Please enter filename containing data: ')
try:
    data = load_data(filename)                
except OSError:
    print('Invalid file name. Try again.')
except FileNotFoundError:
    print('File does not exist. Please try again.')
except TypeError:
    print('Please enter a valid file name.')
except json.decoder.JSONDecodeError:
    print('Invalid file format.')

在这里,如果我输入了一个无效的文件名,例如,///或者一个不存在的文件名 - 在这两种情况下都会OSError触发。另一方面,JSONDecodeError被正确捕获。

我尝试过切换OSErrorFileNotFoundError但仍然只有OSError曾经的触发器。只有当我完全删除 OSError 时,我才能真正捕获 FNFError。

任何人都知道我怎样才能分别捕获OSError两者FNFError

编辑:当我切换 except 语句的顺序时会发生这种情况:

filename = input('Please enter filename containing data: ')
try:
    data = load_data(filename)    
except FileNotFoundError:
    print('File does not exist. Please try again.')            
except OSError:
    print('Invalid file name. Try again.')
except TypeError:
    print('Please enter a valid file name.')
except json.decoder.JSONDecodeError:
    print('Invalid file format.')

>>> Please enter filename containing data: ///
Out: File does not exist. Please try again.

编辑2: 这是代码load_data()

def load_data(filename: str) -> dict:
    with open(filename, 'r') as jsfile:
        data = json.load(jsfile)
    
    print(f'\nLoaded {len(data.keys())} records.')
    return data

标签: pythonexception

解决方案


只需更改顺序(FileNotFoundError是的子类OSError¯\_(ツ)_/¯

因为→</p>

for f in ["///", "blahblah"]:
    try:
        open(f, "rb")
    except FileNotFoundError:
        print('File does not exist: '+f+'. Please try again.')
    except OSError:
        print('Invalid file name: '+f+'. Try again.')
    except TypeError:
        print('Please enter a valid file name: '+f+'.')
    except json.decoder.JSONDecodeError:
        print('Invalid file format: '+f+'.')
Invalid file name: ///. Try again.
File does not exist: blahblah. Please try again.

但:

for f in ["///", "blahblah"]:
    try:
        open(f, "rb")
    except OSError:
        print('Invalid file name: '+f+'. Try again.')
    except FileNotFoundError:
        print('File does not exist: '+f+'. Please try again.')
    except TypeError:
        print('Please enter a valid file name: '+f+'.')
    except json.decoder.JSONDecodeError:
        print('Invalid file format: '+f+'.')
Invalid file name: ///. Try again.
Invalid file name: blahblah. Try again.

测试Python 3.7.1Linux

编辑 1。

使用 json.load() 测试的行为

按预期工作 →</p>

import json

for f in ["///", "blahblah"]:
    try:
        with open(f, 'r') as jsfile:
            data = json.load(jsfile)
    except FileNotFoundError:
        print('File does not exist: '+f+'. Please try again.')
    except OSError:
        print('Invalid file name: '+f+'. Try again.')
    except TypeError:
        print('Please enter a valid file name: '+f+'.')
Invalid file name: ///. Try again.
File does not exist: blahblah. Please try again.

你在使用 Windows 吗?不确定///Windows FS (NTFS) 的名称是否错误。例如\\\是 Linux FS 的好名字

import json

for f in ["\\\\\\", "///", "blahblah"]:
    try:
        with open(f, 'r') as jsfile:
            data = json.load(jsfile)
    except FileNotFoundError:
        print('File does not exist: '+f+'. Please try again.')
    except OSError:
        print('Invalid file name: '+f+'. Try again.')
    except TypeError:
        print('Please enter a valid file name: '+f+'.')
File does not exist: \\\. Please try again.
Invalid file name: ///. Try again.
File does not exist: blahblah. Please try again.
$ touch '\\\'
$ ls -l

...
-rw-r--r--.  1 root root        0 May 25 11:59 \\\
...

推荐阅读