0

How Do I Delete Local Files on Session Close?

My app allows users to upload a file and request some server-side stuff be done to it. Awesome. However, I don't want these files to stay there. Looking at the documentation, something like this should work (sanitized to protect the innocent)...

from shiny import App, reactive, render, ui
import os

def server(input, output, session):
     def delete_uploaded_file():
        try:
            os.remove('file.xlsx')))
        except:
            # If there isn't a file, it's not really a problem
            pass

    # This triggers at the end of a session
    session.on_ended(delete_uploaded_file())

    # this closes the session when the user exits out on their browser
    @reactive.Effect
    @reactive.event(input.close)
    async def _():
        await session.close()

app = App(app_ui, server)

but it yields an 'Exception in ASGI application' and a 'TypeError,' all without triggering any of the above code. Everything in the traceback seems to point to shiny, so what am I doing wrong here?

ERROR:    Exception in ASGI application
Traceback (most recent call last):
  File "C:\Users\username\AppData\Roaming\Python\Python39\site-packages\uvicorn\protocols\websockets\websockets_impl.py", line 238, in run_asgi
    result = await self.app(self.scope, self.asgi_receive, self.asgi_send)
  File "C:\Users\e365627\AppData\Roaming\Python\Python39\site-packages\uvicorn\middleware\proxy_headers.py", line 78, in __call__
    return await self.app(scope, receive, send)
  File "C:\Users\username\AppData\Roaming\Python\Python39\site-packages\shiny\_app.py", line 220, in __call__
    await self.starlette_app(scope, receive, send)
  File "C:\Users\username\AppData\Roaming\Python\Python39\site-packages\starlette\applications.py", line 124, in __call__
    await self.middleware_stack(scope, receive, send)
  File "C:\Users\username\AppData\Roaming\Python\Python39\site-packages\starlette\middleware\errors.py", line 149, in __call__
    await self.app(scope, receive, send)
  File "C:\Users\username\AppData\Roaming\Python\Python39\site-packages\shiny\_autoreload.py", line 114, in __call__
    return await self.app(scope, receive, send)
  File "C:\Users\username\AppData\Roaming\Python\Python39\site-packages\starlette\middleware\exceptions.py", line 79, in __call__
    raise exc
  File "C:\Users\username\AppData\Roaming\Python\Python39\site-packages\starlette\middleware\exceptions.py", line 68, in __call__
    await self.app(scope, receive, sender)
  File "C:\Users\username\AppData\Roaming\Python\Python39\site-packages\starlette\routing.py", line 706, in __call__
    await route.handle(scope, receive, send)
  File "C:\Users\username\AppData\Roaming\Python\Python39\site-packages\starlette\routing.py", line 341, in handle
    await self.app(scope, receive, send)
  File "C:\Users\username\AppData\Roaming\Python\Python39\site-packages\starlette\routing.py", line 82, in app
    await func(session)
  File "C:\Users\username\AppData\Roaming\Python\Python39\site-packages\shiny\_app.py", line 294, in _on_connect_cb
    await session._run()
  File "C:\Users\username\AppData\Roaming\Python\Python39\site-packages\shiny\session\_session.py", line 326, in _run
    self._run_session_end_tasks()
  File "C:\Users\username\AppData\Roaming\Python\Python39\site-packages\shiny\session\_session.py", line 228, in _run_session_end_tasks
    self._on_ended_callbacks.invoke()
  File "C:\Users\username\AppData\Python\Python39\site-packages\shiny\_utils.py", line 335, in invoke
    fn()
TypeError: 'NoneType' object is not callable
INFO:     connection closed
PipperChip
  • 141
  • 1
  • 1
  • 8

2 Answers2

0

What if you try:

from shiny import App, reactive, render, ui
import os

def server(input, output, session):
     def delete_uploaded_file():
        try:
            os.remove('file.xlsx')))
        except:
            # If there isn't a file, it's not really a problem
            pass


    # this closes the session when the user exits out on their browser
    @reactive.Effect
    @reactive.event(input.close)
    async def _():
        delete_uploaded_file()
        await session.close()

app = App(app_ui, server)

So your fuction is executed before the session is closed

abe_mercy
  • 36
  • 2
0

Remove the parenthesis after the function name:

session.on_ended(delete_uploaded_file())

should be

session.on_ended(delete_uploaded_file)

jesliu
  • 11
  • 1