Existe uma maneira em python de transformar um try / except em uma única linha?
algo como...
b = 'some variable'
a = c | b #try statement goes here
Onde bé uma variável declarada e cnão é ... então clançaria um erro e ase tornaria b...
Respostas:
Não há como compactar um try/ exceptblock em uma única linha no Python.
Além disso, é uma coisa ruim não saber se uma variável existe no Python, como você faria em algumas outras linguagens dinâmicas. A maneira mais segura (e o estilo predominante) é definir todas as variáveis para algo. Se eles não forem definidos, defina-os como Noneprimeiro (ou 0ou ''ou algo se for mais aplicável).
Se você fazer atribuir todos os nomes que você está interessado em primeiro lugar, você tem opções.
A melhor opção é uma instrução if.
c = None
b = [1, 2]
if c is None:
a = b
else:
a = c
A opção de uma linha é uma expressão condicional.
c = None
b = [1, 2]
a = c if c is not None else b
Algumas pessoas abusam do comportamento de curto-circuito de orpara fazer isso. Isso está sujeito a erros, então nunca o uso.
c = None
b = [1, 2]
a = c or b
Considere o seguinte caso:
c = []
b = [1, 2]
a = c or b
Nesse caso, aprovavelmente deveria ser [], mas é [1, 2]porque []é falso em um contexto booleano. Como há muitos valores que podem ser falsos, não uso esse ortruque. (Este é o mesmo problema que as pessoas enfrentam quando dizem if foo:quando querem dizer if foo is not None:).
try/ except. Felizmente, as linhas são baratas, então a solução de 4 linhas deve funcionar para você. ;-)
getse você não quiser uma exceção. Use em seu filterlugar.
Isso é terrivelmente hackeado, mas usei-o no prompt quando queria escrever uma sequência de ações para depuração:
exec "try: some_problematic_thing()\nexcept: problem=sys.exc_info()"
print "The problem is %s" % problem[1]
Na maior parte do tempo, não estou nem um pouco incomodado com a restrição de não tentar uma única linha, mas quando estou apenas experimentando e quero que o readline lembre um pedaço inteiro de código de uma vez no interpretador interativo, que eu possa ajustá-lo de alguma forma, este pequeno truque é útil.
Para o propósito real que está tentando realizar, você pode tentar locals().get('c', b); idealmente, seria melhor usar um dicionário real em vez do contexto local, ou apenas atribuir c a None antes de executar qualquer opção que possa ou não definir.
problem[0]devolver o que essa função retorna?
Em python3, você pode usar contextlib.suppress :
from contextlib import suppress
d = {}
with suppress(KeyError): d['foo']
Outra maneira é definir um gerenciador de contexto:
class trialContextManager:
def __enter__(self): pass
def __exit__(self, *args): return True
trial = trialContextManager()
Em seguida, use a withinstrução para ignorar os erros em uma única linha:
>>> with trial: a = 5 # will be executed normally
>>> with trial: a = 1 / 0 # will be not executed and no exception is raised
>>> print a
5
Nenhuma exceção será levantada no caso de um erro de tempo de execução. É como um try:sem o except:.
Versão da resposta poke53280 com exceções esperadas limitadas.
def try_or(func, default=None, expected_exc=(Exception,)):
try:
return func()
except expected_exc:
return default
e poderia ser usado como
In [2]: try_or(lambda: 1/2, default=float('nan'))
Out[2]: 0.5
In [3]: try_or(lambda: 1/0, default=float('nan'), expected_exc=(ArithmeticError,))
Out[3]: nan
In [4]: try_or(lambda: "1"/0, default=float('nan'), expected_exc=(ArithmeticError,))
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
[your traceback here]
TypeError: unsupported operand type(s) for /: 'str' and 'int'
In [5]: try_or(lambda: "1"/0, default=float('nan'), expected_exc=(ArithmeticError, TypeError))
Out[5]: nan
parse_float = lambda x, y=exec("def f(s):\n try:\n return float(s)\n except: return None"): f(x)
Sempre existe uma solução.
O problema é que, na verdade, é uma consulta django model.objects.get que estou tentando testar. o .get retorna um erro se nenhum dado for encontrado ... ele não retorna Nenhum (o que me irrita)
Use algo assim:
print("result:", try_or(lambda: model.objects.get(), '<n/a>'))
Onde try_or é uma função de utilidade definida por você:
def try_or(fn, default):
try:
return fn()
except:
return default
Opcionalmente, você pode restringir os tipos de exceção aceitou NameError, AttributeErroretc.
Que tal usar duas linhas. esta ok?
>>> try: a = 3; b= 0; c = a / b
... except : print('not possible'); print('zero division error')
...
not possible
zero division error
Você pode fazê-lo acessando o dict namespace usando vars(), locals()ou globals(), consoante o que for mais adequado para sua situação.
>>> b = 'some variable'
>>> a = vars().get('c', b)
Funciona em Python3, inspirado em Walter Mundt
exec("try:some_problematic_thing()\nexcept:pass")
Para linhas múltiplas em uma linha
exec("try:\n\tprint('FirstLineOk')\n\tsome_problematic_thing()\n\tprint('ThirdLineNotTriggerd')\nexcept:pass")
Ps: Exec não é seguro para usar em dados que você não tem controle.
se você realmente precisa gerenciar exceções:
(modificado da resposta de poke53280)
>>> def try_or(fn, exceptions: dict = {}):
try:
return fn()
except Exception as ei:
for e in ei.__class__.__mro__[:-1]:
if e in exceptions: return exceptions[e]()
else:
raise
>>> def context():
return 1 + None
>>> try_or( context, {TypeError: lambda: print('TypeError exception')} )
TypeError exception
>>>
observe que se a exceção não for suportada, ela aumentará conforme o esperado:
>>> try_or( context, {ValueError: lambda: print('ValueError exception')} )
Traceback (most recent call last):
File "<pyshell#57>", line 1, in <module>
try_or( context, {ValueError: lambda: print('ValueError exception')} )
File "<pyshell#38>", line 3, in try_or
return fn()
File "<pyshell#56>", line 2, in context
return 1 + None
TypeError: unsupported operand type(s) for +: 'int' and 'NoneType'
>>>
também se Exceptionfor fornecido, ele corresponderá a qualquer coisa abaixo.
( BaseExceptioné mais alto, então não vai corresponder)
>>> try_or( context, {Exception: lambda: print('exception')} )
exception
Aqui está uma versão mais simples da resposta fornecida por @surendra_ben
a = "apple"
try: a.something_that_definitely_doesnt_exist
except: print("nope")
...
nope
Use a withsintaxe em uma linha:
class OK(): __init__ = lambda self, *isok: setattr(self, 'isok', isok); __enter__ = lambda self: None; __exit__ = lambda self, exc_type, exc_value, traceback: (True if not self.isok or issubclass(exc_type, self.isok) else None) if exc_type else None
Ignore quaisquer erros:
with OK(): 1/0
Ignore os erros especificados:
with OK(ZeroDivisionError, NameError): 1/0