uvicorn
uvicorn copied to clipboard
asyncio.exceptions.CancelledError with asyncio
Initial Checks
- [X] I confirm this was discussed, and the maintainers suggest I open an issue.
- [X] I'm aware that if I created this issue without a discussion, it may be closed without a response.
Discussion Link
yes
Description
I am building a tkinter gui and in the background host a fastapi and uvicorn server for static files. here i want to exit program when hit system tray menu ,it do but a lot of error related to how i start a uvicorn server with asyncio
INFO: Started server process [4692]
INFO: Waiting for application startup.
INFO: Application startup complete.
INFO: Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)
shutdown icon
shutdown server
INFO: Shutting down
INFO: Shutting down
shutdown root
shutdown loop
An error occurred when calling message handler
Traceback (most recent call last):
File "D:\program\miniconda\lib\site-packages\pystray\_win32.py", line 412, in _dispatcher
return int(icon._message_handlers.get(
File "D:\program\miniconda\lib\site-packages\pystray\_win32.py", line 224, in _on_notify
descriptors[index - 1](self)
File "D:\program\miniconda\lib\site-packages\pystray\_base.py", line 328, in inner
callback(self)
File "D:\program\miniconda\lib\site-packages\pystray\_base.py", line 453, in __call__
return self._action(icon, self)
File "D:\workspace\tiktoka\tiktoka-studio-uploader-genius\t.py", line 65, in quit_window
loop.close()
File "D:\program\miniconda\lib\asyncio\proactor_events.py", line 681, in close
raise RuntimeError("Cannot close a running event loop")
RuntimeError: Cannot close a running event loop
Traceback (most recent call last):
File "D:\workspace\tiktoka\tiktoka-studio-uploader-genius\t.py", line 128, in <module>
loop.run_forever()
File "D:\program\miniconda\lib\asyncio\windows_events.py", line 319, in run_forever
ERROR: Traceback (most recent call last):
File "D:\program\miniconda\lib\site-packages\starlette\routing.py", line 686, in lifespan
await receive()
File "D:\program\miniconda\lib\site-packages\uvicorn\lifespan\on.py", line 137, in receive
return await self.receive_queue.get()
File "D:\program\miniconda\lib\asyncio\queues.py", line 159, in get
await getter
asyncio.exceptions.CancelledError
assert self._self_reading_future is None
AssertionError
Exception in thread Thread-1 (start_fastapi_server):
Traceback (most recent call last):
File "D:\program\miniconda\lib\site-packages\uvicorn\server.py", line 82, in serve
await self.shutdown(sockets=sockets)
File "D:\program\miniconda\lib\site-packages\uvicorn\server.py", line 275, in shutdown
await asyncio.sleep(0.1)
File "D:\program\miniconda\lib\asyncio\tasks.py", line 605, in sleep
return await future
asyncio.exceptions.CancelledError
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "D:\program\miniconda\lib\threading.py", line 1016, in _bootstrap_inner
self.run()
File "D:\program\miniconda\lib\threading.py", line 953, in run
self._target(*self._args, **self._kwargs)
File "D:\workspace\tiktoka\tiktoka-studio-uploader-genius\t.py", line 88, in start_fastapi_server
loop.run_until_complete(server.serve())
File "D:\program\miniconda\lib\asyncio\base_events.py", line 649, in run_until_complete
return future.result()
asyncio.exceptions.CancelledError
Example Code
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
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()
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())
try:
tasks = asyncio.all_tasks(loop)
for task in tasks:
task.cancel()
except RuntimeError as err:
print('SIGINT or SIGTSTP raised')
print("cleaning and exiting")
sys.exit(1)
print('shutdown root')
root.destroy()
print('shutdown loop')
loop.close()
# loop.stop()
# loop.run_until_complete(asyncio.gather(*[shutdown()]))
# 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)
loop.run_until_complete(server.serve())
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()
### Python, Uvicorn & OS Version
```Text
Running uvicorn 0.24.0.post1 with CPython 3.10.10 on Windows
[!IMPORTANT]
- We're using Polar.sh so you can upvote and help fund this issue.
- We receive the funding once the issue is completed & confirmed by you.
- Thank you in advance for helping prioritize & fund our backlog.