Continue the loop after an exception used in python - python

I am trying to run a loop with try and exception in python. Initially it runs for p=0 and j=1,2 then falls into the exception. the problem is that then I would like the loop to continue for p=1 and j=1,2,2....can you help me thanks! I tried something like this but it's not working
for p in range(1):
for j in range(23):
try:
b = response_json[0]['countries'][p]['names'][j]['values']
except:
break

Overall, using exceptions to handle normal flow is a bad pattern. Exceptions are for, well, exceptions.
Looks like you are trying to iterate over an array with missing keys. Instead of trying each key, you could iterate over the collection directly
country_data = response_json[0]['countries']
for country in country_data:
for name in country['names']:
b = name['values']

Replace break with continue (or pass).
break jumps to the end of the loop, continue jumps back to the start to continue with the next iteration. pass is a no-op used when a block is empty.

Related

How to handle Exception Handling in Python

If a list_goods[i] item does not exist in all_keys variable which is a keys of dictionary, I am supposed to catch an exception and adds the item followed by a value "none" to a new dictionary variable. However my codes does not work. Appreciate it if someone could point me in the right direction, Thanks!P.s I am not supposed to use If else in this assignment.
List and Dictionary in main method
dict_q2 = {"vinegar": [120.0, 100], "ketchup": [950, 1000],"apples": [850,1100],"oranges": [1050, 0]
}
list_q2 = ["ketchup","oranges","pear"]
Function to take in the above list and dict
def compute_unit_prices(dict_goods, list_goods):
#dict variable with name of good as key and unit prices as values.
return_dict = {}
all_keys = dict_goods.keys()
i =0
#Try block
try:
while (list_goods[i] in all_keys):
goods_name = list_goods[i]
storage = dict_goods[goods_name]
results = storage[0] / storage[1]
return_dict.update({goods_name:results})
i = i+1
except KeyError as e:
return_dict.update({goods_name:"none"})
# If zeroDivisionError is encountered, this block of code is used
except ZeroDivisionError as e:
results = -1
return_dict.update({goods_name:results})
# This block of code works if errors other than the above two occurs
except:
return_dict = {}
finally:
print(return_dict)
You was told to make sure that your code throws exceptions (run-time error) and catches them with try. And yet your code avoids iterating over the missing dictionary keys due to a peculiar while loop condition. Which is wrong on many levels. Better refactor to for i in range(len(list_goods)) loop. Otherwise while exits the loop on the first key out of the dictionary, so the KeyError exception does not have a single chance to occur. Also you risk i running out of the boundaries.
Move exception handling inside the loop. Otherwise the first exception will terminate the loop, and you want to process each and every element of the list.
Remove finally. You do not need it any more. Just print the result outside of the loop.
PS. Actually for good in list_goods is more pythonic, use that if you comfortable enough with python loop, but you will need to do more changes inside the loop.

Excepting Breaks In Python

I know this sounds crazy, but I couldn't find a solution. I was trying to except the break statement inside a loop using try-except.
Here is what I tried:
for i in range(10):
try:
print(i)
break
except break:
print("Break excepted")
pass
But Python3.x returns the Error:
SyntaxError: invalid syntax
So how do I except the break statement?
Ps: I know I could have the print statement before the break and avoid break statement, but if case I want to, how would I?
You cannot add a break exception because break is not an exception.
Also with the flow of operations, if the loop cannot run, your print(i) will not get executed and so the code will not reach the break statement anyways.
If you're trying to find at which loop the code breaks, your code should work without needing the break too.
for i in range(10):
try #try running the loop
print(i)
except: #if the loop breaks
print("Break excepted") #print this and continue loop
Because the try is inside the for-loop; when there is an exception, the loop will still continue with the next iteration.
You can of course, also catch more specific exceptions like except IndexError or except KeyError. The full list of exceptions is available in the documentation.

Catching exceptions by generators inside `for` loop

I want to write decorator for generators that will catch all exceptions inside for loop, process them and continues loop.
I wrote this decorator (for Django 1.5 ORM):
def savepoint_loop(generator, uniq_error_in='_uniq'):
with commit_on_success():
sp = savepoint()
for obj in generator:
try:
yield obj
except DatabaseError as e:
if uniq_error_in not in e.args[0]:
raise
savepoint_rollback(sp)
yield None
else:
savepoint_commit(sp)
sp = savepoint()
And I use it like:
loop = savepoint_loop(offer.booking_data.iteritems())
for provider_name, booking_data in loop:
try:
BookingData.objects.create(
offer=pnr_offer, provider=provider_name, **booking_data)
except Exception as e:
loop.throw(e)
But it doesn't looks Pythonic. It allows me to make my code DRY, but looks confusing.
Is there any way to make it cleaner? At least I want to remove try-except-throw construction or change it to with operator.
Ideally it should look like this:
for provider_name, booking_data in savepoint_loop(
offer.booking_data.iteritems()):
BookingData.objects.create(
offer=pnr_offer, provider=provider_name, **booking_data)
import contextlib
#contextlib.contextmanager
def error_processor(uniq_error_in='_uniq'):
sp = savepoint()
try:
yield
except DatabaseError as e:
if uniq_error_in not in e.args[0]:
raise
savepoint_rollback(sp)
else:
savepoint_commit(sp)
This is a context manager that should do the job your coroutine does, but hopefully in a more understandable manner. You'd use it as follows:
with commit_on_success():
for provider_name, booking_data in offer.booking_data.iteritems():
with error_processor():
BookingData.objects.create(
offer=pnr_offer, provider=provider_name, **booking_data)
I couldn't fit the commit_on_success into the context manager, as the commit_on_success needs to go around the for loop, but the error handling needs to go inside the loop.
Hm... I think I see why this isn't straightforward. Any loop over an iterable basically comprises the following steps:
initialization
check termination condition
get next element
execute body of loop
... repeat steps 2-4 until the termination condition is satisfied
In a Python for loop, steps 2 and 3 are encapsulated in the for x in y statement. But it sounds like you want to use the same try...except to catch exceptions in steps 3 and 4. So it would appear that this will require you to "decompose" the for statement, i.e. implement it manually using a while loop instead.
iterable = offer.booking_data.iteritems() # step 2
try:
while True:
try:
provider_name, booking_data = iterable.next() # step 3
BookingData.objects.create(...) # step 4
except:
except StopIteration:
pass
I'm sure you would agree that this is stylistically worse than the code sample you already have in your question, with try...except inside the for loop. Sure, it's conceivable that it might be useful, if you really need steps 3 and 4 to be inside the same try block, but I would imagine cases like that are rare.
It's also possible there is some sneaky way to construct a generator that does what you want, but I can't think of one.

What's the difference between pass and continue in python [duplicate]

This question already has answers here:
Is there a difference between "pass" and "continue" in a for loop in Python?
(13 answers)
Closed 5 years ago.
My test shows that both pass and continue can be used equivalently to construct a empty for-loop for test purpose. Are there any difference between them?
The pass keyword is a "no-operation" keyword. It does exactly nothing. It's often used as a placeholder for code which will be added later:
if response == "yes":
pass # add "yes" code later.
The continue keyword, on the other hand, is used to restart a loop at the control point, such as with:
for i in range(10):
if i % 2 == 0:
continue
print(i)
That loop will only output the odd numbers since continue returns to the loop control statement (for) for iterations where i is even.
Contrast that with the exact same code, but using pass in place of continue:
for i in range(10):
if i % 2 == 0:
pass
print(i)
That loop prints all the numbers in the range, since pass does not return to the loop control statement for even (or any) values of i. It simply drops through to the print statement.
In terms of an empty for loop, you're correct that they're functionally identical. You can use either of:
for i in range(10):
pass
for i in range(10):
continue
pass does nothing (no operation), while continue make control flow to continue to next cycle of the loop.
If the loop contains only a single statement, a pass or continue won't make any difference. But if there are multiple statements, then it matters:
for item in my_list:
pass
print(item) #This will be executed
for item in my_list:
continue
print(item) #won't be executed
Basically, the pass statement do nothing, while the continue statement will restart the loop.
But in your case:
for item in my_list:
pass
#Since there's nothing after pass, the loop is finished.
for item in my_list:
continue
#You're restarting the loop
There difference is not very visible.
Hope this helps!
continue means "skip to the end of the loop body". If it's a while loop, the loop continues on to the loop test; if it's a for loop, the loop continues on to the next element of whatever it's iterating over.
pass does absolutely nothing. It exists because you have to have something in the body of an empty block statement, and pass is more readable than executing 1 or None as a statement for that purpose.
This will lead to an infinite loop if you use continue:
i = 0
while i<1:
continue
i = i + 1
print i
because continue only goes to the next iteration. But pass will work for this case.
pass and continue both work, but may create infinite loops.
For example, the following code will create infinite loop.
i = 0
while i<100:
continue # replacing continue with pass still creates an infinite loop.
If you want to avoid this (perhaps you intend to modify i withe loop, but you haven't written the code yet), use break.

syntaxError: 'continue' not properly in loop

I have been struggling with this error for a while now and there seems to be different opinions regarding why the interpreter complains about the 'continue'. So I would like to provide the erroneous code below.
import tweepy
import time
def writeHandlesToFile():
file = open("dataFile.txt","w")
try:
list = tweepy.Cursor(tweepy.api.followers,screen_name='someHandle',).items(100000)
print "cursor executed"
for item in list:
file.write(item.screen_name+"\n")
except tweepy.error.TweepError as e:
print "In the except method"
print e
time.sleep(3600)
continue
The reason I am particular on including the continue at the end is because I would like for the program to restart execution at the top from where it left off after the sleep in order to preserve the program state. I need the sleep in order to abide by the twitter api rate limits wherein the api only allows you to make a certain number of requests every hour.
So anyone who might see my mistake naive or otherwise please do point it out or please provide me with an alternative implementation without the use of the continue statement.
BTW I do not have tabs and spaces mixed as was suggested in another post.
Thank you for your help in advance.
continue is only allowed within a for or while loop. You can easily restructure your function to loop until a valid request.
def writeHandlesToFile():
while True:
with open("dataFile.txt","w") as f:
try:
lst = tweepy.Cursor(tweepy.api.followers,screen_name='someHandle',).items(100000)
print "cursor executed"
for item in lst:
f.write(item.screen_name+"\n")
break
except tweepy.error.TweepError as e:
print "In the except method"
print e
time.sleep(3600)
The problem might be in the way you are using continue
continue may only occur syntactically nested in a for or while loop,
but not nested in a function or class definition or finally statement
within that loop.6.1It continues with the next cycle of the nearest
enclosing loop.

Categories

Resources