Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Activity
    Penguin Master
    @PenguinMaster0226

    @pgjones sorry for the late reply, but here's my code:

    from quart import Quart, websocket
    from functools import wraps
    import asyncio
    
    app = Quart(__name__)
    
    connected_websockets = set()
    
    def collect_websocket(func):
        @wraps(func)
        async def wrapper(*args, **kwargs):
            global connected_websockets
            queue = asyncio.Queue()
            connected_websockets.add(queue)
            print(connected_websockets)
            try:
                return await func(queue, *args, **kwargs)
            finally:
                connected_websockets.remove(queue)
        return wrapper
    
    
    async def broadcast(message):
        for queue in connected_websockets:
            queue.put_nowait("New connection")
    
    
    @app.websocket('/')
    @collect_websocket
    async def ws(queue):
        while True:
            data = await websocket.receive()
            print(data)
            await broadcast(data)
    
    if __name__ == "__main__":
        app.run(host="0.0.0.0", port=8080)

    You can ignore the host="0.0.0.0", that's just there because it's on replit

    Phil Jones
    @pgjones
    In this code you receive data from the websocket connections and place "New connection" (ignoring the data) on a queue, but you never read the data from the queue. The connected_websockets set will contain a queue for each websocket connection though. What are you hoping will happen?
    Phil Jones
    @pgjones
    @7185 see pgjones/quart-auth@68b6786 - could you say if this solves your need?
    tibs
    @7185
    @pgjones yes, this is exactly what I wanted, thank you!
    povar81
    @povar81

    Hi, everyone.
    I've just started using quart for my tests, I'm using this simple code :

    def start_app():
        from keyboard import press
        import quart
        app = quart.Quart(__name__)
        @app.route("/api", methods=["POST"])
        async def json():
            return {"hello": "quart world"}
        app.run(host='myip',port=5000)
    start_app()

    and it's working fine, except that I always get these unwanted messages when it starts:

    • Serving Quart app 'main'
    • Environment: production
    • Please use an ASGI server (e.g. Hypercorn) directly in production
    • Debug mode: False
    • Running on http://myhost:5000 (CTRL + C to quit)
      [2021-04-05 18:19:07,784] Running on http://myhost:5000 (CTRL + C to quit).

    Can anyone please tell me how to disable them?
    I've tried

    logging.getLogger('werkzeug').setLevel(logging.CRITICAL)
    logging.getLogger('app.serving').setLevel(logging.CRITICAL)
    logging.getLogger('quart.serving').setLevel(logging.CRITICAL)
    
    logging.getLogger('app.serving').disabled = True
    logging.getLogger('quart.serving').disabled = True
    
    logging.getLogger('app.serving').propagate = False
    logging.getLogger('quart.serving').propagate = False

    nothing helps

    Phil Jones
    @pgjones
    Probably best for you to make use of the run_task method to fully control how quart runs
    povar81
    @povar81
    Thank you, I see there are some options for changing the look of the logging:
    config = HyperConfig()
    config.access_log_format = "%(h)s %(r)s %(s)s %(b)s %(D)s"
    config.accesslog = create_serving_logger()
    but how can I disable the logging entirely (temporarily)?
    Phil Jones
    @pgjones
    I think if you remove the accesslog line it will disable all loggers
    povar81
    @povar81

    thank you, it worked in combination with
    sys.stdout = open(os.devnull, 'w')
    sys.stderr = open(os.devnull, "w")

    but I actually wanted to start this function in background via this code:

    import multiprocess as mp
    proc = mp.Process(target=start_app, args=())
    proc.start()

    and that still doesn't work because besides those lines I'm also getting an empty line in console (the app waiting for the requests I guess).

    Is there a way to start/stop the quart app in background?

    Phil Jones
    @pgjones
    Yea, you can use asyncio.run(app.run_task(...)) in the start_app function
    povar81
    @povar81
    No, I mean I need the start_app function to be running in the background
    and then be able to stop it at certain point
    povar81
    @povar81
    I was able to run the start_app function in the background but only when I moved start_app function into a separate py file, imported and run it like this:
    import mock_service_app
    import multiprocessing as mp
    proc = mp.Process(target=mock_service_app.start_app, args=())
    proc.start()
    proc = mp.Process(target=start_app, args=(), initializer=mute)
    povar81
    @povar81
    are there any working examples of how to use startup/shutdown described in:
    https://pgjones.gitlab.io/quart/how_to_guides/startup_shutdown.html
    ?
    Phil Jones
    @pgjones
    There is an example here for my website
    povar81
    @povar81

    Thank you,
    I see
    @app.before_serving

    and
    app.run()

    is there also an example on how to shutdown it?

    Phil Jones
    @pgjones
    Something like this?
    Ernesto Ruge
    @the-infinity
    @povar81 I just pushed an project where I used before and after serving as a global extension: https://github.com/openbikebox/open-bike-box-connect/blob/master/webapp/common/amqp_queue.py . Perhaps this is an inspiration, too? :)
    András Mózes
    @mozesa
    @the-infinity Nice work! A great inspiration source :smile:
    Phil Jones
    @pgjones
    Nice!
    Phil Jones
    @pgjones
    @the-infinity Hopefully you don't need jsonify anymore (can just return a dict) e.g. here.
    Ernesto Ruge
    @the-infinity
    @pgjones thanks for the hint! The configure_error_handlers is somehow a standard block which is in all my Flask / Quart projects, but without jsonify it's even more beautiful. Does it respect the JSON encoder I set here without jsonify: https://github.com/openbikebox/connect/blob/master/webapp/common/filter.py#L13 ?
    povar81
    @povar81
    Thank you.
    I need a solution so that my start_app can be started in background in pytest in one case
    and then to be able to read data coming to the start_app in another case
    (and then stop it in yet another case - but that one I've already figured out via psutils)
    Phil Jones
    @pgjones
    @the-infinity it should do (bug if it doesn't)
    shantanoo
    @shantanoo:matrix.org
    [m]
    hi, how do i use sqlite3 or ORM like peewee (sqlite3) with quart?
    was looking @ https://aiosqlite.omnilib.dev/en/stable/ but couldn't find any example
    Phil Jones
    @pgjones
    Hi @shantanoo:matrix.org there isn't anything particularly special you need to do. Which aspects are you unsure about? Here is an sqlite example and pgjones/quart#35 is a good discussion.
    5 replies
    Montassar Ben Dhifallah
    @Momentum-TN
    hello everyone,
    I am new to quart.
    I want to get multiple files from a request. In flask, I used to use request.files.getlist("file")
    What is the equivalent in quart ?
    Phil Jones
    @pgjones
    (await request.files).getlist("file") should work
    shantanoo
    @shantanoo:matrix.org
    [m]
    but asyncpg seems nice
    Montassar Ben Dhifallah
    @Momentum-TN
    @pgjones thank you so much !
    tomgper
    @tomgper
    hi, I'm moving some code from flask to quart. In flask with gevent we had a way to obtain the port that was opened by the internal socket (configured with port 0 basically). Is there a way to do the same with quart (asyncio) + hypercorn? Thank you
    Montassar Ben Dhifallah
    @Momentum-TN

    hey everyone!
    hope you are all well
    I am trying to learn how to make an ML-based web app using Quart.
    I want to build an application that can handle prediction of a batch of images. I want to divide the batch into small chunks, make predictions and return the response to the user. This process should be done until the last chunk
    I thought of making an async recursive api call. All I want to do is to make it recursively return the response.

    Any help is appreciated.
    This is the function that I want to call it recursively.

    @app.route('/predict', methods=['POST'])
    async def predict():
    
        if request.method == 'POST':
            has_files = (await request.files).get("file", None)
        if has_files:
            files = (await request.files).getlist("file")
            responses= {}
            # split files into small chunks to place here !
    
            for file, i in zip(files, range(len(files))):
                img_bytes = file.read()
    
                class_id, class_name = await get_prediction(model=model,
                                                      image_bytes=img_bytes,
                                                      imagenet_class_index= imagenet_class_index)
                responses[i] = {'class_id': class_id, 'class_name': class_name}
                print(responses[i])
    
            return await render_template("results.html", text=str(responses))
        else:
            return await render_template("results.html", text="please upload image!")
    Phil Jones
    @pgjones
    Would something using Server Sent Events, SSE, be what you need? https://gitlab.com/pgjones/quart/-/tree/master/examples/broadcast
    Ahmad Kurdi
    @ahmaddmkurdii_twitter
    Hello, I would like to ask how can I make my Quart API await for API Calls before opening new connections? Cause every time a request is sent to the Quart app, it processes it and opens a new connection after it's done automatically, even if there is no API calls which leads to timeout after 60s. Thank you.
    I have previously opened a GitLab issue: pgjones/quart#409
    Phil Jones
    @pgjones
    I've responded, but I don't fully understand what the issue is
    luna
    @lun-4

    @pgjones when using websocket.close() from latest quart (from master branch), i get an error because quart is trying to close the websocket again in handle_websocket

    I made a hotfix for hypercorn that forces only one websocket.close event to be executed, ignoring the rest. I did this in hypercorn because quart is not aware of the websocket state, and so it can not know if the websocket has closed (or is in the process of doing so), does this make sense? Is it correct to MR this fix?

    Another question: Is hypercorn going to support HTTP&Websockets ASGI 2.3? reason is not a blocker on my webapp development, but it is wanted in the future (this would also mean support for 2.2, since hypercorn is currently on 2.1)

    fiatjaf
    @fiatjaf
    whenever there is any error or exception anywhere in my app, quart just stops working -- but it doesn't crash.
    trio's nurseries break and stop accepting tasks, HTTP requests time out without logging anything to the server
    and so on
    what am I doing wrong?
    I imagine there is a way to catch all exceptions by default and show them to the user and go on
    this is the code (if it matters, probably not): https://github.com/lnbits/lnbits
    Phil Jones
    @pgjones
    @lun-4 I think that is a good solution, but I'll check pgjones/quart#410.
    Yep, Hypercorn will support 2.3 when I next release it
    luna
    @lun-4
    Thank you!
    Phil Jones
    @pgjones
    @fiatjaf is there a traceback you can share?
    fiatjaf
    @fiatjaf
    hypercorn[497166]: [2021-05-03 18:07:08 +0000] [497166] [ERROR] Error in ASGI Framework
    hypercorn[497166]: Traceback (most recent call last):
    hypercorn[497166]:   File "/root/lnbits/venv/lib/python3.8/site-packages/hypercorn/trio/context.py", line 39, in _handle
    hypercorn[497166]:     await invoke_asgi(app, scope, receive, send)
    hypercorn[497166]:   File "/root/lnbits/venv/lib/python3.8/site-packages/hypercorn/utils.py", line 239, in invoke_asgi
    hypercorn[497166]:     await app(scope, receive, send)
    hypercorn[497166]:   File "/root/lnbits/venv/lib/python3.8/site-packages/quart/app.py", line 2117, in __call__
    hypercorn[497166]:     await self.asgi_app(scope, receive, send)
    hypercorn[497166]:   File "/root/lnbits/venv/lib/python3.8/site-packages/quart/app.py", line 2140, in asgi_app
    hypercorn[497166]:     await asgi_handler(receive, send)
    hypercorn[497166]:   File "/root/lnbits/venv/lib/python3.8/site-packages/quart_trio/asgi.py", line 18, in __call__
    hypercorn[497166]:     nursery.start_soon(self.handle_request, nursery, request, send)
    hypercorn[497166]:   File "/root/lnbits/venv/lib/python3.8/site-packages/trio/_core/_run.py", line 741, in __aexit__
    hypercorn[497166]:     raise combined_error_from_nursery
    hypercorn[497166]:   File "/root/lnbits/venv/lib/python3.8/site-packages/quart_trio/asgi.py", line 29, in handle_request
    hypercorn[497166]:     response = await self.app.handle_request(request)
    hypercorn[497166]:   File "/root/lnbits/venv/lib/python3.8/site-packages/quart_trio/app.py", line 135, in handle_request
    hypercorn[497166]:     return await self.handle_exception(error)
    hypercorn[497166]:   File "/root/lnbits/venv/lib/python3.8/site-packages/quart/app.py", line 1118, in handle_exception
    hypercorn[497166]:     raise error
    hypercorn[497166]:   File "/root/lnbits/venv/lib/python3.8/site-packages/quart_trio/app.py", line 131, in handle_request
    hypercorn[497166]:     return await self.full_dispatch_request(request_context)
    hypercorn[497166]:   File "/root/lnbits/venv/lib/python3.8/site-packages/quart_trio/app.py", line 153, in full_dispatch_request
    hypercorn[497166]:     result = await self.handle_user_exception(error)
    hypercorn[497166]:   File "/root/lnbits/venv/lib/python3.8/site-packages/quart_trio/app.py", line 166, in handle_user_exception
    hypercorn[497166]:     return await super().handle_user_exception(error)
    hypercorn[497166]:   File "/root/lnbits/venv/lib/python3.8/site-packages/quart/app.py", line 1104, in handle_user_exception
    hypercorn[497166]:     raise error
    hypercorn[497166]:   File "/root/lnbits/venv/lib/python3.8/site-packages/quart_trio/app.py", line 151, in full_dispatch_request
    hypercorn[497166]:     result = await self.dispatch_request(request_context)
    hypercorn[497166]:   File "/root/lnbits/venv/lib/python3.8/site-packages/quart/app.py", line 1933, in dispatch_request
    hypercorn[497166]:     return await handler(**request_.view_args)
    hypercorn[497166]:   File "/root/lnbits/lnbits/decorators.py", line 28, in wrapped_view
    hypercorn[497166]:     return await view(**kwargs)
    hypercorn[497166]:   File "/root/lnbits/lnbits/core/views/api.py", line 313, in api_payments_sse
    hypercorn[497166]:     g.nursery.start_soon(payment_received)
    hypercorn[497166]:   File "/root/lnbits/venv/lib/python3.8/site-packages/trio/_core/_run.py", line 912, in start_soon
    hypercorn[497166]:     GLOBAL_RUN_CONTEXT.runner.spawn_impl(async_fn, args, self, name)
    hypercorn[497166]:   File "/root/lnbits/venv/lib/python3.8/site-packages/trio/_core/_run.py", line 1357, in spawn_impl
    hypercorn[497166]:     raise RuntimeError("Nursery is closed to new arrivals")
    hypercorn[497166]: RuntimeError: Nursery is closed to new arrivals