Reputation: 357
I have made a generator function which search a csv file using a keyword and I want to print the results if there is something. How can I do that without using the print(next(gen_results)) over and over again?
I have tried a try-catch statement for the stopIteration, when there is no matching of keyword with a contact but I want a more concise solution.
def search(keyword, filename):
f = open(filename, 'r')
for line in f:
if keyword in line:
yield line
f.close()
the_generator = search('Python', 'contacts.csv')
print(next(the_generator))
print(next(the_generator))
contacts.csv
Name01, 89888
Name02, 8885445
Name03, 54555
Name04, 55544584
Name05, 55855
Python, 100
BigPi, 444
Python, 101
I expect the output to be a statement as 'Nothing Found',if there are no contacts with the keyword. In case there are contacts with the keyword, it outputs all the listings.
Upvotes: 1
Views: 1294
Reputation: 491
Please try this
def search(keyword, filename):
f = open(filename, 'r')
for line in f:
if keyword in line:
yield line
else:
yield 'Nothing Found'
f.close()
the_generator = search('Python', 'contacts.csv')
for g in the_generator:
print(g)
'the_generator' is an iterate object and 'for' loop needs an iterate object to run. The output of the program will :
Nothing Found
Nothing Found
Nothing Found
Nothing Found
Nothing Found
Python, 100
Upvotes: 2
Reputation: 231385
You could put the 'not found' test in the generator itself:
def search(keyword, lines):
cnt = 0
for line in lines:
if keyword in line:
cnt += 1
yield line
if cnt==0:
yield "NOT FOUND"
In [166]: txt = """Name01, 89888
...: Name02, 8885445
...: Name03, 54555
...: Name04, 55544584
...: Name05, 55855
...: Python, 100
...: BigPi, 444
...: Python, 101
...: """.splitlines()
In [167]: for x in search("Python",txt):print(x)
Python, 100
Python, 101
In [168]: for x in search("Foobar",txt):print(x)
NOT FOUND
Otherwise I think the simplest is to list
the generator, and check for an empty list. By itself the generator mechanism does not count the number of yields
.
Upvotes: 1
Reputation: 8215
def search(keyword, filename):
f = open(filename, 'r')
for line in f:
if keyword in line:
yield line
f.close()
the_generator = search('Python', 'contacts.csv')
my_list=list(the_generator)
if not my_list:
print("Not Found")
for item in my_list:
print(item.strip())
Upvotes: 1
Reputation: 51643
There are several methods to consume the generator - unsing next()
only consumes (the next) value of it.
Generate file:
def gen_file():
with open("contacts.csv","w") as f:
f.write("""Name01, 89888
Name02, 8885445
Name03, 54555
Name04, 55544584
Name05, 55855
Python, 100
BigPi, 444
Python, 101
""")
Use it:
gen_file()
def search(keyword, filename="contacts.csv"):
"""Changed to use .. with open() as f: ... style syntax."""
with open(filename, 'r') as f:
for line in f:
if keyword in line:
yield line
# consume all of it into a list - you can reuse it
print("-"*40)
the_generator = search('Python', 'contacts.csv')
contacts = list(the_generator)
print(*contacts, sep="")
print("-"*40)
# decompose the generator directly for printing
the_generator = search('Python', 'contacts.csv')
print(*the_generator, sep="" )
print("-"*40)
# use a for loop over the generated results
the_generator = search('Python', 'contacts.csv')
for li in the_generator:
print(li, end="") # remove end=\n
print("-"*40)
# using str.join to create the output
the_generator = search('Python', 'contacts.csv')
print("".join(the_generator))
print("-"*40)
# loop endlessly until StopIteration is raised
try:
while True:
print(next(the_generator), end="")
except StopIteration:
pass
etc.
Output (several times):
----------------------------------------
Python, 100
Python, 101
The "best" one if you do not reuse the generated values is probably print(*the_generator,sep="")
or the more explicit:
# use a for loop over the generated results
the_generator = search('Python', 'contacts.csv')
for li in the_generator:
print(li,end="") # remove end=\n
You may also want to read here: Using yield from with conditional in python
Upvotes: 0