Qt Forum

    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    • Unsolved

    Call for Presentations - Qt World Summit

    Unsolved Run an async web server along with PyQt5

    Qt for Python
    4
    8
    1298
    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.
    • R
      rhx9 last edited by

      Hello,
      I'm trying to run an async web server like Sanic along side my PyQt5 app, but the web server api requires that i run a function .run which runs an event loop, and i'm having trouble running it along side the PyQt5 event loop:

      I tried to run it inside a Qthread but even then it makes the app freeze because the .run function never returns until the app is closed.

      My example Qthread class:

      
      class api_server(qtc.QObject):
          def __init__(self, *args, **kwargs):
              super().__init__(*args, **kwargs)
              self.api = Sanic(name='test')
              self.api.add_route(self.test, "/")
      
          def run(self):
              
              self.api.run(host="0.0.0.0", port=8080)
       
          async def test(self,request):
              return json({"hello": "world"})
      

      Then in my main qtw.QMainWindow init method I'm doing the following:

      self._api_server_thread = qtc.QThread()
      self._api_server = api.api_server()
      self._api_server_thread.started.connect(self._api_server.run)
      self._api_server.moveToThread(self._api_server_thread)
      self._api_server_thread.start()
      

      Regards

      eyllanesc 1 Reply Last reply Reply Quote 0
      • SGaist
        SGaist Lifetime Qt Champion last edited by

        Hi,

        Why do you need a full blown web server as part of your GUI application ?

        That said you may have to consider using the Python subprocess module rather than multithreading.

        Interested in AI ? www.idiap.ch
        Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

        R 1 Reply Last reply Reply Quote 0
        • R
          rhx9 @SGaist last edited by rhx9

          @SGaist said in Run an async web server along with PyQt5:

          Hi,

          Why do you need a full blown web server as part of your GUI application ?

          To provide an api for another app running on a different machine and since my gui app is already connected the sqlite database i want to run the server from the same code to keep resource usage to a minimum

          That said you may have to consider using the Python subprocess module rather than multithreading.

          That means i need to run the server from a different python file which means i can't reference the server from inside my app code.

          There was a proposed qt component a couple of years ago which would have been perfect for my use case, sadly it was never merged upstream

          Regards

          1 Reply Last reply Reply Quote 0
          • SGaist
            SGaist Lifetime Qt Champion last edited by

            That doesn't answer my question about the why.

            Understanding the why may help found how.

            From memory QHttpServer is a separate module. If you really want it in Python, you can create the necessary bindings yourself.

            Interested in AI ? www.idiap.ch
            Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

            R 1 Reply Last reply Reply Quote 0
            • R
              rhx9 @SGaist last edited by

              @SGaist said in Run an async web server along with PyQt5:

              That doesn't answer my question about the why.

              Understanding the why may help found how.

              The gui app is connected to an SQLITE database, along side the main app function, it should also provide an api that can be called from a different machine, this api can be used to control the main app(provide records from the database, delete, insert as well as running functions that changes the Widget appearance which is why i need the server to be called from my pyqt app code

              From memory QHttpServer is a separate module. If you really want it in Python, you can create the necessary bindings yourself.

              That would be too much of a hassle and i have no prior experience in that space

              Regards

              1 Reply Last reply Reply Quote 0
              • SGaist
                SGaist Lifetime Qt Champion last edited by

                In that case, I would suggest to have these two cleanly separated and have your GUI connect to the API server as well for example through a local socket.

                They can both connect to the same database if required. Establish a protocol for whatever needs to be changed in your GUI based on what is called your API server.

                This has the added advantage that your GUI can crash without killing the server and vice-versa.

                Interested in AI ? www.idiap.ch
                Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                1 Reply Last reply Reply Quote 0
                • eyllanesc
                  eyllanesc @rhx9 last edited by

                  @rhx9 A simple solution is to use qasync:

                  # https://github.com/sanic-org/sanic/blob/main/examples/run_async.py
                  import asyncio
                  from signal import signal, SIGINT
                  import sys
                  
                  from sanic import Sanic
                  from sanic.response import json
                  
                  from PyQt5.QtCore import QDateTime, Qt, QTimer
                  from PyQt5.QtWidgets import QApplication, QLabel
                  
                  import qasync
                  
                  
                  app = Sanic(__name__)
                  
                  
                  @app.route("/")
                  async def test(request):
                      return json({"hello": "world"})
                  
                  
                  def main():
                      qtapp = QApplication(sys.argv)
                      loop = qasync.QEventLoop(qtapp)
                      asyncio.set_event_loop(loop)
                  
                      w = QLabel(alignment=Qt.AlignmentFlag.AlignCenter)
                      w.resize(640, 480)
                      w.show()
                  
                      def handle_timeout():
                          w.setText(QDateTime.currentDateTime().toString())
                  
                      timer = QTimer()
                      timer.setInterval(1000)
                      timer.timeout.connect(handle_timeout)
                      timer.start()
                      handle_timeout()
                  
                      server = app.create_server(host="0.0.0.0", port=8000, return_asyncio_server=True)
                      loop = asyncio.get_event_loop()
                      task = asyncio.ensure_future(server)
                      server = loop.run_until_complete(task)
                      loop.run_until_complete(server.startup())
                      signal(SIGINT, lambda s, f: loop.stop())
                  
                      try:
                          loop.run_forever()
                      finally:
                          loop.stop()
                  
                  
                  if __name__ == "__main__":
                      main()
                  

                  If you want me to help you develop some work then you can write to my email: e.yllanescucho@gmal.com.

                  A 1 Reply Last reply Reply Quote 2
                  • A
                    allenZ @eyllanesc last edited by

                    @eyllanesc qasync is awesome, i use it to embed a asyncio tcp server with my qml application.
                    yet it did not support python 3.11 for right now as this issue described, does qasync has a substitude which work with python 3.11?
                    i also noticed that asyncio example is in discussion mentioned in 08. December 2022 development notes, yet i can not find any official asyncio example until now

                    1 Reply Last reply Reply Quote 0
                    • First post
                      Last post