d3pd
d3pd

Reputation: 8315

How can a generator be converted to a function that returns only the first value yielded by the generator?

I have some code that prints out any messages that it receives in a loop:

import pytg
import pytg.utils
import pytg.receiver

@pytg.utils.coroutine
def receiver_function(tg_receiver):
    while True:
        message = (yield)
        print(message)

tg_receiver = pytg.receiver.Receiver()
tg_receiver.start()
tg_receiver.message(receiver_function(tg_receiver))
receiver.stop()

I want to change this code such that it uses a simple function that halts until a message is encountered and then returns that one message and, of course, control:

import pytg
import pytg.receiver

def get_one_message():
    tg_receiver.start()
    while #<insert magic>:
        #<insert magic>
        message = #<insert magic>
    tg.receiver.stop()
    return message

print(get_one_message())

How could this be done?

Upvotes: 0

Views: 45

Answers (1)

Ry-
Ry-

Reputation: 225124

pytg’s Receiver.message doesn’t seem to give you access to the generator’s GeneratorExit, so you might have to hack it:

def get_one_message():
    message = None

    @pytg.utils.coroutine
    def receiver_function(tg_receiver):
        nonlocal message
        message = (yield)

    tg_receiver.start()
    tg_receiver.message(receiver_function(tg_receiver))
    tg_receiver.stop()
    return message

Or dive into its undocumented (and therefore unstable) parts, though it’s not a good idea to do so:

def get_one_message():
    tg_receiver.start()
    tg_receiver._new_messages.acquire()
    with tg_receiver._queue_access:
        message = tg_receiver._queue.popleft()
    tg_receiver.stop()
    return message

Upvotes: 1

Related Questions