Stopiteration identfying the iterable object - python

I have 2 generator and using the next method & while loop to process thru it as below,
code
while end_of_loop = 'n':
try:
table1_row = next(table1_generator)
table2_row = next(table2_generator)
except StopIteration:
end_of_loop = 'y'
How do I identify which iterator object has no rows?
Im trying to compare 2 tables and each table rows are in generator objects.
def _compare(self):
end_of_table = 'N'
try:
while end_of_table =='N':
try:
if self.table1_key == self.table2_key:
print 'same key'
self.table1_row = next(self.table1_generator)
self._convert_table1_key_fields()
self.table2_row = next(self.table2_generator)
self._convert_table2_key_fields()
elif self.table1_key > self.table2_key:
self.table2_row = next(self.table1_generator)
self._convert_table2_key_fields()
elif self.table1_key < self.table2_key:
self.table1_row = next(self.table2_generator)
self._convert_table1_key_fields()
except StopIteration as e:
print e.args
print 'IterError'
end_of_table = 'y'
except StopIteration:
print 'Next Iteration'

You can provide a second "sentinel" value to next:
sentinel = object()
while end_of_loop = 'n':
table1_row = next(table1_generator,sentinel)
table2_row = next(table2_generator,sentinel)
#I don't account for the case where they could be exhausted at
#the same time. It's easy to add that if it matters though.
if table1_row is sentinel:
print "table1_generator gave up first"
#"break" might be more appropriate ...
#(Unless there more to the loop than this.)
end_of_loop = 'y'
elif table2_row is sentinel:
print "table2_generator gave up first"
end_of_loop = 'y'

You didn't provide details about the context or what you're actually trying to do, but it sounds like itertools.izip_longest might be useful in your case (and more pythonic). You can fill with Nones or another value which is suitable.

I can't think of a use case for this (care to share?), but I'd try wrapping next into my own function:
def mynext(it):
try:
return next(it)
except StopIteration:
raise StopIteration(it)
and then, for example,
a = iter([1,2,3,4,5])
b = iter([4,5,6,7])
try:
while True:
print mynext(a)
print mynext(b)
except StopIteration as e:
if e.args[0] == a: print 'a ended'
if e.args[0] == b: print 'b ended'

Related

How to handle error in a for loop (python) and continue execution

I m trying to get my script to still print action 2 "print (list1[3])" and skip action 1 "print (list1[9])" if it can not execute it. I aplozise in advnace if my question is not clear enough I m trying to do my best to explain the issue. I m a beginner.
list1 = ['a','b','c','d','f']
try:
for i in list1:
#action 1
print (list1[9])
#action 2
print (list1[3])
break
except:
pass
Try this cleaner way
l = ['a','b','c','d','f']
# execute the function in try-except
def try_to_do(fun, index):
try:
fun(l[index])
except:
pass
for j in l:
try_to_do(print, 11)
try_to_do(print, 1)
print('Done')
Just put a try for each action instead of both actions together, like this
list1 = ['a','b','c','d','f']
for i in list1:
try:
#action 1
print (list1[9])
except IndexError:
pass
try:
#action 2
print (list1[3])
except IndexError:
pass
break
Use try except inside the loop
list1 = ['a','b','c','d','f']
for i in list1:
try:
#action 1
print (list1[9])
except:
print(e.with_traceback())
try:
#action 2
print (list1[3])
except Exception as e:
print(e.with_traceback())

Pythonic way to validate user input

Is there any pythonic way to deal with wrong user input? I'm creating a module to help people work with files, and I have functions like rename, move, basepath, etc. Example:
def move(file_path):
# do something and return
I would like to know how to handle exceptions (i.e. if I should wrap my code in a try-except block);
def move(file_path):
try:
# do something and return
except Exception as error:
# return error
If I should use the try-except, I would like to know how I should return from it. I have a background in functional programming, so I was thinking like this:
def move(file_path):
try:
# do something
return (True, something...)
except Exception as error:
return (False, error)
Other example:
def execute_query(database_cursor, query, fetch):
if type(database_cursor) != "":
return (1, "database_cursor isn't a valid database cursor")
cursor.execute(query)
if fetch == "*":
return self.cursor.fetchall()
yield self.cursor.fetchone()
In this case, I'm worried about the user sending input that is not a database.
Is there any convention for this functionality?
Thanks!
Update
How i'm doing:
from sys import exit
def testing_something(a, b, c):
try:
return 0, a + b + c
except Exception, error:
return 1, error
error, result = testing_something(1, 2, 3)
if error:
print error # raise error or treat.
sys.exit(error)
I think is very clever to do like this, now i can decide to raise it or to treat it.
In the past, I've used something like the following to ensure that a certain user input was "valid" in the sense that it was contained within a list or something. This was useful for validating manual file input for loading data into memory.
def validate_choice(selection, choices):
while selection not in choices:
selection = input("'%s' is not a valid entry. Try again: " % selection)
print("'%s' works! Returning..." % selection)
return selection
result1 = validate_choice('foo', ['foo', 'bar', 'baz'])
result2 = validate_choice('boogers', ['foo', 'bar', 'baz'])
If you're trying to coerce something of one type to another type, here's another example which coerces the user to enter either A) an integer or B) a number that can be coerced to an integer:
def str_to_int_validation(num):
parsed = False
while not parsed:
try:
num = input("Enter an integer: ")
num = int(num)
parsed = True
except ValueError:
print("'%s' is not an integer. Try again.")
return num
Hope that helps!
This you may consider Pythonic if you want, but it is nothing really but a hacky bit of code:
import os
import shutil
class MoveError(Exception): pass
def move (patha, pathb):
# Some checks
if not os.path.exists(patha):
return MoveError("'%s' does not exist!" % patha)
if os.path.exists(pathb):
return MoveError("'%s' already exists! I will not overwrite it!" % pathb)
print "Moving '%s' to '%s'..." % (patha, pathb)
try: shutil.move(patha, pathb)
except Exception, e:
return MoveError("Whoops, something nasty happened! Error is:\n%s" % str(e))
return "%i bytes moved" % os.path.getsize(pathb)
def help ():
print "This is some help!"
def quit ():
global running
print "Quitting!"
running = 0
commands = {"mv": move, "move": move, "help": help, "?": help, "q": quit, "quit": quit}
running = 1
while running:
inp = raw_input("--> ").split()
if not inp: continue
try: cmd = commands[inp[0]]
except:
print "Invalid command '%s'" % inp[0]
continue
result = cmd(*inp[1:])
if isinstance(result, Exception):
print "Error occurred!"
else: print "Done!"
if result is not None:
print result
Getting the command from commands dictionary could have also been:
cmd = commands.get(inp[0], None)
if not cmd: print "Command doesn't exist!"
or unefficient way:
if inp[0]not in commands:
print "No such command"
else: cmd = commands[inp[0]]
Now, we can start arguing over which of the three is more Pythonic. And that's just for this part of code.
But, it is dead true that returning exceptions, although it may be tempting is something to be done rarely. Usually only when you have to push something into some library's object to force it to catch the exception. (depends on design of the lib - and is very rarely needed). Your original design, starts well, with flag indicating error, but the second thing should be the error message then. Or go on like this, if you feel that you really need it for some reason. But you can always do:
def move (pa, pb):
raise MoveError, "I will not move anything!"
and then:
try:
commands["move"]("somefile", "somewhereelse") # To simulate call from user input
print "Done!"
except Exception, e:
print "An error occurred.\n%s" % str(e)

python issue in anagram script

Second modification to the script (changes made below)
Made the changes mentioned in the comments (renamed all to print_all, and added the excepetion, changed the code below to reflect the same)
However, execution still exits without any reason
Initial query:
The following is a script that tries to identify various anagrams of a word (as in the website: http://wordsmith.org/anagram/anagram.cgi?anagram=suchindra&t=1000&a=n):
import sys
import itertools
import threading
from collections import defaultdict
words_dict = defaultdict(lambda: "")
def lower_and_nocrlf(s):
return s.lower().strip()
def two_or_more(s):
if len(s) >= 1:
return 1
else:
return 0
def get_perms(cur_iter):
lst = []
for i in range(0, 10000):
try:
lst.append("".join(cur_iter.next()))
except:
break
return lst
def get_twordlist(z):
lst1 = []
lst2 = []
for i in range (1, len(z)):
lst1.append(z[:i])
lst2.append(z[i:])
return lst1, lst2
def filter_dict(x):
if x in words_dict.keys():
return x
else:
return 0
def main():
print_all = None
word = None
try:
word = sys.argv[1]
print_all = sys.argv[2]
except:
pass
if word == None:
try:
word = sys.stdin.readline()
print_all = sys.stdin.readline()
except:
pass
if word == None:
sys.exit(1)
fd = open('/usr/apps/words', 'r')
words = fd.readlines()
fd.close()
words_lower = map(lower_and_nocrlf, words)
words_lower = filter(two_or_more, words_lower)
from collections import defaultdict
for i in words_lower:
words_dict[i] = ""
iter = itertools.permutations(word)
all_permutations = []
iters = []
for i in range(0, 100):
iters.append(iter)
result = map(get_perms, iters)
main_list = []
for l in result:
if l != []:
for word in l:
main_list.append(word)
results = []
try:
main_list_len = len(main_list)
for index in range(0, main_list_len):
percent = (index/len(main_list)) * 100
lst1, lst2 = get_twordlist(main_list[index])
result1 = map(filter_dict, lst1)
result2 = map(filter_dict, lst2)
for index in range(0, len(result1)):
if (result1[index] != 0) and (result2[index] != 0):
results.append("%s %s" % (result1[index], result2[index]))
except KeyboardInterrupt:
print("User stopped execution, partial results:")
print results
sys.exit(1)
except Exception:
# catches all other types of exception here
print(sys.exc_info())
traceback.print_exc()
print(results)
if __name__ == "__main__":
try:
main()
except:
sys.exit(0)
So, your code is clearly executing down to the print index line and then failing somewhere inside the block. The exception handler only catches exceptions of type KeyboardInterrupt - i.e. when a user presses Ctl+C on their keyboard. Any other error will exit via the sys.exit(0) method, so you have no way of knowing what the error is.
Personally I quite like the traceback module for these printing out errors, so I suggest you modify your try catch block to be something like:
import traceback
try:
main_list_len = len(main_list)
print main_list_len
for index in range(0, main_list_len):
print index
percent = (index/len(main_list)) * 100
lst1, lst2 = get_twordlist(main_list[index])
result = map(filter_dict, lst1, lst2)
results.append[result]
except KeyboardInterrupt:
print("User stopped execution, partial results:")
print("Exception: %s" % (sys.exc_info()))
print results
except Exception:
# catches all other types of exception here
traceback.print_exc()
This will allow you to debug the problem as the traceback module will give you line numbers and an error message to work with.
Good luck!
OK after some analysis, it looks like filter does not accept more than one list. The second issue is because I am using multiple lists in the filter

If else code help in try/ except block

SomeDict = {'Sarah':20, 'Mark': 'hello', 'Jackie': 'bye'}
try:
result = ""
theKey = raw_input("Enter some key: ")
val = someDict[theKey]
except keyErrorr:
result "hello"
else:
result = result + "" + "done"
print result
I understand the try block you can insert and code to try and see what error comes up, and the error then can be caught by the except block. I am trying to figure out the best way to insert a if / else in the try and except block for the same key error that is present in this code. I was thinking that i could just replace the try and except with If/else or is it possible to just add a if/else in the try and except. Any help on how to insert a if/else into this code for key error would be greatly appreciated. So basically i want to add a if/else code into the try and except block for the same key error.
SomeDict = {'Sarah':20, 'Mark': 'hello', 'Jackie': 'bye'}
try:
result = "" #could i insert something like if result == "" : #for this line?
theKey = raw_input("Enter some key: ")
val = someDict[theKey]
except keyErrorr:
result "hello"
else:
result = result + "" + "done"
print result
One reasonable option is to initialize result = None, then test if result is None:.
It's better to use None than the empty string, since someday you might want a dictionary value to be the empty string, plus None is probably clearer to the casual reader of your code.
You could also just skip the try-except, and use if theKey in someDict:.
you can add another except without a specification what exception it should handle.
try:
# do something
except KeyError:
# do something because of the Keyerror
except:
# do what you need to do if the exception is not a KeyError
someDict = {'Sarah':20, 'Mark': 'hello', 'Jackie': 'bye'} # corrected dict name
result = ""
theKey = raw_input("Enter some key: ")
try: # just try the code where the error could be
val = someDict[theKey]
except KeyError: # corrected exception name and indent level
result = "hello" # corrected syntax
else: # corrected indent level
result = result + "" + "done" # why add "" ?
print result
does this work for you?

Python: Is it possible to have multiple exceptions statments for a try block?

try:
case_no = re.search("Case Number:</span></td><td><span class=\"Value\">([^<]*?)<",br.response().read()).group(1)
except:
try:
try:
case_no = re.search("Citation Number:</span></td><td><span class=\"Value\">([^<]*?)<",br.response().read()).group(1)
except:
case_no = re.search("Citation Number:</span></td><td><span class=\"Value\">([^<]*?)<",br.response().read()).group(1)
except:
case_no = "N/A"
As you can see the above code is quite clumsy. I want to know if there is any way I can do like this.
try:
XYZ
except:
DOXYZ
except:
DOXYZ
Basically I want to be able to use - "try X if exception then try Y if exception then try Z" without nesting too much statemtns.
Probably you shouldn't be checking exception at all?
patterns = [
"Case Number:</span></td><td><span class=\"Value\">([^<]*?)<",
"Citation Number:</span></td><td><span class=\"Value\">([^<]*?)<",
"Citation Number:</span></td><td><span class=\"Value\">([^<]*?)<" # same as #2?
]
text = br.response().read()
case_no = "N/A"
for pattern in patterns:
res = re.search(pattern, text)
if res:
case_no = res.group(1)
break
Yes, it is posible, as long as you define exception condition...
Like:
try:
f = open('myfile.txt')
s = f.readline()
i = int(s.strip())
except IOError as (errno, strerror):
print "I/O error({0}): {1}".format(errno, strerror)
except ValueError:
print "Could not convert data to an integer."
except:
print "Unexpected error:", sys.exc_info()[0]
raise
But, you must define the exception type.
A common idiom for the behavior you're looking for is something like:
try: foo()
except: pass
try: bar()
except: pass
But you should always catch a specific exception and make sure it makes sense. In your case it simply doesn't make sense - to see if the regular expression matched, test the result for None:
r = br.response().read()
PATTERN1="..."
PATTERN2="..."
PATTERN3="..."
mo = re.search(PATTERN1, r) or re.search(PATTERN2, r) or re.search(PATTERN3, r)
case_no = mo.group(1) if mo else "N/A"
For performance reasons you can precompile your regexes:
RE1 = re.compile("...")
RE2 = re.compile("...")
RE3 = re.compile("...")
mo = RE1.search(r) or RE2.search(r) or RE3.search(r)
Also, for your specific regex patterns you can easily combine them into one, and using a named group can help readability:
pat = r"""(Case|Citation) Number:</span></td><td><span class="Value">(?P<case_no>[^<]*?)<"""
mo = re.search(pat, r)
case_no = mo.group("case_no") if mo else "N/A"
And finally, using regular expressions to parse HTML is the road to disaster, consider using HTMLParser from the standard lib or Beautiful Soup.
No, it is not possible to do what you want. the semantics of multiple except clauses covers catching different types of exceptions that may be thrown from the same block of code. You must nest the statements or rethink your code to get the desired results.
This might be a case where it would be better to test for the preconditions that you expect to cause an exception.
if test1():
#dox
elif test2():
#doy
elif test3():
#doz
etc.
I would also recommend against using catchall except: phrases except in very specialized circumstances where you know you need them.
I'd avoid the exceptions if I were doing this:
count = 3
caseRe = re.compile("Case Number:</span></td><td><span class=\"Value\">([^<]*?)<")
while count > 0:
text = br.response().read()
mo = caseRe.search(text)
if mo is None:
count -= 1
continue
case_no = mo.group(1)
break
if count == 0:
case_no = "N/A"
You'd be better off restructuring your code:
success = False
for _ in xrange(MAX_ATTEMPTS):
try:
XYZ
success = True
break
except:
pass
if not success:
DOXYZ
It's better to explicitly specify the exception, though. Do you really want to catch KeyboardInterrupts?
If you're doing the same or a similar thing in every try/except block, you might use a loop
case_no = "N/A"
for _ in range(3):
try:
case_no = re.search("Case Number:</span></td><td><span class=\"Value\">([^<]*?)<",br.response().read()).group(1)
break
except SomeExplicitlyCaughtExceptions:
pass
Of course it makes no sense in this form, because trying the same thing three times will yield the same result.

Categories

Resources