Can a generator wait with yielding until another function is triggered?











up vote
1
down vote

favorite












I have written the following testing code for a website. The index shows a relatively empty page, but it'll open a stream from which it can receive more messages from the server, effectively allowing me to make server side events. For this, I need to insert a generator into the Response object.



from flask import Flask, Response, render_template

app = Flask(__name__)

def answer():
while True:
q = input("Whaddaya wanna say? ")
yield 'data: {} nn'.format(q)

@app.route('/')
def index():
return render_template('index.html')

@app.route('/stream')
def stream():
return Response(answer(), mimetype="text/event-stream")

if __name__ == "__main__":
app.run(threaded=True, debug=True)


Together with a file called index.html, this works perfectly fine. I am receiving any text that I have given as an input to the terminal. However, if a second user were to visit the server, Python starts going back and forth between the two users - some input will be sent to one user, the next will always be sent to the other. I understand that this is how it's supposed to work, but I wondered if it was possible to create a generator that would yield to all clients.



Currently, I could think of two possible ways to do this. The first one isn't too complicated, but I'm not sure if it's a good idea to put in practice. Here, one Messenger instance would be created, after which its ànswer() function would be given as a generator.



class Messenger:
def __init__(self):
self.message = ""
def send_msg(self,msg):
self.message = msg

def answer(self):
current_message = self.message
while True:
# Yield when the message has been updated
if self.message != current_message:
current_message = self.message
yield current_message


I do not really like this code for two reasons. First off, it does not allow the user to send the same message twice in a row. Second, checking constantly seems like wasting a lot of time on checking stuff. There has to be a better way. Is there?



I have been trying multiple methods, but I just can't think of any. I couldn't find any solution on the internet either. My current guess is to somehow make the function wait until the update is made. Something like the following, though I wouldn't know how to finish this code.



class Messenger:
def __init__(self):
self.message = ""
def send_msg(self,msg):
self.message = msg

def answer(self):
while True:
pass # Pause function until send_msg() is executed

yield self.message


Is it possible to create such a function? Is there a better way to solve this issue? Would you instead recommend looking into finding an alternative to the generator? Is the first option not as bad as it seems, and if so, why?










share|improve this question


























    up vote
    1
    down vote

    favorite












    I have written the following testing code for a website. The index shows a relatively empty page, but it'll open a stream from which it can receive more messages from the server, effectively allowing me to make server side events. For this, I need to insert a generator into the Response object.



    from flask import Flask, Response, render_template

    app = Flask(__name__)

    def answer():
    while True:
    q = input("Whaddaya wanna say? ")
    yield 'data: {} nn'.format(q)

    @app.route('/')
    def index():
    return render_template('index.html')

    @app.route('/stream')
    def stream():
    return Response(answer(), mimetype="text/event-stream")

    if __name__ == "__main__":
    app.run(threaded=True, debug=True)


    Together with a file called index.html, this works perfectly fine. I am receiving any text that I have given as an input to the terminal. However, if a second user were to visit the server, Python starts going back and forth between the two users - some input will be sent to one user, the next will always be sent to the other. I understand that this is how it's supposed to work, but I wondered if it was possible to create a generator that would yield to all clients.



    Currently, I could think of two possible ways to do this. The first one isn't too complicated, but I'm not sure if it's a good idea to put in practice. Here, one Messenger instance would be created, after which its ànswer() function would be given as a generator.



    class Messenger:
    def __init__(self):
    self.message = ""
    def send_msg(self,msg):
    self.message = msg

    def answer(self):
    current_message = self.message
    while True:
    # Yield when the message has been updated
    if self.message != current_message:
    current_message = self.message
    yield current_message


    I do not really like this code for two reasons. First off, it does not allow the user to send the same message twice in a row. Second, checking constantly seems like wasting a lot of time on checking stuff. There has to be a better way. Is there?



    I have been trying multiple methods, but I just can't think of any. I couldn't find any solution on the internet either. My current guess is to somehow make the function wait until the update is made. Something like the following, though I wouldn't know how to finish this code.



    class Messenger:
    def __init__(self):
    self.message = ""
    def send_msg(self,msg):
    self.message = msg

    def answer(self):
    while True:
    pass # Pause function until send_msg() is executed

    yield self.message


    Is it possible to create such a function? Is there a better way to solve this issue? Would you instead recommend looking into finding an alternative to the generator? Is the first option not as bad as it seems, and if so, why?










    share|improve this question
























      up vote
      1
      down vote

      favorite









      up vote
      1
      down vote

      favorite











      I have written the following testing code for a website. The index shows a relatively empty page, but it'll open a stream from which it can receive more messages from the server, effectively allowing me to make server side events. For this, I need to insert a generator into the Response object.



      from flask import Flask, Response, render_template

      app = Flask(__name__)

      def answer():
      while True:
      q = input("Whaddaya wanna say? ")
      yield 'data: {} nn'.format(q)

      @app.route('/')
      def index():
      return render_template('index.html')

      @app.route('/stream')
      def stream():
      return Response(answer(), mimetype="text/event-stream")

      if __name__ == "__main__":
      app.run(threaded=True, debug=True)


      Together with a file called index.html, this works perfectly fine. I am receiving any text that I have given as an input to the terminal. However, if a second user were to visit the server, Python starts going back and forth between the two users - some input will be sent to one user, the next will always be sent to the other. I understand that this is how it's supposed to work, but I wondered if it was possible to create a generator that would yield to all clients.



      Currently, I could think of two possible ways to do this. The first one isn't too complicated, but I'm not sure if it's a good idea to put in practice. Here, one Messenger instance would be created, after which its ànswer() function would be given as a generator.



      class Messenger:
      def __init__(self):
      self.message = ""
      def send_msg(self,msg):
      self.message = msg

      def answer(self):
      current_message = self.message
      while True:
      # Yield when the message has been updated
      if self.message != current_message:
      current_message = self.message
      yield current_message


      I do not really like this code for two reasons. First off, it does not allow the user to send the same message twice in a row. Second, checking constantly seems like wasting a lot of time on checking stuff. There has to be a better way. Is there?



      I have been trying multiple methods, but I just can't think of any. I couldn't find any solution on the internet either. My current guess is to somehow make the function wait until the update is made. Something like the following, though I wouldn't know how to finish this code.



      class Messenger:
      def __init__(self):
      self.message = ""
      def send_msg(self,msg):
      self.message = msg

      def answer(self):
      while True:
      pass # Pause function until send_msg() is executed

      yield self.message


      Is it possible to create such a function? Is there a better way to solve this issue? Would you instead recommend looking into finding an alternative to the generator? Is the first option not as bad as it seems, and if so, why?










      share|improve this question













      I have written the following testing code for a website. The index shows a relatively empty page, but it'll open a stream from which it can receive more messages from the server, effectively allowing me to make server side events. For this, I need to insert a generator into the Response object.



      from flask import Flask, Response, render_template

      app = Flask(__name__)

      def answer():
      while True:
      q = input("Whaddaya wanna say? ")
      yield 'data: {} nn'.format(q)

      @app.route('/')
      def index():
      return render_template('index.html')

      @app.route('/stream')
      def stream():
      return Response(answer(), mimetype="text/event-stream")

      if __name__ == "__main__":
      app.run(threaded=True, debug=True)


      Together with a file called index.html, this works perfectly fine. I am receiving any text that I have given as an input to the terminal. However, if a second user were to visit the server, Python starts going back and forth between the two users - some input will be sent to one user, the next will always be sent to the other. I understand that this is how it's supposed to work, but I wondered if it was possible to create a generator that would yield to all clients.



      Currently, I could think of two possible ways to do this. The first one isn't too complicated, but I'm not sure if it's a good idea to put in practice. Here, one Messenger instance would be created, after which its ànswer() function would be given as a generator.



      class Messenger:
      def __init__(self):
      self.message = ""
      def send_msg(self,msg):
      self.message = msg

      def answer(self):
      current_message = self.message
      while True:
      # Yield when the message has been updated
      if self.message != current_message:
      current_message = self.message
      yield current_message


      I do not really like this code for two reasons. First off, it does not allow the user to send the same message twice in a row. Second, checking constantly seems like wasting a lot of time on checking stuff. There has to be a better way. Is there?



      I have been trying multiple methods, but I just can't think of any. I couldn't find any solution on the internet either. My current guess is to somehow make the function wait until the update is made. Something like the following, though I wouldn't know how to finish this code.



      class Messenger:
      def __init__(self):
      self.message = ""
      def send_msg(self,msg):
      self.message = msg

      def answer(self):
      while True:
      pass # Pause function until send_msg() is executed

      yield self.message


      Is it possible to create such a function? Is there a better way to solve this issue? Would you instead recommend looking into finding an alternative to the generator? Is the first option not as bad as it seems, and if so, why?







      python function flask generator






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Nov 22 at 7:42









      Randium

      113




      113





























          active

          oldest

          votes











          Your Answer






          StackExchange.ifUsing("editor", function () {
          StackExchange.using("externalEditor", function () {
          StackExchange.using("snippets", function () {
          StackExchange.snippets.init();
          });
          });
          }, "code-snippets");

          StackExchange.ready(function() {
          var channelOptions = {
          tags: "".split(" "),
          id: "1"
          };
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function() {
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled) {
          StackExchange.using("snippets", function() {
          createEditor();
          });
          }
          else {
          createEditor();
          }
          });

          function createEditor() {
          StackExchange.prepareEditor({
          heartbeatType: 'answer',
          autoActivateHeartbeat: false,
          convertImagesToLinks: true,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: 10,
          bindNavPrevention: true,
          postfix: "",
          imageUploader: {
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          },
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          });


          }
          });














          draft saved

          draft discarded


















          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53426055%2fcan-a-generator-wait-with-yielding-until-another-function-is-triggered%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown






























          active

          oldest

          votes













          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes
















          draft saved

          draft discarded




















































          Thanks for contributing an answer to Stack Overflow!


          • Please be sure to answer the question. Provide details and share your research!

          But avoid



          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.


          To learn more, see our tips on writing great answers.





          Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


          Please pay close attention to the following guidance:


          • Please be sure to answer the question. Provide details and share your research!

          But avoid



          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.


          To learn more, see our tips on writing great answers.




          draft saved


          draft discarded














          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53426055%2fcan-a-generator-wait-with-yielding-until-another-function-is-triggered%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          Popular posts from this blog

          Berounka

          Sphinx de Gizeh

          Different font size/position of beamer's navigation symbols template's content depending on regular/plain...