tempfile.py 17.9 KB
Newer Older
1
"""Temporary files.
2

3 4 5 6 7
This module provides generic, low- and high-level interfaces for
creating temporary files and directories.  The interfaces listed
as "safe" just below can be used without fear of race conditions.
Those listed as "unsafe" cannot, and are provided for backward
compatibility only.
Guido van Rossum's avatar
Guido van Rossum committed
8

9
This module also provides some data items to the user:
Guido van Rossum's avatar
Guido van Rossum committed
10

11 12 13 14 15 16 17 18 19 20 21
  TMP_MAX  - maximum number of names that will be tried before
             giving up.
  template - the default prefix for all temporary names.
             You may change this to control the default prefix.
  tempdir  - If this is set to a string before the first use of
             any routine from this module, it will be considered as
             another candidate location to store temporary files.
"""

__all__ = [
    "NamedTemporaryFile", "TemporaryFile", # high level safe interfaces
22
    "SpooledTemporaryFile",
23 24 25 26 27 28 29 30 31 32 33 34 35 36
    "mkstemp", "mkdtemp",                  # low level safe interfaces
    "mktemp",                              # deprecated unsafe interface
    "TMP_MAX", "gettempprefix",            # constants
    "tempdir", "gettempdir"
   ]


# Imports.

import os as _os
import errno as _errno
from random import Random as _Random

if _os.name == 'mac':
Jack Jansen's avatar
Jack Jansen committed
37 38
    import Carbon.Folder as _Folder
    import Carbon.Folders as _Folders
39

40
try:
41
    from cStringIO import StringIO as _StringIO
42
except:
43
    from StringIO import StringIO as _StringIO
44

45 46
try:
    import fcntl as _fcntl
47
except ImportError:
48 49 50
    def _set_cloexec(fd):
        pass
else:
51
    def _set_cloexec(fd):
52 53 54 55
        try:
            flags = _fcntl.fcntl(fd, _fcntl.F_GETFD, 0)
        except IOError:
            pass
56
        else:
57 58 59
            # flags read successfully, modify
            flags |= _fcntl.FD_CLOEXEC
            _fcntl.fcntl(fd, _fcntl.F_SETFD, flags)
60

61 62 63

try:
    import thread as _thread
64 65 66
except ImportError:
    import dummy_thread as _thread
_allocate_lock = _thread.allocate_lock
67 68

_text_openflags = _os.O_RDWR | _os.O_CREAT | _os.O_EXCL
Tim Peters's avatar
Tim Peters committed
69 70 71 72
if hasattr(_os, 'O_NOINHERIT'):
    _text_openflags |= _os.O_NOINHERIT
if hasattr(_os, 'O_NOFOLLOW'):
    _text_openflags |= _os.O_NOFOLLOW
73 74

_bin_openflags = _text_openflags
Tim Peters's avatar
Tim Peters committed
75 76
if hasattr(_os, 'O_BINARY'):
    _bin_openflags |= _os.O_BINARY
77 78 79 80 81 82

if hasattr(_os, 'TMP_MAX'):
    TMP_MAX = _os.TMP_MAX
else:
    TMP_MAX = 10000

83
template = "tmp"
84

85
tempdir = None
86

87 88 89 90
# Internal routines.

_once_lock = _allocate_lock()

91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
if hasattr(_os, "lstat"):
    _stat = _os.lstat
elif hasattr(_os, "stat"):
    _stat = _os.stat
else:
    # Fallback.  All we need is something that raises os.error if the
    # file doesn't exist.
    def _stat(fn):
        try:
            f = open(fn)
        except IOError:
            raise _os.error
        f.close()

def _exists(fn):
    try:
        _stat(fn)
    except _os.error:
        return False
    else:
        return True

113 114 115 116 117 118 119 120
class _RandomNameSequence:
    """An instance of _RandomNameSequence generates an endless
    sequence of unpredictable strings which can safely be incorporated
    into file names.  Each string is six characters long.  Multiple
    threads can safely use the same instance at the same time.

    _RandomNameSequence is an iterator."""

121 122
    characters = ("abcdefghijklmnopqrstuvwxyz" +
                  "ABCDEFGHIJKLMNOPQRSTUVWXYZ" +
123
                  "0123456789_")
124 125 126 127 128

    def __init__(self):
        self.mutex = _allocate_lock()
        self.rng = _Random()
        self.normcase = _os.path.normcase
129

130 131 132 133 134 135
    def __iter__(self):
        return self

    def next(self):
        m = self.mutex
        c = self.characters
136
        choose = self.rng.choice
137

138
        m.acquire()
139
        try:
140
            letters = [choose(c) for dummy in "123456"]
141 142 143
        finally:
            m.release()

144
        return self.normcase(''.join(letters))
145 146 147 148 149 150 151 152

def _candidate_tempdir_list():
    """Generate a list of candidate temporary directories which
    _get_default_tempdir will try."""

    dirlist = []

    # First, try the environment.
153
    for envname in 'TMPDIR', 'TEMP', 'TMP':
154 155 156 157 158
        dirname = _os.getenv(envname)
        if dirname: dirlist.append(dirname)

    # Failing that, try OS-specific locations.
    if _os.name == 'mac':
159
        try:
Jack Jansen's avatar
Jack Jansen committed
160 161 162
            fsr = _Folder.FSFindFolder(_Folders.kOnSystemDisk,
                                              _Folders.kTemporaryFolderType, 1)
            dirname = fsr.as_pathname()
163
            dirlist.append(dirname)
Jack Jansen's avatar
Jack Jansen committed
164
        except _Folder.error:
165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
            pass
    elif _os.name == 'riscos':
        dirname = _os.getenv('Wimp$ScrapDir')
        if dirname: dirlist.append(dirname)
    elif _os.name == 'nt':
        dirlist.extend([ r'c:\temp', r'c:\tmp', r'\temp', r'\tmp' ])
    else:
        dirlist.extend([ '/tmp', '/var/tmp', '/usr/tmp' ])

    # As a last resort, the current directory.
    try:
        dirlist.append(_os.getcwd())
    except (AttributeError, _os.error):
        dirlist.append(_os.curdir)

    return dirlist
Tim Peters's avatar
Tim Peters committed
181

182 183
def _get_default_tempdir():
    """Calculate the default directory to use for temporary files.
184
    This routine should be called exactly once.
185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204

    We determine whether or not a candidate temp dir is usable by
    trying to create and write to a file in that directory.  If this
    is successful, the test file is deleted.  To prevent denial of
    service, the name of the test file must be randomized."""

    namer = _RandomNameSequence()
    dirlist = _candidate_tempdir_list()
    flags = _text_openflags

    for dir in dirlist:
        if dir != _os.curdir:
            dir = _os.path.normcase(_os.path.abspath(dir))
        # Try only a few names per directory.
        for seq in xrange(100):
            name = namer.next()
            filename = _os.path.join(dir, name)
            try:
                fd = _os.open(filename, flags, 0600)
                fp = _os.fdopen(fd, 'w')
Tim Peters's avatar
Tim Peters committed
205 206
                fp.write('blat')
                fp.close()
207 208 209 210 211 212 213 214 215
                _os.unlink(filename)
                del fp, fd
                return dir
            except (OSError, IOError), e:
                if e[0] != _errno.EEXIST:
                    break # no point trying more names in this directory
                pass
    raise IOError, (_errno.ENOENT,
                    ("No usable temporary directory found in %s" % dirlist))
216

217 218
_name_sequence = None

219 220
def _get_candidate_names():
    """Common setup sequence for all user-callable interfaces."""
221

222 223 224 225 226 227 228 229
    global _name_sequence
    if _name_sequence is None:
        _once_lock.acquire()
        try:
            if _name_sequence is None:
                _name_sequence = _RandomNameSequence()
        finally:
            _once_lock.release()
230 231 232 233 234 235 236 237 238 239 240 241 242 243
    return _name_sequence


def _mkstemp_inner(dir, pre, suf, flags):
    """Code common to mkstemp, TemporaryFile, and NamedTemporaryFile."""

    names = _get_candidate_names()

    for seq in xrange(TMP_MAX):
        name = names.next()
        file = _os.path.join(dir, pre + name + suf)
        try:
            fd = _os.open(file, flags, 0600)
            _set_cloexec(fd)
244
            return (fd, _os.path.abspath(file))
245 246 247 248 249 250
        except OSError, e:
            if e.errno == _errno.EEXIST:
                continue # try again
            raise

    raise IOError, (_errno.EEXIST, "No usable temporary file name found")
Tim Peters's avatar
Tim Peters committed
251

252 253

# User visible interfaces.
254

255
def gettempprefix():
256 257 258
    """Accessor for tempdir.template."""
    return template

259 260
tempdir = None

261 262
def gettempdir():
    """Accessor for tempdir.tempdir."""
263 264 265 266 267 268 269 270
    global tempdir
    if tempdir is None:
        _once_lock.acquire()
        try:
            if tempdir is None:
                tempdir = _get_default_tempdir()
        finally:
            _once_lock.release()
271 272
    return tempdir

273
def mkstemp(suffix="", prefix=template, dir=None, text=False):
274
    """mkstemp([suffix, [prefix, [dir, [text]]]])
275 276 277 278 279 280 281 282 283 284 285 286 287
    User-callable function to create and return a unique temporary
    file.  The return value is a pair (fd, name) where fd is the
    file descriptor returned by os.open, and name is the filename.

    If 'suffix' is specified, the file name will end with that suffix,
    otherwise there will be no suffix.

    If 'prefix' is specified, the file name will begin with that prefix,
    otherwise a default prefix is used.

    If 'dir' is specified, the file will be created in that directory,
    otherwise a default directory is used.

288 289 290
    If 'text' is specified and true, the file is opened in text
    mode.  Else (the default) the file is opened in binary mode.  On
    some operating systems, this makes no difference.
291 292 293 294 295

    The file is readable and writable only by the creating user ID.
    If the operating system uses permission bits to indicate whether a
    file is executable, the file is executable by no one. The file
    descriptor is not inherited by children of this process.
296

297
    Caller is responsible for deleting the file when done with it.
298 299
    """

300 301 302
    if dir is None:
        dir = gettempdir()

303
    if text:
304
        flags = _text_openflags
305 306
    else:
        flags = _bin_openflags
307

308
    return _mkstemp_inner(dir, prefix, suffix, flags)
Guido van Rossum's avatar
Guido van Rossum committed
309

310

311
def mkdtemp(suffix="", prefix=template, dir=None):
312 313 314 315
    """mkdtemp([suffix, [prefix, [dir]]])
    User-callable function to create and return a unique temporary
    directory.  The return value is the pathname of the directory.

316
    Arguments are as for mkstemp, except that the 'text' argument is
317 318 319 320 321 322 323 324
    not accepted.

    The directory is readable, writable, and searchable only by the
    creating user.

    Caller is responsible for deleting the directory when done with it.
    """

325 326 327
    if dir is None:
        dir = gettempdir()

328
    names = _get_candidate_names()
Tim Peters's avatar
Tim Peters committed
329

330 331 332 333 334
    for seq in xrange(TMP_MAX):
        name = names.next()
        file = _os.path.join(dir, prefix + name + suffix)
        try:
            _os.mkdir(file, 0700)
335
            return file
336 337 338 339
        except OSError, e:
            if e.errno == _errno.EEXIST:
                continue # try again
            raise
340

341
    raise IOError, (_errno.EEXIST, "No usable temporary directory name found")
342

343
def mktemp(suffix="", prefix=template, dir=None):
344 345 346
    """mktemp([suffix, [prefix, [dir]]])
    User-callable function to return a unique temporary file name.  The
    file is not created.
347

348
    Arguments are as for mkstemp, except that the 'text' argument is
349 350 351 352 353 354
    not accepted.

    This function is unsafe and should not be used.  The file name
    refers to a file that did not exist at some point, but by the time
    you get around to creating it, someone else may have beaten you to
    the punch.
355
    """
356

357 358 359
##    from warnings import warn as _warn
##    _warn("mktemp is a potential security risk to your program",
##          RuntimeWarning, stacklevel=2)
360

361 362 363
    if dir is None:
        dir = gettempdir()

364 365 366 367
    names = _get_candidate_names()
    for seq in xrange(TMP_MAX):
        name = names.next()
        file = _os.path.join(dir, prefix + name + suffix)
368
        if not _exists(file):
369 370 371
            return file

    raise IOError, (_errno.EEXIST, "No usable temporary filename found")
372

373

374 375 376 377 378 379 380
class _TemporaryFileWrapper:
    """Temporary file wrapper

    This class provides a wrapper around files opened for
    temporary use.  In particular, it seeks to automatically
    remove the file when it is no longer needed.
    """
381

382
    def __init__(self, file, name, delete=True):
383 384
        self.file = file
        self.name = name
385
        self.close_called = False
386
        self.delete = delete
387 388

    def __getattr__(self, name):
389 390 391
        # Attribute lookups are delegated to the underlying file
        # and cached for non-numeric results
        # (i.e. methods are cached, closed and friends are not)
392 393
        file = self.__dict__['file']
        a = getattr(file, name)
394
        if not issubclass(type(a), type(0)):
395
            setattr(self, name, a)
396
        return a
397

398 399 400 401 402 403
    # The underlying __enter__ method returns the wrong object
    # (self.file) so override it to return the wrapper
    def __enter__(self):
        self.file.__enter__()
        return self

404 405 406 407 408 409 410 411 412 413 414 415 416
    # NT provides delete-on-close as a primitive, so we don't need
    # the wrapper to do anything special.  We still use it so that
    # file.name is useful (i.e. not "(fdopen)") with NamedTemporaryFile.
    if _os.name != 'nt':
        # Cache the unlinker so we don't get spurious errors at
        # shutdown when the module-level "os" is None'd out.  Note
        # that this must be referenced as self.unlink, because the
        # name TemporaryFileWrapper may also get None'd out before
        # __del__ is called.
        unlink = _os.unlink

        def close(self):
            if not self.close_called:
417
                self.close_called = True
418
                self.file.close()
419 420
                if self.delete:
                    self.unlink(self.name)
421 422 423 424

        def __del__(self):
            self.close()

425 426 427 428 429 430 431 432
        # Need to trap __exit__ as well to ensure the file gets
        # deleted when used in a with statement
        def __exit__(self, exc, value, tb):
            result = self.file.__exit__(exc, value, tb)
            self.close()
            return result


433
def NamedTemporaryFile(mode='w+b', bufsize=-1, suffix="",
434
                       prefix=template, dir=None, delete=True):
435 436 437 438 439
    """Create and return a temporary file.
    Arguments:
    'prefix', 'suffix', 'dir' -- as for mkstemp.
    'mode' -- the mode argument to os.fdopen (default "w+b").
    'bufsize' -- the buffer size argument to os.fdopen (default -1).
440
    'delete' -- whether the file is deleted on close (default True).
441 442
    The file is created as mkstemp() would do it.

443 444
    Returns an object with a file-like interface; the name of the file
    is accessible as file.name.  The file will be automatically deleted
445
    when it is closed unless the 'delete' argument is set to False.
446
    """
447

448 449 450
    if dir is None:
        dir = gettempdir()

451 452 453 454
    if 'b' in mode:
        flags = _bin_openflags
    else:
        flags = _text_openflags
455

456 457
    # Setting O_TEMPORARY in the flags causes the OS to delete
    # the file when it is closed.  This is only supported by Windows.
458
    if _os.name == 'nt' and delete:
459
        flags |= _os.O_TEMPORARY
460

461 462
    (fd, name) = _mkstemp_inner(dir, prefix, suffix, flags)
    file = _os.fdopen(fd, mode, bufsize)
463
    return _TemporaryFileWrapper(file, name, delete)
464

465 466 467
if _os.name != 'posix' or _os.sys.platform == 'cygwin':
    # On non-POSIX and Cygwin systems, assume that we cannot unlink a file
    # while it is open.
468
    TemporaryFile = NamedTemporaryFile
469 470

else:
471
    def TemporaryFile(mode='w+b', bufsize=-1, suffix="",
472
                      prefix=template, dir=None):
473 474
        """Create and return a temporary file.
        Arguments:
475
        'prefix', 'suffix', 'dir' -- as for mkstemp.
476 477 478 479
        'mode' -- the mode argument to os.fdopen (default "w+b").
        'bufsize' -- the buffer size argument to os.fdopen (default -1).
        The file is created as mkstemp() would do it.

480 481
        Returns an object with a file-like interface.  The file has no
        name, and will cease to exist when it is closed.
482 483
        """

484 485 486
        if dir is None:
            dir = gettempdir()

487 488 489 490
        if 'b' in mode:
            flags = _bin_openflags
        else:
            flags = _text_openflags
491 492 493 494 495 496 497 498

        (fd, name) = _mkstemp_inner(dir, prefix, suffix, flags)
        try:
            _os.unlink(name)
            return _os.fdopen(fd, mode, bufsize)
        except:
            _os.close(fd)
            raise
499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529

class SpooledTemporaryFile:
    """Temporary file wrapper, specialized to switch from
    StringIO to a real file when it exceeds a certain size or
    when a fileno is needed.
    """
    _rolled = False

    def __init__(self, max_size=0, mode='w+b', bufsize=-1,
                 suffix="", prefix=template, dir=None):
        self._file = _StringIO()
        self._max_size = max_size
        self._rolled = False
        self._TemporaryFileArgs = (mode, bufsize, suffix, prefix, dir)

    def _check(self, file):
        if self._rolled: return
        max_size = self._max_size
        if max_size and file.tell() > max_size:
            self.rollover()

    def rollover(self):
        if self._rolled: return
        file = self._file
        newfile = self._file = TemporaryFile(*self._TemporaryFileArgs)
        del self._TemporaryFileArgs

        newfile.write(file.getvalue())
        newfile.seek(file.tell(), 0)

        self._rolled = True
530

531 532 533 534 535 536 537 538 539 540 541 542 543 544
    # The method caching trick from NamedTemporaryFile
    # won't work here, because _file may change from a
    # _StringIO instance to a real file. So we list
    # all the methods directly.

    # Context management protocol
    def __enter__(self):
        if self._file.closed:
            raise ValueError("Cannot enter context with closed file")
        return self

    def __exit__(self, exc, value, tb):
        self._file.close()

545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620
    # file protocol
    def __iter__(self):
        return self._file.__iter__()

    def close(self):
        self._file.close()

    @property
    def closed(self):
        return self._file.closed

    @property
    def encoding(self):
        return self._file.encoding

    def fileno(self):
        self.rollover()
        return self._file.fileno()

    def flush(self):
        self._file.flush()

    def isatty(self):
        return self._file.isatty()

    @property
    def mode(self):
        return self._file.mode

    @property
    def name(self):
        return self._file.name

    @property
    def newlines(self):
        return self._file.newlines

    def next(self):
        return self._file.next

    def read(self, *args):
        return self._file.read(*args)

    def readline(self, *args):
        return self._file.readline(*args)

    def readlines(self, *args):
        return self._file.readlines(*args)

    def seek(self, *args):
        self._file.seek(*args)

    @property
    def softspace(self):
        return self._file.softspace

    def tell(self):
        return self._file.tell()

    def truncate(self):
        self._file.truncate()

    def write(self, s):
        file = self._file
        rv = file.write(s)
        self._check(file)
        return rv

    def writelines(self, iterable):
        file = self._file
        rv = file.writelines(iterable)
        self._check(file)
        return rv

    def xreadlines(self, *args):
        return self._file.xreadlines(*args)