Por que "exceto: passar" é uma prática ruim de programação?

325

Costumo ver comentários sobre outras questões do Stack Overflow sobre como o uso de except: passé desencorajado. Por que isso é ruim? Às vezes, simplesmente não me importo com os erros e quero continuar com o código.

try:
    something
except:
    pass

Por que o uso de um except: passbloco é ruim? O que a torna ruim? É o fato de eu estar passcom um erro ou de exceptalgum erro?

Vader
fonte
1
No mínimo, sugiro que você faça o logon, para que você saiba quais problemas está ignorando. Use o loggingmódulo no nível DEBUG para evitar que eles fluam na produção, mas mantenha-os disponíveis no desenvolvimento.
21418 pcurry

Respostas:

346

Como você adivinhou corretamente, existem dois lados: Capturar qualquer erro especificando nenhum tipo de exceção depois excepte simplesmente transmiti-lo sem executar nenhuma ação.

Minha explicação é "um pouco" mais longa - então tl; dr se resume a isso:

  1. Não pegue nenhum erro . Sempre especifique de quais exceções você está preparado para recuperar e somente as captura.
  2. Tente evitar a passagem, exceto blocos . A menos que seja explicitamente desejado, esse geralmente não é um bom sinal.

Mas vamos entrar em detalhes:

Não pegue nenhum erro

Ao usar um trybloco, você geralmente faz isso porque sabe que há uma chance de uma exceção ser lançada. Como tal, você também já tem uma idéia aproximada do que pode quebrar e que exceção pode ser lançada. Nesses casos, você captura uma exceção porque pode se recuperar positivamente dela. Isso significa que você está preparado para a exceção e tem algum plano alternativo que seguirá no caso dessa exceção.

Por exemplo, quando você pede ao usuário para inserir um número, pode converter a entrada usando o int()que pode gerar a ValueError. Você pode recuperá-lo facilmente, simplesmente pedindo ao usuário para tentar novamente, então capturar ValueErrore solicitar ao usuário novamente seria um plano apropriado. Um exemplo diferente seria se você quiser ler alguma configuração de um arquivo e esse arquivo não existir. Por ser um arquivo de configuração, você pode ter alguma configuração padrão como fallback, portanto, o arquivo não é exatamente necessário. Portanto, pegar um FileNotFoundErrore simplesmente aplicar a configuração padrão seria um bom plano aqui. Agora, em ambos os casos, temos uma exceção muito específica que esperamos e temos um plano igualmente específico para se recuperar dela. Como tal, em cada caso, explicitamente apenas except que certas exceção.

No entanto, se quiséssemos capturar tudo , então - além das exceções que estamos preparados para recuperar - também há uma chance de obtermos exceções que não esperávamos e das quais realmente não podemos recuperar; ou não deve se recuperar.

Vamos dar o exemplo do arquivo de configuração acima. No caso de um arquivo ausente, acabamos de aplicar nossa configuração padrão e, posteriormente, podemos decidir salvar automaticamente a configuração (portanto, da próxima vez, o arquivo existe). Agora imagine que temos um IsADirectoryError, ou umPermissionErrorem vez de. Nesses casos, provavelmente não queremos continuar; ainda poderíamos aplicar nossa configuração padrão, mas mais tarde não conseguiremos salvar o arquivo. E é provável que o usuário tenha também uma configuração personalizada, portanto, o uso dos valores padrão provavelmente não é desejado. Portanto, gostaríamos de informar o usuário sobre isso imediatamente e provavelmente abortar a execução do programa também. Mas isso não é algo que queremos fazer em algum lugar profundo dentro de uma pequena parte do código; isso é algo de importância no nível do aplicativo, por isso deve ser tratado no topo - deixe a exceção surgir.

Outro exemplo simples também é mencionado no documento de idiomas do Python 2 . Aqui, existe um simples erro de digitação no código que causa a sua quebra. Como estamos capturando todas as exceções, também captamos NameErrors e SyntaxErrors . Ambos são erros que acontecem a todos nós durante a programação; e ambos são erros que absolutamente não queremos incluir ao enviar o código. Mas como também os capturamos, nem saberemos que eles ocorreram lá e perderemos qualquer ajuda para depurá-lo corretamente.

Mas também existem exceções mais perigosas para as quais não estamos preparados. Por exemplo, SystemError é geralmente algo que acontece raramente e que não podemos realmente planejar; significa que há algo mais complicado acontecendo, algo que provavelmente nos impede de continuar a tarefa atual.

De qualquer forma, é muito improvável que você esteja preparado para tudo em uma parte do código em pequena escala; portanto, é nesse ponto que você deve capturar apenas as exceções para as quais está preparado. Algumas pessoas sugerem, pelo menos, capturar Exception, pois não incluirão coisas como SystemExite KeyboardInterruptque, por design, devem finalizar seu aplicativo, mas eu argumentaria que isso ainda é muito inespecífico. Só existe um lugar onde eu pessoalmente aceito capturar Exceptionou qualquerexceção, e isso está em um único manipulador de exceções no nível de aplicativo global que tem o único objetivo de registrar qualquer exceção para a qual não estávamos preparados. Dessa forma, ainda podemos reter o máximo de informações sobre exceções inesperadas, que podemos usar para estender nosso código para lidar com elas explicitamente (se conseguirmos recuperar delas) ou - no caso de um bug - para criar casos de teste para garantir isso não vai acontecer novamente. Mas, é claro, isso só funciona se capturarmos as exceções que já esperávamos; portanto, as que não esperávamos naturalmente borbulhariam.

Tente evitar a passagem, exceto blocos

Ao capturar explicitamente uma pequena seleção de exceções específicas, há muitas situações em que ficaremos bem simplesmente sem fazer nada. Nesses casos, apenas ter except SomeSpecificException: passestá bem. Na maioria das vezes, porém, esse não é o caso, pois provavelmente precisamos de algum código relacionado ao processo de recuperação (como mencionado acima). Isso pode ser, por exemplo, algo que repete a ação novamente ou para configurar um valor padrão.

Se esse não for o caso, por exemplo, porque nosso código já está estruturado para repetir até que seja bem-sucedido, apenas passar é bom o suficiente. Tomando nosso exemplo acima, podemos solicitar ao usuário que digite um número. Como sabemos que os usuários gostam de não fazer o que pedimos, podemos colocá-lo em um loop em primeiro lugar, para que fique assim:

def askForNumber ():
    while True:
        try:
            return int(input('Please enter a number: '))
        except ValueError:
            pass

Como continuamos tentando até que nenhuma exceção seja lançada, não precisamos fazer nada de especial no bloco exceto, então isso é bom. Mas, é claro, alguém pode argumentar que pelo menos queremos mostrar ao usuário alguma mensagem de erro para lhe dizer por que ele precisa repetir a entrada.

Em muitos outros casos, apenas passar exceptum sinal de que não estávamos realmente preparados para a exceção que estamos capturando. A menos que essas exceções sejam simples (como ValueErrorou TypeError), e a razão pela qual podemos passar seja óbvia, tente evitar apenas passar. Se não houver realmente nada a fazer (e você tiver certeza absoluta disso), considere adicionar um comentário sobre o motivo; caso contrário, expanda o bloco de exceção para incluir algum código de recuperação.

except: pass

O pior ofensor é a combinação de ambos. Isso significa que estamos apanhando qualquer erro de boa vontade, embora não estejamos absolutamente preparados para isso e também não fazemos nada a respeito. Você, pelo menos, deseja registrar o erro e também provavelmente re-aumentá-lo para finalizar o aplicativo (é improvável que você possa continuar normalmente após um MemoryError). Só passar não só manterá o aplicativo um pouco vivo (dependendo de onde você captura, é claro), mas também jogará fora todas as informações, tornando impossível descobrir o erro - o que é especialmente verdadeiro se você não o descobrir.


Portanto, o ponto principal é: Capture apenas as exceções que você realmente espera e está preparado para se recuperar; todos os outros provavelmente são erros que você deve corrigir ou algo para o qual não está preparado. Passar exceções específicas é bom se você realmente não precisa fazer algo sobre elas. Em todos os outros casos, é apenas um sinal de presunção e de preguiça. E você definitivamente quer consertar isso.

cutucar
fonte
1
"Você pelo menos deseja registrar o erro e também provavelmente re-aumentá-lo para finalizar o aplicativo". Você pode demonstrar como "reler" uma exceção para que ela continue borbulhando mesmo depois de capturá-la? Isso me parece útil para adicionar algumas mensagens de erro personalizadas enquanto ainda permite que a exceção force o encerramento do aplicativo.
Gabriel Staples
1
Isso ajuda a esclarecer: eles usam o cobertor except, mas depois chamam raisesem argumentos para continuar deixando a exceção aparecer, encerrando o aplicativo. Gostei: ianbicking.org/blog/2007/09/re-raising-exceptions.html . Parece uma exceção sólida à regra de não usar o cobertor except.
Gabriel Staples
1
@GabrielStaples Sim, uma exceção capturada pode ser reapresentada usando raise. Normalmente, você faria isso apenas em alguns locais do aplicativo para registrar a exceção.
Poke
Isso é ótimo, evite passar exceto blocos. Eu diria que faça o que parecer mais compreensível, especialmente para os outros. Obtenha um segundo conjunto de olhos python para revisar seu código e ver se eles questionam o bloco. Legibilidade é a chave.
radtek
262

O principal problema aqui é que ele ignora todo e qualquer erro: Sem memória, a CPU está queimando, o usuário quer parar, o programa quer sair, o Jabberwocky está matando os usuários.

Isso é demais. Na sua cabeça, você está pensando "Quero ignorar esse erro de rede". Se algo inesperado der errado, seu código continuará silenciosamente e quebrará de maneiras completamente imprevisíveis que ninguém pode depurar.

É por isso que você deve limitar-se a ignorar especificamente apenas alguns erros e deixar o resto passar.

Aaron Digulla
fonte
75

Executar o seu pseudo-código literalmente não gera nenhum erro:

try:
    something
except:
    pass

como se fosse um pedaço de código perfeitamente válido, em vez de lançar a NameError. Espero que não seja isso que você deseja.

YS-L
fonte
51

Por que "exceto: passar" é uma prática ruim de programação?

Por que isso é ruim?

try:
    something
except:
    pass

Isso captura todas as exceções possíveis, incluindo GeneratorExit,, KeyboardInterrupte SystemExit- que são exceções que você provavelmente não pretende capturar. É o mesmo que pegar BaseException.

try:
    something
except BaseException:
    pass

As versões mais antigas da documentação dizem :

Como todo erro no Python gera uma exceção, o uso de except:vários erros de programação pode parecer problemas de tempo de execução, o que dificulta o processo de depuração.

Hierarquia de exceção do Python

Se você capturar uma classe de exceção pai, também captura todas as classes filho. É muito mais elegante capturar apenas as exceções que você está preparado para lidar.

Aqui está a hierarquia de exceção do Python 3 - você realmente quer pegá-los todos ?:

BaseException
 +-- SystemExit
 +-- KeyboardInterrupt
 +-- GeneratorExit
 +-- Exception
      +-- StopIteration
      +-- StopAsyncIteration
      +-- ArithmeticError
      |    +-- FloatingPointError
      |    +-- OverflowError
      |    +-- ZeroDivisionError
      +-- AssertionError
      +-- AttributeError
      +-- BufferError
      +-- EOFError
      +-- ImportError
           +-- ModuleNotFoundError
      +-- LookupError
      |    +-- IndexError
      |    +-- KeyError
      +-- MemoryError
      +-- NameError
      |    +-- UnboundLocalError
      +-- OSError
      |    +-- BlockingIOError
      |    +-- ChildProcessError
      |    +-- ConnectionError
      |    |    +-- BrokenPipeError
      |    |    +-- ConnectionAbortedError
      |    |    +-- ConnectionRefusedError
      |    |    +-- ConnectionResetError
      |    +-- FileExistsError
      |    +-- FileNotFoundError
      |    +-- InterruptedError
      |    +-- IsADirectoryError
      |    +-- NotADirectoryError
      |    +-- PermissionError
      |    +-- ProcessLookupError
      |    +-- TimeoutError
      +-- ReferenceError
      +-- RuntimeError
      |    +-- NotImplementedError
      |    +-- RecursionError
      +-- SyntaxError
      |    +-- IndentationError
      |         +-- TabError
      +-- SystemError
      +-- TypeError
      +-- ValueError
      |    +-- UnicodeError
      |         +-- UnicodeDecodeError
      |         +-- UnicodeEncodeError
      |         +-- UnicodeTranslateError
      +-- Warning
           +-- DeprecationWarning
           +-- PendingDeprecationWarning
           +-- RuntimeWarning
           +-- SyntaxWarning
           +-- UserWarning
           +-- FutureWarning
           +-- ImportWarning
           +-- UnicodeWarning
           +-- BytesWarning
           +-- ResourceWarning

Não faça isso

Se você estiver usando esta forma de tratamento de exceções:

try:
    something
except: # don't just do a bare except!
    pass

Então você não poderá interromper seu somethingbloco com Ctrl-C. Seu programa ignorará todas as exceções possíveis dentro do trybloco de código.

Aqui está outro exemplo que terá o mesmo comportamento indesejável:

except BaseException as e: # don't do this either - same as bare!
    logging.info(e)

Em vez disso, tente capturar apenas a exceção específica que você sabe que está procurando. Por exemplo, se você sabe que pode receber um erro de valor em uma conversão:

try:
    foo = operation_that_includes_int(foo)
except ValueError as e:
    if fatal_condition(): # You can raise the exception if it's bad,
        logging.info(e)   # but if it's fatal every time,
        raise             # you probably should just not catch it.
    else:                 # Only catch exceptions you are prepared to handle.
        foo = 0           # Here we simply assign foo to 0 and continue. 

Explicação adicional com outro exemplo

Você pode estar fazendo isso porque está UnicodeErrorusando a Web scraping e obtendo, digamos, um , mas porque usou a captura de exceção mais ampla, seu código, que pode ter outras falhas fundamentais, tentará executar até a conclusão, desperdiçando largura de banda , tempo de processamento, desgaste do equipamento, falta de memória, coleta de dados de lixo etc.

Se outras pessoas estão pedindo que você preencha para que possam confiar no seu código, entendo que estou sendo obrigado a lidar com tudo. Mas se você estiver disposto a falhar ruidosamente à medida que se desenvolver, terá a oportunidade de corrigir problemas que só podem aparecer intermitentemente, mas que seriam erros dispendiosos a longo prazo.

Com um tratamento de erro mais preciso, o código pode ser mais robusto.

Aaron Hall
fonte
31
>>> import this

O Zen de Python, de Tim Peters

Bonito é melhor que feio.
Explícito é melhor que implícito.
Simples é melhor que complexo.
Complexo é melhor que complicado.
Flat é melhor que aninhado.
Esparso é melhor que denso.
Legibilidade conta.
Casos especiais não são especiais o suficiente para violar as regras.
Embora praticidade supere a pureza.
Os erros nunca devem passar silenciosamente.
A menos que seja explicitamente silenciado.
Diante da ambiguidade, recuse a tentação de adivinhar.
Deve haver uma - e preferencialmente apenas uma - maneira óbvia de fazê-lo.
Embora esse caminho possa não ser óbvio a princípio, a menos que você seja holandês.
Agora é melhor do que nunca.
Embora nunca seja frequentemente melhor do queagora mesmo .
Se a implementação é difícil de explicar, é uma má ideia.
Se a implementação é fácil de explicar, pode ser uma boa ideia.
Os espaços para nome são uma ótima idéia - vamos fazer mais!

Então, aqui está a minha opinião. Sempre que encontrar um erro, você deve fazer algo para lidar com isso, por exemplo, escrevê-lo no arquivo de log ou algo mais. Pelo menos, informa que costumava haver um erro.

Booster
fonte
64
O argumento da autoridade não explica nada. A autoridade pode estar errada.
Izkata 04/02
23
o que o @Izkata escreveu, E, uma linha abaixo, a mesma autoridade escreve: "A menos que seja explicitamente silenciado", que é exatamente o que exceto: pass faz.
Ofri Raviv
13
@OfriRaviv Não, o erro não está passando implicitamente ? Explicitamente exigiria nomear o erro que deveria passar silenciosamente, ou seja, ser explícito sobre ele . Isso não é o que, exceto: passa sim.
Chelonian
24

Você deve usar pelo menos except Exception:para evitar exceções do sistema como SystemExitou KeyboardInterrupt. Aqui está o link para documentos.

Em geral, você deve definir explicitamente as exceções que deseja capturar, para evitar capturar exceções indesejadas. Você deve saber quais exceções você ignora .

Tupteq
fonte
13

Primeiro, ele viola dois princípios do Zen of Python :

  • Explícito é melhor que implícito
  • Erros nunca devem passar silenciosamente

O que isso significa é que você intencionalmente comete o erro silenciosamente. Além disso, você não sabe qual erro ocorreu exatamente, porque except: passcapturará qualquer exceção.

Segundo, se tentarmos abstrair-se do Zen de Python e falar em termos de apenas sanidade, você deve saber que o uso o except:passdeixa sem conhecimento e controle em seu sistema. A regra geral é gerar uma exceção, se ocorrer um erro, e tomar as ações apropriadas. Se você não souber com antecedência, quais devem ser as ações, pelo menos registre o erro em algum lugar (e é melhor redigitar a exceção):

try:
    something
except:
    logger.exception('Something happened')

Mas, geralmente, se você tentar capturar alguma exceção, provavelmente está fazendo algo errado!

Alexander Zhukov
fonte
2
... A menos que seja explicitamente silenciado, que é o caso do OP.
Hyperboreus
Eu quero conhecer sua solução. De fato, quando realmente nada precisa ser feito, apenas listo os erros, exceto, faço comentários e escrevo logs. Então apenas passe.
impulsionador
2
@ Hyperboreus, eu não acho, que pegar todos e quaisquer erros os esteja silenciando explicitamente, ou seja, você nem sabe o que você pega.
Alexander Zhukov
13
"Porque alguém diz isso" não é realmente uma resposta para um "Por quê?" questão.
Sebastian Negraszus
12

A except:passconstrução basicamente silencia todas e quaisquer condições excepcionais que surgem enquanto o código coberto no try:bloco está sendo executado.

O que torna essa má prática é que ela geralmente não é o que você realmente deseja. Mais frequentemente, está surgindo alguma condição específica que você deseja silenciar e except:passé um instrumento muito contundente. Ele fará o trabalho, mas também ocultará outras condições de erro que você provavelmente não previu, mas que pode muito bem querer lidar de alguma outra maneira.

O que torna isso particularmente importante no Python é que, pelos idiomas dessa linguagem, as exceções não são necessariamente erros . Eles são frequentemente usados ​​dessa maneira, é claro, assim como na maioria dos idiomas. Mas o Python, em particular, ocasionalmente os usou para implementar um caminho de saída alternativo de algumas tarefas de código que não fazem parte do caso de execução normal, mas ainda é conhecido por surgir de tempos em tempos e pode até ser esperado na maioria dos casos. SystemExitjá foi mencionado como um exemplo antigo, mas o exemplo mais comum hoje em dia pode ser StopIteration. O uso de exceções dessa maneira causou muita controvérsia, especialmente quando os iteradores e geradores foram introduzidos pela primeira vez no Python, mas eventualmente a idéia prevaleceu.

The Spooniest
fonte
12

O motivo número 1 já foi declarado - oculta erros que você não esperava.

(# 2) - Torna seu código difícil para outras pessoas lerem e entenderem. Se você capturar uma FileNotFoundException ao tentar ler um arquivo, é bastante óbvio para outro desenvolvedor que funcionalidade o bloco 'catch' deve ter. Se você não especificar uma exceção, precisará de comentários adicionais para explicar o que o bloco deve fazer.

(# 3) - Demonstra programação lenta. Se você usar o try / catch genérico, isso indica que você não entende os possíveis erros de tempo de execução no seu programa ou que não sabe quais exceções são possíveis no Python. A captura de um erro específico mostra que você entende o seu programa e o intervalo de erros que o Python gera. É mais provável que outros desenvolvedores e revisores de código confiem no seu trabalho.

Kevin
fonte
12

Então, qual saída esse código produz?

fruits = [ 'apple', 'pear', 'carrot', 'banana' ]

found = False
try:
     for i in range(len(fruit)):
         if fruits[i] == 'apple':
             found = true
except:
     pass

if found:
    print "Found an apple"
else:
    print "No apples in list"

Agora imagine o bloco try- excepté centenas de linhas de chamadas para uma hierarquia complexa de objetos e é chamado no meio da árvore de chamadas de grandes programas. Quando o programa dá errado, onde você começa a procurar?

Ian Harvey
fonte
5
Er, graças às pessoas que 'corrigiram' isso, mas por favor não - é intencionalmente errado, no sentido de 'pergunta da entrevista'. É possivelmente mais sutil que ele apareça pela primeira vez - tente. Meu argumento é que esmagar todas as exceções, especialmente em Python, torna a depuração difícil, mesmo em uma dúzia de linhas de código triviais.
Ian Harvey
11

Em geral, você pode classificar qualquer erro / exceção em uma das três categorias :

  • Fatal : Não é sua culpa, você não pode evitá-los, não pode se recuperar deles. Você certamente não deve ignorá-los, continuar e deixar seu programa em um estado desconhecido. Apenas deixe o erro finalizar o seu programa, não há nada que você possa fazer.

  • Boneheaded : Sua própria falha, provavelmente devido a um erro de supervisão, bug ou programação. Você deve corrigir o erro. Novamente, você certamente não deve ignorar e continuar.

  • Exógenos : você pode esperar esses erros em situações excepcionais, como arquivo não encontrado ou conexão encerrada . Você deve lidar explicitamente com esses erros, e somente estes.

Em todos os casos except: pass, apenas deixará seu programa em um estado desconhecido, onde poderá causar mais danos.

Daniel AA Pelsmaeker
fonte
6

Simplificando, se uma exceção ou erro for lançado, algo está errado. Pode não ser algo muito errado, mas criar, lançar e capturar erros e exceções apenas para o uso de instruções goto não é uma boa idéia, e raramente é feito. 99% das vezes, havia um problema em algum lugar.

Problemas precisam ser resolvidos. Assim como na vida, na programação, se você deixar os problemas em paz e tentar ignorá-los, eles não desaparecerão por conta própria muitas vezes; em vez disso, aumentam e se multiplicam. Para impedir que um problema cresça em você e atinja novamente mais adiante, você 1) elimina-o e limpa a bagunça depois, ou 2) o contém e limpa a bagunça depois.

Ignorar exceções e erros e deixá-los assim é uma boa maneira de experimentar vazamentos de memória, excelentes conexões com o banco de dados, bloqueios desnecessários nas permissões de arquivos, etc.

Em raras ocasiões, o problema é tão minúsculo, trivial e - além de precisar de um bloco de tentativa ... autônomo , que realmente não há bagunça a ser limpa depois. Essas são as únicas ocasiões em que essa prática recomendada não se aplica necessariamente. Na minha experiência, isso geralmente significa que tudo o que o código está fazendo é basicamente mesquinho e perdoável, e algo como tentativas de repetição ou mensagens especiais não valem nem a complexidade nem a manutenção do encadeamento.

Na minha empresa, a regra é quase sempre fazer algo em um bloco de captura e, se você não fizer nada, deve sempre colocar um comentário com uma boa razão para não fazê-lo. Você nunca deve passar ou deixar um bloco de captura vazio quando houver algo a ser feito.

Panzercrisis
fonte
6

Na minha opinião, os erros têm uma razão para aparecer, que parece estúpido, mas é assim que é. Uma boa programação apenas gera erros quando você precisa lidar com eles. Além disso, como li há algum tempo, "a declaração pass é uma declaração que mostra o código será inserida mais tarde"; portanto, se você quiser ter uma declaração exceto vazia, sinta-se à vontade para fazê-lo, mas, para um bom programa, haverá falta uma parte. porque você não lida com as coisas que deveria ter. As exceções aparentes oferecem a chance de corrigir dados de entrada ou alterar sua estrutura de dados para que essas exceções não ocorram novamente (mas na maioria dos casos (exceções de rede, exceções de entrada gerais)) indicam que as próximas partes do programa não serão executadas corretamente. Por exemplo, um NetworkException pode indicar uma conexão de rede interrompida e o programa não pode enviar / receber dados nas próximas etapas do programa.

Mas usar um bloco de aprovação para apenas um bloco de execução é válido, porque você ainda diferencia entre os tipos de exceções; portanto, se você colocar todos os blocos de exceção em um, ele não estará vazio:

try:
    #code here
except Error1:
    #exception handle1

except Error2:
    #exception handle2
#and so on

pode ser reescrito dessa maneira:

try:
    #code here
except BaseException as e:
    if isinstance(e, Error1):
        #exception handle1

    elif isinstance(e, Error2):
        #exception handle2

    ...

    else:
        raise

Portanto, mesmo vários blocos de exceção com instruções de passe podem resultar em código, cuja estrutura lida com tipos especiais de exceções.

Sirac
fonte
4

Todos os comentários apresentados até o momento são válidos. Sempre que possível, você precisa especificar exatamente qual exceção deseja ignorar. Sempre que possível, você precisa analisar o que causou a exceção e ignorar apenas o que pretendia ignorar, e não o resto. Se a exceção faz o aplicativo "travar espetacularmente", seja assim, porque é muito mais importante saber o inesperado que aconteceu quando aconteceu do que ocultar que o problema já ocorreu.

Com tudo isso dito, não tome nenhuma prática de programação como um fator primordial. Isso é estúpido. Sempre há a hora e o local para fazer o bloco ignorar todas as exceções.

Outro exemplo de primordial idiota é o uso do gotooperador. Quando eu estava na escola, nosso professor nos ensinou o gotooperador apenas para mencionar que você nunca deve usá-lo, NUNCA. Não acredite nas pessoas dizendo que o xyz nunca deve ser usado e não pode haver um cenário em que seja útil. Sempre existe.

galets
fonte
1
O caso "goto" é estilístico e é uma questão de opinião, enquanto "exceto: pass" geralmente é errado. Ele pressupõe que, se alguém, por exemplo, "mata -TERM" seu processo naquele momento, deve ignorá-lo. No mínimo, isso é mau comportamento.
Score_Under
1
@Score_Under ainda existem casos em que isso é apropriado para uso. Por exemplo, quando uma função que você está chamando é suplementar, de origem / autor desconhecida, não afeta a funcionalidade principal, mas se as falhas podem causar problemas. Sei que você argumentaria que essas ligações devem ser pesquisadas e analisadas adequadamente, mas na vida real nem sempre é possível.
galets
Ainda assim, se eu quiser finalizar seu processo, kill -9 não deve ser a única opção confiável.
Score_Under
2

Lidar com erros é muito importante na programação. Você precisa mostrar ao usuário o que deu errado. Em muito poucos casos, você pode ignorar os erros. É uma prática de programação muito ruim.

fastcodejava
fonte
2

Como ainda não foi mencionado, é melhor usar o estilo contextlib.suppress:

with suppress(FileNotFoundError):
    os.remove('somefile.tmp')

Observe que, no exemplo fornecido, o estado do programa permanece o mesmo, independentemente da exceção. Ou seja, somefile.tmpsempre se torna inexistente.

Mateen Ulhaq
fonte