This is kind of a weird question so I'll explain:
I have a generator like this that is acting as a generator frontend to an IRC server:
def irc_iter(): # not the real code, simplified
msgs = get_msgs()
for msg in msgs:
if is_ping(msg):
pong()
else:
to_send = yield msg
for s in to_send:
send(s)
This, theoretically, should allow me to do something cool, like:
server = connect()
for line in server:
if should_respond(line):
server.send('WOW SUCH MESSAGE')
However, there's a hitch: generator.send
yields the next value as well. This means that server.send
is also giving me the next message... which I would prefer to handle like all the other messages, yielded as line
.
I know I can fix this in an ugly way, by just yielding a junk value after receiving a send, but I'm trying to keep my code elegant and that is the opposite. Is there a way to just tell the generator I don't want a new value yet?
Thanks.
The send() method returns the next value yielded by the generator, or raises StopIteration if the generator exits without yielding another value. When send() is called to start the generator, it must be called with None as the argument, because there is no yield expression that could receive the value.
Inside a program, when you call a function that has a yield statement, as soon as a yield is encountered, the execution of the function stops and returns an object of the generator to the function caller.
The yield statement hauls the function and returns back the value to the function caller and restart from where it is left off. The yield statement can be called multiple times. While the return statement ends the execution of the function and returns the value back to the caller.
I also just came across this issue and also didn't find anything better than dummy yield
...
So in your generator code:
# Input
input_value = yield
if input_value is None:
# Handle situation if someone used your generator in a wrong way
sys.exit(-1)
yield "DUMMY YIELD JUST STOP HERE!!!"
And in the client code:
while True:
values = next(my_generator)
...
if values == 'INPUT_NEEDED':
# At this point you realize it's input time
next(my_generator) # Rewind to the input point
my_generator.send(12345) # Returns "DUMMY YIELD JUST STOP HERE!!!"
continue
# Continue the main loop
It looks like the problem comes from you calling the generator twice per iteration, once with .send(None)
(in the for loop) and once with .send(response)
.
It would be a simple fix if the for loop could iterate over .send() instead of .next(), but I am not familiar with any way to get that to work (optional extended continue statement in pep342?) without wrapping it in another generator (possibly using a queue to push values into .send() on .next() calls). The simplest solution, though, would probably be:
server = connect()
response = None
try:
while True:
line = server.send(response)
response = None
if should_respond(line):
response ='WOW SUCH MESSAGE'
except StopIteration:
pass
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With