62

I have a python program that creates temporary directories under /temp by using tempfile.mkdtemp. Unfortunately, the Python program did not delete the directory after using it. So now the disk space is low.

Questions:

  1. How do I delete the temporary directories left under /temp manually? I tried to delete them manually but got "permission denied" error.
  2. In the Python program, how to delete temp directory after using them?
nbro
  • 15,395
  • 32
  • 113
  • 196
Yesheng Li
  • 621
  • 1
  • 5
  • 3
  • 3
    I don't think the OP's question was understood. The suggested code is a good example of what you should write in your program to clear out the temp dirs created. However, what if you application crashes (hard) without the chance to run that clean-up code? Then you'll have a temp dir kicking around that can only be deleted by the original process that created it (at least that what the docs seem to indicate) -- how is one supposed to clean that up? – Chris Barker Feb 07 '13 at 22:20
  • 1
    Did you try to use the root account/admin? – Bakuriu Feb 16 '15 at 13:29
  • Regarding 1 (deleting manually): it's a permissions problem: fix the permissions and delete, e.g.: `chmod -R +w /tmp/tmp0ytcxm9c && rm -fr /tmp/tmp0ytcxm9c` (if this is a permission error, you need to be the user that ran the program, or root). – Nils von Barth Jun 04 '16 at 04:11

5 Answers5

93

To manage resources (like files) in Python, best practice is to use the with keyword, which automatically releases the resources (i.e., cleans up, like closing files); this is available from Python 2.5.

From Python 3.2, you can use tempfile.TemporaryDirectory() instead of tempfile.mkdtmp() – this is usable in with and automatically cleans up the directory:

from tempfile import TemporaryDirectory

with TemporaryDirectory() as temp_dir:
    # ... do something with temp_dir
# automatically cleaned up when context exited

If you are using an earlier version of Python (at least 2.5, so have with), you can use backports.tempfile; see Nicholas Bishop’s answer to tempfile.TemporaryDirectory context manager in Python 2.7.

It’s easy and instructive to roll your own class, called a context manager. The return value of the __enter__() method is bound to the target of the as clause, while the __exit__() method is called when the context is exited – even by exception – and performs cleanup.

import shutil
import tempfile

class TemporaryDirectory(object):
    """Context manager for tempfile.mkdtemp() so it's usable with "with" statement."""
    def __enter__(self):
        self.name = tempfile.mkdtemp()
        return self.name

    def __exit__(self, exc_type, exc_value, traceback):
        shutil.rmtree(self.name)

You can simplify this with the @contextlib.contextmanager decorator, so you don’t need to write a context manager manually. The code prior to the yield is executed when entering the context, the yielded value is bound to the target of the as, and the code after the yield is executed when exiting the context. This is fundamentally a coroutine that encapsulates the resource acquisition and release, with the yield yielding control to the suite (body) of the with clause. Note that here you do need to have a try...finally block, as @contextlib.contextmanager does not catch exceptions in the yield – this just factors the resource management into a coroutine.

from contextlib import contextmanager
import tempfile
import shutil

@contextmanager
def TemporaryDirectory():
    name = tempfile.mkdtemp()
    try:
        yield name
    finally:
        shutil.rmtree(name)

As simplylizz notes, if you don’t mind the directory already being deleted (which the above code assumes does not happen), you can catch the “No such file or directory” exception as follows:

import errno
# ...
try:
    shutil.rmtree(self.name)
except OSError as e:
    # Reraise unless ENOENT: No such file or directory
    # (ok if directory has already been deleted)
    if e.errno != errno.ENOENT:
        raise

You can compare with the standard implementation in tempfile.py; even this simple class has had bugs and evolved over the years.

For background on with, see:

Nils von Barth
  • 3,239
  • 2
  • 26
  • 27
  • 1
    You could also use [backports.tempfile](https://stackoverflow.com/questions/19296146/tempfile-temporarydirectory-context-manager-in-python-2-7/39628795#39628795) – Frank Kusters Dec 21 '16 at 21:03
35

Read the documentation, it's simple. ;) From the docs: the directory is readable, writable, and searchable only by the creating user ID.

To delete temp directory try something like this:

import errno
import shutil
import tempfile

try:
    tmp_dir = tempfile.mkdtemp()  # create dir
    # ... do something
finally:
    try:
        shutil.rmtree(tmp_dir)  # delete directory
    except OSError as exc:
        if exc.errno != errno.ENOENT:  # ENOENT - no such file or directory
            raise  # re-raise exception

Also you can try tempdir package or see its sources.

simplylizz
  • 1,686
  • 14
  • 28
  • 6
    this does not seem to be working. I got "Permission denied" error when running it. Also, I have many tmp directories on disk that I want to delete. I can not manually delete them also. What is the proper way to delete trees created by mkdtemp? thanks. – Yesheng Li Aug 01 '11 at 18:18
  • Maybe the problem in the value of umask on your system? You can see it in the umask command output, try to change it to 022 by executing: umask 022 and then try my code again. – simplylizz Aug 02 '11 at 22:01
  • 4
    FWIW, your answer is nicer than the documentation. – Erik Garrison Mar 24 '14 at 14:00
  • This is a good answer. Note, however, that the tempdir doc link is currently dead. – Ami Tavory Apr 24 '16 at 12:11
5

I have had the same/similar problem using TemporaryDirectory() which is basically covering the functionality you defined above.

My problem was due to the usage of the temporary directory. I used to populate the content by cloning a git repository, it happened that there were read-only files created during the process and with a normal exit these read-only temp files were causing the complete temporary directory to stay there.

Did inherit the TemporaryDirectory to my own class and did override the class method _cleanup with the following code.

The code before super() might be optimized but for me, the performance was not the problem.

I did use the force and read the source of "tempfile"

import tempfile
import shutil
import stat 

class myTempDir(tempfile.TemporaryDirectory):
    @classmethod
    def _cleanup(self,name, warn_message):
        for root, dirs, files in os.walk(name):
            for fname in files:
                full_path = os.path.join(root, fname)
                os.chmod(full_path ,stat.S_IWRITE)
        super()

Solution worked for Windows 10 with Python 3

Ali Avcı
  • 870
  • 5
  • 8
0

I think the user is responsible for deleting the temporary directory and its content created by using tempfile.mkdtemp(). it will not deleted automatically just like temporary file. There are many ways you can delete the directory

If the directory is empty you can use

`os.removedirs or os.rmdir`

Note it can be used only if the directory is empty otherwise will raise

OSError

This will delete the entire directory path:

import shutil    
shutil.rmtree('/path/to/your/dir/')

be careful while using this, it will delete the whole directory and files inside it.

dportman
  • 1,101
  • 10
  • 20
mohammed wazeem
  • 1,310
  • 1
  • 10
  • 26
0

An alternative to the with statement could be:

import tempfile
tmp_dir = tempfile.TemporaryDirectory()
print(tmp_dir.name)
# Your code Here
tmp_dir.cleanup()
Julia Meshcheryakova
  • 3,162
  • 3
  • 22
  • 42