Code Monkey home page Code Monkey logo

Comments (4)

kenn avatar kenn commented on June 18, 2024 2

This issue shows up repeatedly (like #1160 ), and I hope it gets an attention.

Here's a workaround to silence this verbose error messages at exit.

Hope it helps!

# Monkey patching to silence verbose error at uvicorn exit
# Put this code at the end of main.py

if is_dev_environment:
    get = asyncio.Queue.get

    async def new_get(self):
        try:
            return await get(self)
        except asyncio.exceptions.CancelledError:
            pass

    asyncio.Queue.get = new_get

from uvicorn.

wanghaisheng avatar wanghaisheng commented on June 18, 2024
import sys
import threading
from fastapi import FastAPI
from fastapi.responses import FileResponse

from fastapi.staticfiles import StaticFiles
from fastapi.middleware.cors import CORSMiddleware
from pystray import MenuItem as item
import pystray
from PIL import Image, ImageTk
import asyncio
import tkinter as tk
from asyncio import CancelledError
from contextlib import suppress

app = FastAPI()
# Allow all origins
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],  # You can replace this with specific origins if needed
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

def start(lang, root=None, async_loop=None):
    global mainwindow, canvas

    # root.resizable(width=True, height=True)
    root.iconbitmap("assets/icon.ico")
    root.title('tkinter asyncio demo')


    root.update_idletasks()

async def wait():


    try:
        tasks = asyncio.all_tasks(loop)
        print(f'========{tasks}')
        for task in tasks:
            try:
                # await asyncio.sleep(3600)
                await task.cancel()                
            except asyncio.exceptions.CancelledError:
                print("done")


    except RuntimeError as err:
        print('SIGINT or SIGTSTP raised')
        print("cleaning and exiting")
        sys.exit(1)    

def quit_window(icon, item):
    global loop,fastapi_thread

    print('shutdown icon')

    icon.stop()



    print('shutdown server')
    server.should_exit = True
    server.force_exit = True
    asyncio.run(server.shutdown())

    print(f'0:{asyncio.all_tasks(loop)}')
    try:
        if loop.is_running():
            # _logger.debug("Asked running asyncio loop to stop.")
            loop.call_soon_threadsafe(loop.stop)        
            tasks = asyncio.all_tasks(loop)
            print(tasks,'========')
            for task in tasks:
                try:
                    # await asyncio.sleep(3600)
                    task.cancel()           
                    with suppress(CancelledError):
                        loop.run_until_complete(task)
                except asyncio.exceptions.CancelledError:
                    print("done")


    except RuntimeError as err:
        print('SIGINT or SIGTSTP raised')
        print("cleaning and exiting")
        sys.exit(1)    
    print('shutdown root')

    root.destroy()

    asyncio.run(wait())

    print('close loop')



    print(f'1:{asyncio.all_tasks(loop)}')
    # loop.close()
    print('stop loop')

    loop.stop()
    # loop.run_until_complete(asyncio.gather(*[shutdown()]))
    # import os
    # os._exit(0)

def show_window(icon, item):
    icon.stop()
    root.after(0, root.deiconify)


def withdraw_window():
    root.withdraw()
    image = Image.open("assets/icon.ico")
    menu = (item("Quit", quit_window), item("Show", show_window))
    icon = pystray.Icon("name", image, "title", menu)
    # icon.run_detached()
    icon.run()

def start_fastapi_server(loop):
    import uvicorn
    global server
    config = uvicorn.Config(app, loop=loop, host="0.0.0.0", port=8000)
    server = uvicorn.Server(config)
    try:
        loop.run_until_complete(server.serve())
    except KeyboardInterrupt:
        print("Received Ctrl+C. Stopping gracefully...")
        # Cancel all running tasks
        for task in asyncio.Task.all_tasks():
            task.cancel()
        # Optionally: Close any open resources (sockets, files, etc.)
        # Cleanup code here
    finally:
        loop.close()




def start_tkinter_app(async_loop):
    global root, settings, db, canvas, locale
    root = tk.Tk()

    locale = 'en'
    start(locale, root, async_loop)

    root.protocol('WM_DELETE_WINDOW', withdraw_window)


    root.mainloop()




if __name__ == "__main__":
    global loop,fastapi_thread
    loop=None
    if sys.platform == 'win32':
        asyncio.get_event_loop().close()
        # On Windows, the default event loop is SelectorEventLoop, which does
        # not support subprocesses. ProactorEventLoop should be used instead.
        # Source: https://docs.python.org/3/library/asyncio-subprocess.html
        loop = asyncio.ProactorEventLoop()
        asyncio.set_event_loop(loop)
    else:
        loop = asyncio.get_event_loop()

    # Start FastAPI server in a separate thread
    fastapi_thread = threading.Thread(target=start_fastapi_server,args=(
            loop,)).start()


    start_tkinter_app(loop)
    loop.run_forever()
    loop.close()

from uvicorn.

RobertCall avatar RobertCall commented on June 18, 2024

I have same effect then trying to close server from inside

Example code

from fastapi import FastAPI
import uvicorn


class ServerRunner:
    def __init__(self):
        self.app = FastAPI()

        @self.app.get("/close")
        async def close():
            self.server.force_exit = True
            self.server.should_exit = True
            await self.server.shutdown()

        config = uvicorn.Config(self.app, host='0.0.0.0', port=5432, forwarded_allow_ips='*')
        self.server = uvicorn.Server(config)

    def run(self):
        self.server.run()


if __name__ == '__main__':
    runner = ServerRunner()
    runner.run()

Output

INFO:     Started server process [3840]
INFO:     Waiting for application startup.
INFO:     Application startup complete.
INFO:     Uvicorn running on http://0.0.0.0:5432 (Press CTRL+C to quit)
INFO:     127.0.0.1:58584 - "GET /close HTTP/1.1" 200 OK
INFO:     Shutting down
INFO:     Finished server process [3840]
ERROR:    Traceback (most recent call last):
  File "D:\Projects\some_project\venv310\lib\site-packages\starlette\routing.py", line 686, in lifespan
    await receive()
  File "D:\Projects\some_project\venv310\lib\site-packages\uvicorn\lifespan\on.py", line 137, in receive
    return await self.receive_queue.get()
  File "C:\Users\user\AppData\Local\Programs\Python\Python310\lib\asyncio\queues.py", line 159, in get
    await getter
asyncio.exceptions.CancelledError


Process finished with exit code 0

Versions

(venv310) PS D:\Projects\some_project> python --version
Python 3.10.11
(venv310) PS D:\Projects\some_project> pip show uvicorn
Name: uvicorn
Version: 0.25.0

from uvicorn.

Kludex avatar Kludex commented on June 18, 2024

I'll close this since I can't run the provided code. Please create a minimal, reproducible, example.

from uvicorn.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.