omz:forum

    • Register
    • Login
    • Search
    • Recent
    • Popular

    Welcome!

    This is the community forum for my apps Pythonista and Editorial.

    For individual support questions, you can also send an email. If you have a very short question or just want to say hello — I'm @olemoritz on Twitter.


    Web server in a separate thread?

    Pythonista
    3
    5
    5747
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • mikael
      mikael last edited by

      Would someone know of a robust web server implementation running in a separate thread, whenever my app is running?

      For the web server, I would be happy with any basic option available in Pythonista; vanilla, bottle, flask, ...

      To be considered a "robust implementation", my simple wish list includes:

      1. Logs issues, but stays up and running
      2. (Can be made to) Exit cleanly with the rest of the app
      3. Has been used in some real app for a while

      Any pointers?

      1 Reply Last reply Reply Quote 0
      • ccc
        ccc last edited by

        One example... https://github.com/cclauss/Pythonista_scene/blob/master/remote_control_scene.py#L39

        mikael 1 Reply Last reply Reply Quote 0
        • mikael
          mikael @ccc last edited by

          @ccc, thank you. Seems simple enough, but I cannot get it to release the socket on exit, causing an error on the next run. Was this not an issue for you, or am I doing something wrong?

          1 Reply Last reply Reply Quote 0
          • dgelessus
            dgelessus last edited by

            FWIW, when I've experimented with servers in Pythonista, I also found that the port would often remain "occupied" after stopping the server using the stop button (i. e. KeyboardInterrupt). This was easily fixed by rerunning the server twice - i. e. the first run would fail due to the port being in use, but the second run would work again. (This was a while ago when I was playing around with Python's built-in HTTP server module, no idea if this still happens in current versions, or if this even applies to your situation.)

            My wild guess would be that this is some sort of interaction between the "dirty" shutdown via KeyboardInterrupt, the garbage collector, and how Pythonista's interpreter never fully restarts. The KeyboardInterrupt breaks out of the server's main loop, but doesn't close or delete the socket, which is still referenced (indirectly) from a global variable. Rerunning the script clears or overwrites the global, which eventually deletes the socket, but not quick enough for that script run to reuse the port. On the next run, the port is free again and can be reused. (Again, I just came up with this explanation in my head and didn't really verify it. This may be absolute nonsense.)

            1 Reply Last reply Reply Quote 0
            • mikael
              mikael last edited by

              Below is a version of a bottle server that runs in a thread and can be told to shut down cleanly, based on this stackoverflow answer.

              #coding: utf-8
              from ui import *
              import bottle, threading, requests, time
              
              from bottle import Bottle, ServerAdapter
              
              class MyWSGIRefServer(ServerAdapter):
                server = None
              
                def run(self, handler):
                  from wsgiref.simple_server import make_server, WSGIRequestHandler
                  if self.quiet:
                    class QuietHandler(WSGIRequestHandler):
                      def log_request(*args, **kw): pass
                    self.options['handler_class'] = QuietHandler
                  self.server = make_server(self.host, self.port, handler, **self.options)
                  self.server.serve_forever()
              
                def stop(self):
                  self.server.shutdown()
                  
              app = Bottle()
                  
              @app.get('/')
              def bottle_get_index():
                return "Test OK"
              
              if __name__ == '__main__':
                
                w = WebView()
                w.present('full_screen')
                w.load_html('Loading...')
                
                server = MyWSGIRefServer(port=80)
                
                threading.Thread(group=None, target=app.run, name=None, args=(), kwargs={'server': server, 'quiet': False}).start()
                
                time.sleep(2)
                
                req = requests.get('http://127.0.0.1/')
                w.load_html(req.text)
                
                server.stop()
              
              1 Reply Last reply Reply Quote 1
              • First post
                Last post
              Powered by NodeBB Forums | Contributors