ti-enxame.com

O "open ()" do Python gera erros diferentes para o "arquivo não encontrado" - como lidar com as duas exceções?

Eu tenho um script em que um usuário é solicitado a digitar um nome de arquivo (de um arquivo que será aberto) e, se o arquivo não existir no diretório atual, o usuário será solicitado novamente. Aqui está a versão curta:

file = input("Type filename: ")

...
try:
    fileContent = open(filename, "r")
    ...
except FileNotFoundError:
    ...

Quando testei meu script no meu MacOS X no Python 3.3x, ele funcionou perfeitamente quando digito o nome do arquivo errado de propósito (ele executa o conjunto em "expect").

No entanto, quando eu queria executar meu código em um computador Windows no Python 3.2x, recebo um erro informando que "FileNotFoundError" não está definido. Portanto, o Python 3.2 no Windows considera que "FileNotFoundError" é uma variável e os programas são encerrados com um erro.

Eu descobri que Python 3.2 no Windows lança um "IOError" se o nome do arquivo de entrada não for válido. Eu testei na minha máquina Linux no Python 2.7, e também é um IOError.

Meu problema agora é que o código com

except "FileNotFoundError":

não será executado no Python 3.2 do Windows, mas se eu o alterar para

except "IOError":

não funcionará mais no meu Mac.

Como eu poderia contornar isso? A única maneira de pensar é usar apenas except, o que geralmente não quero.

41
user2015601

No 3.3, IOError SE TORNOU UM ALIAS PARA OSError e FileNotFoundError é uma subclasse de OSError. Então você pode tentar

except (OSError, IOError) as e:
   ...

Isso lançará uma rede bastante ampla e você não pode assumir que a exceção é "arquivo não encontrado" sem inspecionar e.errno, mas pode cobrir seu caso de uso.

PEP 3151 discute a lógica da mudança em detalhes.

65
Russell Borogove

Isso me parece melhor do que um simples except:, mas não tenho certeza se é a melhor solução:

error_to_catch = getattr(__builtins__,'FileNotFoundError', IOError)

try:
    f = open('.....')
except error_to_catch:
    print('!')
10
cwallenpoole

Então, para capturar exatamente apenas quando um arquivo não é encontrado, eu faço:

import errno
try:
   open(filename, 'r')
except (OSError, IOError) as e: # FileNotFoundError does not exist on Python < 3.3
   if getattr(e, 'errno', 0) == errno.ENOENT:
      ... # file not found
   raise
5
Alex Che

você pode pegar 2 erros ao mesmo tempo

except (FileNotFoundError, IOError):

Eu não sabia que era isso que você estava perguntando. Espero que exista uma solução mais eloquente do que inspecionar manualmente

try:
   error_to_catch = FileNotFoundError
except NameError:
   error_to_catch = IOError

except error_to_catch

cwallenpoole faz isso condicionalmente de forma mais eloquente em sua resposta (error_to_catch = getattr(__builtins__,'FileNotFoundError', IOError))

2
dm03514