vedar
vedar

Reputation: 523

Context manager to remove tempfile

I'm trying to write context manager to conditionally cleanup tempfile after processing. Simplified:

import os
from contextlib import contextmanager
from subprocess import Popen
from tempfile import NamedTemporaryFile


@contextmanager
def temp(cleanup=True):
    tmp = NamedTemporaryFile(delete=False)
    try:
        yield tmp
    finally:
        cleanup and os.remove(tmp.name)

with temp() as tmp:
    tmp.write(b'Hi')
    p = Popen(['cmd', '/c', 'type', tmp.name])
    p.wait()

Trying this script raises:

Traceback (most recent call last):
  File "C:\temp\test.py", line 18, in <module>
    p.wait()
  File "C:\Python35\lib\contextlib.py", line 66, in __exit__
    next(self.gen)
  File "C:\temp\test.py", line 13, in temp
    cleanup and os.remove(tmp.name)
PermissionError: [WinError 32] The process cannot access the file because it is being used by another process: 'C:\\Temp\\tmp79su99sg'

I would expect that tempfile is freed at the end of with statement cycle, while apparently it is not.

Upvotes: 6

Views: 6829

Answers (2)

Martin Thoma
Martin Thoma

Reputation: 136605

You can use NamedTemporaryFile as a context manager:

from tempfile import NamedTemporaryFile

with NamedTemporaryFile() as tmp:
    tmp.write(b'Hi')
    p = Popen(['cmd', '/c', 'type', tmp.name])
    p.wait()
# Here the file is closed and thus deleted

Upvotes: 14

Aviad
Aviad

Reputation: 349

Indeed your file is open when you are trying to remove it. You'll have to close the file first before removing it:

@contextmanager
def temp(cleanup=True):
    tmp = NamedTemporaryFile(delete=False)
    try:
        yield tmp
    finally:
        tmp.close() #closes the file, so we can right remove it
        cleanup and os.remove(tmp.name)

Another option is to wrap the file-object with a context-manager:

@contextmanager
def temp(cleanup=True):
    tmp = NamedTemporaryFile(delete=False)
    try:
        with tmp:
            yield tmp
    finally:
        cleanup and os.remove(tmp.name)

Upvotes: 5

Related Questions