How should I put try/except in a single line?

Python

Python Problem Overview


Is there a way in python to turn a try/except into a single line?

something like...

b = 'some variable'
a = c | b #try statement goes here

Where b is a declared variable and c is not... so c would throw an error and a would become b...

Python Solutions


Solution 1 - Python

In python3 you can use contextlib.suppress:

from contextlib import suppress

d = {}
with suppress(KeyError): d['foo']

Solution 2 - Python

This is terribly hackish, but I've used it at the prompt when I wanted to write up a sequence of actions for debugging:

exec "try: some_problematic_thing()\nexcept: problem=sys.exc_info()"
print "The problem is %s" % problem[1]

For the most part, I'm not at all bothered by the no-single-line-try-except restriction, but when I'm just experimenting and I want readline to recall a whole chunk of code at once in the interactive interpreter so that I can adjust it somehow, this little trick comes in handy.

For the actual purpose you are trying to accomplish, you might try locals().get('c', b); ideally it would be better to use a real dictionary instead of the local context, or just assign c to None before running whatever may-or-may-not set it.

Solution 3 - Python

There is no way to compress a try/except block onto a single line in Python.

Also, it is a bad thing not to know whether a variable exists in Python, like you would in some other dynamic languages. The safer way (and the prevailing style) is to set all variables to something. If they might not get set, set them to None first (or 0 or '' or something if it is more applicable.)


If you do assign all the names you are interested in first, you do have options.

  • The best option is an if statement.

     c = None
     b = [1, 2]
    
     if c is None:
         a = b
     else:
         a = c
    
  • The one-liner option is a conditional expression.

     c = None
     b = [1, 2]
     a = c if c is not None else b
    
  • Some people abuse the short-circuiting behavior of or to do this. This is error prone, so I never use it.

     c = None
     b = [1, 2]
     a = c or b
    

    Consider the following case:

     c = []
     b = [1, 2]
     a = c or b
    

    In this case, a probably should be [], but it is [1, 2] because [] is false in a boolean context. Because there are lots of values that can be false, I don't use the or trick. (This is the same problem people run into when they say if foo: when they mean if foo is not None:.)

Solution 4 - Python

Version of poke53280 answer with limited expected exceptions.

def try_or(func, default=None, expected_exc=(Exception,)):
    try:
        return func()
    except expected_exc:
        return default

and it could be used as

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

Solution 5 - Python

Another way is to define a context manager:

class trialContextManager:
    def __enter__(self): pass
    def __exit__(self, *args): return True
trial = trialContextManager()

Then use the with statement to ignore errors in one single line:

>>> 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

No exception will be raised in case of a runtime error. It's like a try: without the except:.

Solution 6 - Python

> The problem is that its actually a django model.objects.get query i am trying to test. the .get returns an error if no data is found... it doesn't return None (which annoys me)

Use something like this:

print("result:", try_or(lambda: model.objects.get(), '<n/a>'))

Where try_or is an utility function defined by you:

def try_or(fn, default):
	try:
		return fn()
	except:
		return default

Optionally you can restrict the accepted exception types to NameError, AttributeError, etc.

Solution 7 - Python

parse_float = lambda x, y=exec("def f(s):\n try:\n  return float(s)\n except:  return None"): f(x)

There is always a solution.

Solution 8 - Python

Works on Python3, inspired by Walter Mundt

exec("try:some_problematic_thing()\nexcept:pass")

For mulitiples lines into one line

exec("try:\n\tprint('FirstLineOk')\n\tsome_problematic_thing()\n\tprint('ThirdLineNotTriggerd')\nexcept:pass")

Ps: Exec is unsafe to use on data you don't have control over.

Solution 9 - Python

How about using two lines. is it ok ?

>>> try: a = 3; b= 0; c = a / b
... except : print('not possible'); print('zero division error')
...
not possible
zero division error

Solution 10 - Python

You can do it by accessing the namespace dict using vars(), locals(), or globals(), whichever is most appropriate for your situation.

>>> b = 'some variable'
>>> a = vars().get('c', b)

Solution 11 - Python

You mentioned that you're using django. If it makes sense for what you're doing you might want to use:

my_instance, created = MyModel.objects.get_or_create()

created will be True or False. Maybe this will help you.

Solution 12 - Python

Here is a simpler version of the answer provided by @surendra_ben

a = "apple"
ā€‹
try: a.something_that_definitely_doesnt_exist
except: print("nope")

...

nope

Solution 13 - Python

Use with syntax in one line:

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 any errors:

with OK(): 1/0

Ignore specified errors:

with OK(ZeroDivisionError, NameError): 1/0

Solution 14 - Python

if you need to actually manage exceptions:
(modified from poke53280's answer)

>>> 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
>>> 

note that if the exception is not supported, it will raise as expected:

>>> 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'
>>> 

also if Exception is given, it will match anything below.
(BaseException is higher, so it will not match)

>>> try_or( context, {Exception: lambda: print('exception')} )
exception

Solution 15 - Python

The two-liner version doesn't work me. I use VSCode on ubuntu 20.04 x64.It only works if I move the exception statements to a new line. The try can remain a single line. So minimally I would need 3 lines. Don't know if this is a bug or feature.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionBrantView Question on Stackoverflow
Solution 1 - Pythondset0xView Answer on Stackoverflow
Solution 2 - PythonWalter MundtView Answer on Stackoverflow
Solution 3 - PythonMike GrahamView Answer on Stackoverflow
Solution 4 - PythonPavlo PravdiukovView Answer on Stackoverflow
Solution 5 - PythonbitagorasView Answer on Stackoverflow
Solution 6 - Pythonpoke53280View Answer on Stackoverflow
Solution 7 - Pythonuser6035995View Answer on Stackoverflow
Solution 8 - PythonPunnerudView Answer on Stackoverflow
Solution 9 - Pythonsurendra benView Answer on Stackoverflow
Solution 10 - PythonjcdyerView Answer on Stackoverflow
Solution 11 - PythonblokeleyView Answer on Stackoverflow
Solution 12 - PythonKalanosView Answer on Stackoverflow
Solution 13 - PythonSakuyaView Answer on Stackoverflow
Solution 14 - PythonTcllView Answer on Stackoverflow
Solution 15 - Pythonmoe fearView Answer on Stackoverflow