I have the following code:
def check_if_number_is_5(x):
try:
#some code
except Exception as e:
#some code
for x in some_list:
#Some code
check_if_number_is_5(x)
#Rest of the code
Basically, I want to move on to the next element in my list if that condition is satisfied and I don't want #Rest of the code to run.
Is there anyway to do this without returning a boolean value and having another conditional statement. I have explored doing this with an exception but the problem is the exception is being caught with by the except block of the function.
The key is the continue statement, to move on to the next iteration, but you need a triggerer, for that, there is 2 ways :
the boolean one
def check_if_number_is_5(x):
try:
# some code
return True
except Exception as e:
# some code
return False
some_list = []
for x in some_list:
# Some code
if check_if_number_is_5(x):
continue
# Rest of the code
the exception one
def check_if_number_is_5(x):
try:
# some code
pass
except Exception as e:
# some code
raise Exception()
some_list = []
for x in some_list:
# Some code
try:
check_if_number_is_5(x)
except:
continue
# Rest of the code
so the function would look like somewhat this:
don't catch error in the function
def check_if_number_is_not_5(x):
if x==5:
return False
return True
In the code call the function and check return value then use the break to breakout of loop.
some_list = []
for x in some_list:
# code
if check_if_number_is_not_5(x):
break
# code
How to catch exception for multiple validation in a single try block ? Is it possible or do I need to use multiple try block for that ? Here is my code :
import sys
def math_func(num1, num2):
return num1*num2
a,b = map(str,sys.stdin.readline().split(' '))
try:
a = int(a)
b = int(b)
print("Result is - ", math_func(a,b), "\n")
except FirstException: # For A
print("A is not an int!")
except SecondException: # For B
print("B is not an int!")
Python believes in explicit Exception handling. If your intention is to only know which line causes the exception then don't go for multiple exception. In your case you don't need separate Exception handlers, since you are not doing any conditional operation based on the specific line raising an exception.
import sys
import traceback
def math_func(num1, num2):
return num1*num2
a,b = map(str, sys.stdin.readline().split(' '))
try:
a = int(a)
b = int(b)
print("Result is - ", math_func(a,b), "\n")
except ValueError:
print(traceback.format_exc())
This will print which line cause the error
You can indeed catch two exceptions in a single block, this can be done like so:
import sys
def mathFunc(No1,No2):
return No1*No2
a,b = map(str,sys.stdin.readline().split(' '))
try:
a = int(a)
b = int(b)
print("Result is - ",mathFunc(a,b),"\n")
except (FirstException, SecondException) as e:
if(isinstance(e, FirstException)):
# put logic for a here
elif(isinstance(e, SecondException)):
# put logic for be here
# ... repeat for more exceptions
You can also simply catch a generic Exception, this is handy for when program excecution must be maintained during runtime, but it is best practice to avoidthis and catch the specific exceptions instead
Hope this helps!
Possibly a duplicate of this?
If you call a function to check exit conditions, can you have it return a break statement? Something like:
def check():
return break
def myLoop:
while myLoop:
check()
Is there anything like this allowed? I know the syntax as written isn't valid.
No, it doesn't work like that unfortunately. You would have to check the return value and then decide to break out of the loop in the caller.
while myLoop:
result = check()
if result == 'oh no':
break
Of course, depending on what you are trying to do, it may just be as simple as:
result = check()
while result != 'oh no':
result = check()
break is a keyword but not an object so it is treated differently by the interpreter, link. Python function can only return objects or the like.
If you want to break out of a loop when deep inside functions, one way is to use an exception:
class BreakException(Exception):
pass
Raise the exception somewhere in a function:
def some_func():
raise BreakException()
And you can break out of a loop like this:
try:
while True:
some_func()
except BreakException:
pass
I do not feel this is good practice, but have seen some language using it, Scala for example link.
def check():
#define your conditions here with if..else statement
return True
def myLoop():
while True:
if check()==True: break
I'm wondering if there's any pythonic or short-form method to achieve the following:
error_response = self.check_conditions(request)
# If we have an error response, return it, otherwise continue as normal.
if error_response:
return error_response
Something like:
(return self.check_conditions(request)) or pass
Alternatively, is it possible for a function to return the calling method, such as:
self.check_conditions(request)
def check_conditions(self, request):
error_response = do_stuff()
if error_response:
return_parent error_response
I get the feeling the second concept is breaking a ton of programming laws to prevent chaos and the apocalypse, just a thought though :)
No, there is no short form for a conditional return.
But, to get to the second part of your question:
There are exceptions in Python. You can write something like this:
class MyErrorResponse(Exception): pass
class MyClass:
...
def check_conditions(self, request):
error_response = do_stuff()
if error_response:
raise MyErrorResponse(error_response)
def do_the_main_stuff():
try:
self.check_conditions()
...
except MyErrorResponse as e:
return e.args[0]
That depends a lot on what check_conditions does under the hood. It's likely that you can move error handling down a level of abstraction and handle things directly:
Compare:
error = False
def foo(request):
global error
try:
result = do_something_with(request)
except SomeWellDefinedError:
error = True
def check_conditions(request):
foo(request)
return error
def main():
error_response = check_conditions(some_request)
if error_response:
# freak out!
With
def foo(request):
try:
result = do_something_with(request)
except SomeWellDefinedError:
# you can try to handle the error here, or...
raise # uh oh!
def main():
try:
foo(some_request)
except SomeWellDefinedError:
# handle the error here, instead!
I am defining a context manager class and I would like to be able to skip the block of code without raising an exception if certain conditions are met during instantiation. For example,
class My_Context(object):
def __init__(self,mode=0):
"""
if mode = 0, proceed as normal
if mode = 1, do not execute block
"""
self.mode=mode
def __enter__(self):
if self.mode==1:
print 'Exiting...'
CODE TO EXIT PREMATURELY
def __exit__(self, type, value, traceback):
print 'Exiting...'
with My_Context(mode=1):
print 'Executing block of codes...'
According to PEP-343, a with statement translates from:
with EXPR as VAR:
BLOCK
to:
mgr = (EXPR)
exit = type(mgr).__exit__ # Not calling it yet
value = type(mgr).__enter__(mgr)
exc = True
try:
try:
VAR = value # Only if "as VAR" is present
BLOCK
except:
# The exceptional case is handled here
exc = False
if not exit(mgr, *sys.exc_info()):
raise
# The exception is swallowed if exit() returns true
finally:
# The normal and non-local-goto cases are handled here
if exc:
exit(mgr, None, None, None)
As you can see, there is nothing obvious you can do from the call to the __enter__() method of the context manager that can skip the body ("BLOCK") of the with statement.
People have done Python-implementation-specific things, such as manipulating the call stack inside of the __enter__(), in projects such as withhacks. I recall Alex Martelli posting a very interesting with-hack on stackoverflow a year or two back (don't recall enough of the post off-hand to search and find it).
But the simple answer to your question / problem is that you cannot do what you're asking, skipping the body of the with statement, without resorting to so-called "deep magic" (which is not necessarily portable between python implementations). With deep magic, you might be able to do it, but I recommend only doing such things as an exercise in seeing how it might be done, never in "production code".
If you want an ad-hoc solution that uses the ideas from withhacks (specifically from AnonymousBlocksInPython), this will work:
import sys
import inspect
class My_Context(object):
def __init__(self,mode=0):
"""
if mode = 0, proceed as normal
if mode = 1, do not execute block
"""
self.mode=mode
def __enter__(self):
if self.mode==1:
print 'Met block-skipping criterion ...'
# Do some magic
sys.settrace(lambda *args, **keys: None)
frame = inspect.currentframe(1)
frame.f_trace = self.trace
def trace(self, frame, event, arg):
raise
def __exit__(self, type, value, traceback):
print 'Exiting context ...'
return True
Compare the following:
with My_Context(mode=1):
print 'Executing block of code ...'
with
with My_Context(mode=0):
print 'Executing block of code ... '
A python 3 update to the hack mentioned by other answers from
withhacks (specifically from AnonymousBlocksInPython):
class SkipWithBlock(Exception):
pass
class SkipContextManager:
def __init__(self, skip):
self.skip = skip
def __enter__(self):
if self.skip:
sys.settrace(lambda *args, **keys: None)
frame = sys._getframe(1)
frame.f_trace = self.trace
def trace(self, frame, event, arg):
raise SkipWithBlock()
def __exit__(self, type, value, traceback):
if type is None:
return # No exception
if issubclass(type, SkipWithBlock):
return True # Suppress special SkipWithBlock exception
with SkipContextManager(skip=True):
print('In the with block') # Won't be called
print('Out of the with block')
As mentioned before by joe, this is a hack that should be avoided:
The method trace() is called when a new local scope is entered, i.e. right when the code in your with block begins. When an exception is raised here it gets caught by exit(). That's how this hack works. I should add that this is very much a hack and should not be relied upon. The magical sys.settrace() is not actually a part of the language definition, it just happens to be in CPython. Also, debuggers rely on sys.settrace() to do their job, so using it yourself interferes with that. There are many reasons why you shouldn't use this code. Just FYI.
Based on #Peter's answer, here's a version that uses no string manipulations but should work the same way otherwise:
from contextlib import contextmanager
#contextmanager
def skippable_context(skip):
skip_error = ValueError("Skipping Context Exception")
prev_entered = getattr(skippable_context, "entered", False)
skippable_context.entered = False
def command():
skippable_context.entered = True
if skip:
raise skip_error
try:
yield command
except ValueError as err:
if err != skip_error:
raise
finally:
assert skippable_context.entered, "Need to call returned command at least once."
skippable_context.entered = prev_entered
print("=== Running with skip disabled ===")
with skippable_context(skip=False) as command:
command()
print("Entering this block")
print("... Done")
print("=== Running with skip enabled ===")
with skippable_context(skip=True) as command:
command()
raise NotImplementedError("... But this will never be printed")
print("... Done")
What you're trying to do isn't possible, unfortunately. If __enter__ raises an exception, that exception is raised at the with statement (__exit__ isn't called). If it doesn't raise an exception, then the return value is fed to the block and the block executes.
Closest thing I could think of is a flag checked explicitly by the block:
class Break(Exception):
pass
class MyContext(object):
def __init__(self,mode=0):
"""
if mode = 0, proceed as normal
if mode = 1, do not execute block
"""
self.mode=mode
def __enter__(self):
if self.mode==1:
print 'Exiting...'
return self.mode
def __exit__(self, type, value, traceback):
if type is None:
print 'Normal exit...'
return # no exception
if issubclass(type, Break):
return True # suppress exception
print 'Exception exit...'
with MyContext(mode=1) as skip:
if skip: raise Break()
print 'Executing block of codes...'
This also lets you raise Break() in the middle of a with block to simulate a normal break statement.
Context managers are not the right construct for this. You're asking for the body to be executed n times, in this case zero or one. If you look at the general case, n where n >= 0, you end up with a for loop:
def do_squares(n):
for i in range(n):
yield i ** 2
for x in do_squares(3):
print('square: ', x)
for x in do_squares(0):
print('this does not print')
In your case, which is more special purpose, and doesn't require binding to the loop variable:
def should_execute(mode=0):
if mode == 0:
yield
for _ in should_execute(0):
print('this prints')
for _ in should_execute(1):
print('this does not')
Another slightly hacky option makes use of exec. This is handy because it can be modified to do arbitrary things (e.g. memoization of context-blocks):
from contextlib import contextmanager
#contextmanager
def skippable_context_exec(skip):
SKIP_STRING = 'Skipping Context Exception'
old_value = skippable_context_exec.is_execed if hasattr(skippable_context_exec, 'is_execed') else False
skippable_context_exec.is_execed=False
command = "skippable_context_exec.is_execed=True; "+("raise ValueError('{}')".format(SKIP_STRING) if skip else '')
try:
yield command
except ValueError as err:
if SKIP_STRING not in str(err):
raise
finally:
assert skippable_context_exec.is_execed, "You never called exec in your context block."
skippable_context_exec.is_execed = old_value
print('=== Running with skip disabled ===')
with skippable_context_exec(skip=False) as command:
exec(command)
print('Entering this block')
print('... Done')
print('=== Running with skip enabled ===')
with skippable_context_exec(skip=True) as command:
exec(command)
print('... But this will never be printed')
print('... Done')
Would be nice to have something that gets rid of the exec without weird side effects, so if you can think of a way I'm all ears. The current lead answer to this question appears to do that but has some issues.