Search code examples
pythonzipfastapitemporary-files

Temporary zip two temporary files


I need to create two files and zip them (ALL TEMPORARY). So after return, there are no files left.

I tried putting the files into a temporary directory. I hoped that it would delete the directory along with the files after returning. But I get an error.

All in all, I need to return a file to a client. Without filling my servers' storage.

Here's the code

import zipfile
import tempfile
from utils.logging import logger
import shutil
from pandas_gbq import read_gbq

with tempfile.TemporaryDirectory() as dir:
    rawData_csv = rawData.to_csv(f"{client}_rawData.csv", index_label=False)
    dataScore_csv = dataScore.to_csv(f"{client}_dataScore.csv", index_label=False)
    shutil.move(f"./{client}_rawData.csv", dir)
    shutil.move(f"./{client}_dataScore.csv", dir)
    destinationFile = f"{client}.zip"
    password = ""
    compression_level = 5
    # with tempfile.TemporaryDirectory() as tdir:
    try:
        dir_path = dir  # holds the directory where script is located
        os.chdir(dir_path)  # Changes to directory where script is located
        fp = os.listdir(dir_path)  # file pointer
        directory_size = len(os.listdir(dir_path))
        zip1 = zipfile.ZipFile(f'{client}.zip', 'w')
        for i in range(directory_size):
            zip1.write(fp[i], compress_type=zipfile.ZIP_DEFLATED)
        # logger.info(zip1.filename)
        logger.info(os.path.dirname(os.path.abspath(zip1.filename)))
        logger.info(dir + "\\")
        logger.info(os.listdir(dir+"\\"))
        return FileResponse(
            # path=tdir + "\\" + destinationFile,
            path=dir,
            filename=f'{client}.zip'
        )
    except Exception as e:
        logger.exception(e)

Here's the error:

ERROR:    Exception in ASGI application
Traceback (most recent call last):
  File "C:\Users\korol\PycharmProjects\API-Integration\venv\lib\site-packages\uvicorn\protocols\http\h11_impl.py", line 396, in run_asgi
    result = await app(self.scope, self.receive, self.send)
  File "C:\Users\korol\PycharmProjects\API-Integration\venv\lib\site-packages\uvicorn\middleware\proxy_headers.py", line 45, in __call__
    return await self.app(scope, receive, send)
  File "C:\Users\korol\PycharmProjects\API-Integration\venv\lib\site-packages\fastapi\applications.py", line 199, in __call__
    await super().__call__(scope, receive, send)
  File "C:\Users\korol\PycharmProjects\API-Integration\venv\lib\site-packages\starlette\applications.py", line 112, in __call__
    await self.middleware_stack(scope, receive, send)
  File "C:\Users\korol\PycharmProjects\API-Integration\venv\lib\site-packages\starlette\middleware\errors.py", line 181, in __call__
    raise exc from None
  File "C:\Users\korol\PycharmProjects\API-Integration\venv\lib\site-packages\starlette\middleware\errors.py", line 159, in __call__
    await self.app(scope, receive, _send)
  File "C:\Users\korol\PycharmProjects\API-Integration\venv\lib\site-packages\starlette\exceptions.py", line 82, in __call__
    raise exc from None
  File "C:\Users\korol\PycharmProjects\API-Integration\venv\lib\site-packages\starlette\exceptions.py", line 71, in __call__
    await self.app(scope, receive, sender)
  File "C:\Users\korol\PycharmProjects\API-Integration\venv\lib\site-packages\starlette\routing.py", line 580, in __call__
    await route.handle(scope, receive, send)
  File "C:\Users\korol\PycharmProjects\API-Integration\venv\lib\site-packages\starlette\routing.py", line 241, in handle
    await self.app(scope, receive, send)
  File "C:\Users\korol\PycharmProjects\API-Integration\venv\lib\site-packages\starlette\routing.py", line 52, in app
    response = await func(request)
  File "C:\Users\korol\PycharmProjects\API-Integration\venv\lib\site-packages\fastapi\routing.py", line 201, in app
    raw_response = await run_endpoint_function(
  File "C:\Users\korol\PycharmProjects\API-Integration\venv\lib\site-packages\fastapi\routing.py", line 148, in run_endpoint_function
    return await dependant.call(**values)
  File "C:\Users\korol\PycharmProjects\API-Integration\app.py", line 142, in read_item
    return await bigTable(client_name)
  File "C:\Users\korol\PycharmProjects\API-Integration\app.py", line 91, in bigTable
    return FileResponse(
  File "C:\Users\korol\AppData\Local\Programs\Python\Python39\lib\tempfile.py", line 826, in __exit__
    self.cleanup()
  File "C:\Users\korol\AppData\Local\Programs\Python\Python39\lib\tempfile.py", line 830, in cleanup
    self._rmtree(self.name)
  File "C:\Users\korol\AppData\Local\Programs\Python\Python39\lib\tempfile.py", line 812, in _rmtree
    _shutil.rmtree(name, onerror=onerror)
  File "C:\Users\korol\AppData\Local\Programs\Python\Python39\lib\shutil.py", line 740, in rmtree
    return _rmtree_unsafe(path, onerror)
  File "C:\Users\korol\AppData\Local\Programs\Python\Python39\lib\shutil.py", line 618, in _rmtree_unsafe
    onerror(os.unlink, fullname, sys.exc_info())
  File "C:\Users\korol\AppData\Local\Programs\Python\Python39\lib\tempfile.py", line 804, in onerror
    cls._rmtree(path)
  File "C:\Users\korol\AppData\Local\Programs\Python\Python39\lib\tempfile.py", line 812, in _rmtree
    _shutil.rmtree(name, onerror=onerror)
  File "C:\Users\korol\AppData\Local\Programs\Python\Python39\lib\shutil.py", line 740, in rmtree
    return _rmtree_unsafe(path, onerror)
  File "C:\Users\korol\AppData\Local\Programs\Python\Python39\lib\shutil.py", line 599, in _rmtree_unsafe
    onerror(os.scandir, path, sys.exc_info())
  File "C:\Users\korol\AppData\Local\Programs\Python\Python39\lib\shutil.py", line 596, in _rmtree_unsafe
    with os.scandir(path) as scandir_it:
NotADirectoryError: [WinError 267] The directory name is invalid: 'C:\\Users\\korol\\AppData\\Local\\Temp\\tmp4pf2dew8tempdir\\Babtooma.zip'

Solution

  • I tried to reproduce the problem and this code gives exactly the same error:

    import zipfile
    import tempfile
    import shutil
    
    with tempfile.TemporaryDirectory() as dir:
        shutil.copy("c:\\temp\\test.txt", dir)
        zip1 = zipfile.ZipFile(dir + "\\test.zip", "w")
        zip1.write("c:\\temp\\test.txt")
        shutil.copy(dir + "\\test.zip", "c:\\temp")
    
    

    The error:

    ...
    NotADirectoryError: [WinError 267] The directory name is invalid: 'C:\\Users\\me\\AppData\\Local\\Temp\\tmplr21qjcj\\test.zip'
    

    I've added one line and the same code works fine now:

    import zipfile
    import tempfile
    import shutil
    
    with tempfile.TemporaryDirectory() as dir:
        shutil.copy("c:\\temp\\test.txt", dir)
        zip1 = zipfile.ZipFile(dir + "\\test.zip", "w")
        zip1.write("c:\\temp\\test.txt")
        zip1.close() # <------------------------------ here
        shutil.copy(dir + "\\test.zip", "c:\\temp")
    

    I wonder if you need as well to close the zip file right after write()?