The tempfile module creates temporary files and directories that clean up after themselves. Use it instead of manually managing /tmp files.

NamedTemporaryFile

Most common use case—a temp file with a name you can pass around:

import tempfile
 
# Auto-deleted when closed
with tempfile.NamedTemporaryFile(mode='w', suffix='.txt') as f:
    f.write('temporary data')
    f.flush()
    print(f.name)  # /tmp/tmpxyz123.txt
    # Pass f.name to other functions
# File deleted here

Keep the file after closing:

with tempfile.NamedTemporaryFile(delete=False) as f:
    path = f.name
    f.write(b'persistent temp data')
# File still exists at `path`
# You must delete it manually later

TemporaryDirectory

Creates a temp directory that deletes itself:

with tempfile.TemporaryDirectory() as tmpdir:
    print(tmpdir)  # /tmp/tmpxyz123
    # Create files inside
    (Path(tmpdir) / 'data.txt').write_text('hello')
# Entire directory deleted here

Great for test fixtures:

def test_file_processing():
    with tempfile.TemporaryDirectory() as tmpdir:
        input_file = Path(tmpdir) / 'input.csv'
        output_file = Path(tmpdir) / 'output.csv'
        
        input_file.write_text('a,b,c\n1,2,3')
        process_csv(input_file, output_file)
        
        assert output_file.exists()

SpooledTemporaryFile

Stays in memory until it exceeds a size threshold:

# In memory until > 10KB, then spills to disk
with tempfile.SpooledTemporaryFile(max_size=10240, mode='w+') as f:
    f.write('small data stays in RAM')
    f.seek(0)
    print(f.read())

Low-Level Functions

When you need more control:

# Create temp file, get file descriptor and path
fd, path = tempfile.mkstemp(suffix='.log')
try:
    os.write(fd, b'log data')
finally:
    os.close(fd)
    os.unlink(path)  # Manual cleanup
 
# Create temp directory
tmpdir = tempfile.mkdtemp(prefix='myapp_')
try:
    # Use tmpdir
    pass
finally:
    shutil.rmtree(tmpdir)  # Manual cleanup

Prefer context managers (NamedTemporaryFile, TemporaryDirectory) over these.

Configuration

# Get default temp directory
print(tempfile.gettempdir())  # /tmp on Unix, %TEMP% on Windows
 
# Create with custom directory
with tempfile.NamedTemporaryFile(dir='/var/cache/myapp') as f:
    pass
 
# Create with prefix
with tempfile.NamedTemporaryFile(prefix='myapp_') as f:
    print(f.name)  # /tmp/myapp_xyz123

Secure Temp Files

tempfile creates files securely:

  • Unpredictable names (prevents guessing)
  • Restrictive permissions (owner-only on Unix)
  • Race-condition safe (atomic creation)

Never do this:

# BAD: predictable name, race condition possible
open(f'/tmp/myapp_{os.getpid()}.txt', 'w')

Always use tempfile:

# GOOD: secure, unpredictable
with tempfile.NamedTemporaryFile() as f:
    pass

Practical Example: Safe File Processing

import tempfile
import shutil
from pathlib import Path
 
def safe_update(filepath: Path, transform_fn):
    """Update a file atomically using temp file."""
    content = filepath.read_text()
    new_content = transform_fn(content)
    
    # Write to temp file first
    with tempfile.NamedTemporaryFile(
        mode='w',
        dir=filepath.parent,  # Same filesystem for atomic move
        delete=False
    ) as tmp:
        tmp.write(new_content)
        tmp_path = tmp.name
    
    # Atomic replace
    shutil.move(tmp_path, filepath)
 
# Usage
safe_update(
    Path('config.json'),
    lambda x: x.replace('old_value', 'new_value')
)

Quick Reference

FunctionPurpose
NamedTemporaryFile()Temp file with accessible path
TemporaryFile()Temp file without name (most secure)
TemporaryDirectory()Self-cleaning temp directory
SpooledTemporaryFile()Memory-first, spills to disk
mkstemp()Low-level: returns (fd, path)
mkdtemp()Low-level: returns directory path
gettempdir()Get system temp directory

Always prefer context managers for automatic cleanup. Your future self will thank you when there's no temp file debris scattered across /tmp.

React to this post: