source: python/trunk/Lib/tempfile.py@ 779

Last change on this file since 779 was 391, checked in by dmik, 11 years ago

python: Merge vendor 2.7.6 to trunk.

  • Property svn:eol-style set to native
File size: 18.3 KB
Line 
1"""Temporary files.
2
3This module provides generic, low- and high-level interfaces for
4creating temporary files and directories. The interfaces listed
5as "safe" just below can be used without fear of race conditions.
6Those listed as "unsafe" cannot, and are provided for backward
7compatibility only.
8
9This module also provides some data items to the user:
10
11 TMP_MAX - maximum number of names that will be tried before
12 giving up.
13 template - the default prefix for all temporary names.
14 You may change this to control the default prefix.
15 tempdir - If this is set to a string before the first use of
16 any routine from this module, it will be considered as
17 another candidate location to store temporary files.
18"""
19
20__all__ = [
21 "NamedTemporaryFile", "TemporaryFile", # high level safe interfaces
22 "SpooledTemporaryFile",
23 "mkstemp", "mkdtemp", # low level safe interfaces
24 "mktemp", # deprecated unsafe interface
25 "TMP_MAX", "gettempprefix", # constants
26 "tempdir", "gettempdir"
27 ]
28
29
30# Imports.
31
32import io as _io
33import os as _os
34import errno as _errno
35from random import Random as _Random
36
37try:
38 from cStringIO import StringIO as _StringIO
39except ImportError:
40 from StringIO import StringIO as _StringIO
41
42try:
43 import fcntl as _fcntl
44except ImportError:
45 def _set_cloexec(fd):
46 pass
47else:
48 def _set_cloexec(fd):
49 try:
50 flags = _fcntl.fcntl(fd, _fcntl.F_GETFD, 0)
51 except IOError:
52 pass
53 else:
54 # flags read successfully, modify
55 flags |= _fcntl.FD_CLOEXEC
56 _fcntl.fcntl(fd, _fcntl.F_SETFD, flags)
57
58
59try:
60 import thread as _thread
61except ImportError:
62 import dummy_thread as _thread
63_allocate_lock = _thread.allocate_lock
64
65_text_openflags = _os.O_RDWR | _os.O_CREAT | _os.O_EXCL
66if hasattr(_os, 'O_NOINHERIT'):
67 _text_openflags |= _os.O_NOINHERIT
68if hasattr(_os, 'O_NOFOLLOW'):
69 _text_openflags |= _os.O_NOFOLLOW
70
71_bin_openflags = _text_openflags
72if hasattr(_os, 'O_BINARY'):
73 _bin_openflags |= _os.O_BINARY
74
75if hasattr(_os, 'TMP_MAX'):
76 TMP_MAX = _os.TMP_MAX
77else:
78 TMP_MAX = 10000
79
80template = "tmp"
81
82# Internal routines.
83
84_once_lock = _allocate_lock()
85
86if hasattr(_os, "lstat"):
87 _stat = _os.lstat
88elif hasattr(_os, "stat"):
89 _stat = _os.stat
90else:
91 # Fallback. All we need is something that raises os.error if the
92 # file doesn't exist.
93 def _stat(fn):
94 try:
95 f = open(fn)
96 except IOError:
97 raise _os.error
98 f.close()
99
100def _exists(fn):
101 try:
102 _stat(fn)
103 except _os.error:
104 return False
105 else:
106 return True
107
108class _RandomNameSequence:
109 """An instance of _RandomNameSequence generates an endless
110 sequence of unpredictable strings which can safely be incorporated
111 into file names. Each string is six characters long. Multiple
112 threads can safely use the same instance at the same time.
113
114 _RandomNameSequence is an iterator."""
115
116 characters = ("abcdefghijklmnopqrstuvwxyz" +
117 "ABCDEFGHIJKLMNOPQRSTUVWXYZ" +
118 "0123456789_")
119
120 def __init__(self):
121 self.mutex = _allocate_lock()
122 self.normcase = _os.path.normcase
123
124 @property
125 def rng(self):
126 cur_pid = _os.getpid()
127 if cur_pid != getattr(self, '_rng_pid', None):
128 self._rng = _Random()
129 self._rng_pid = cur_pid
130 return self._rng
131
132 def __iter__(self):
133 return self
134
135 def next(self):
136 m = self.mutex
137 c = self.characters
138 choose = self.rng.choice
139
140 m.acquire()
141 try:
142 letters = [choose(c) for dummy in "123456"]
143 finally:
144 m.release()
145
146 return self.normcase(''.join(letters))
147
148def _candidate_tempdir_list():
149 """Generate a list of candidate temporary directories which
150 _get_default_tempdir will try."""
151
152 dirlist = []
153
154 # First, try the environment.
155 for envname in 'TMPDIR', 'TEMP', 'TMP':
156 dirname = _os.getenv(envname)
157 if dirname: dirlist.append(dirname)
158
159 # Failing that, try OS-specific locations.
160 if _os.name == 'riscos':
161 dirname = _os.getenv('Wimp$ScrapDir')
162 if dirname: dirlist.append(dirname)
163 elif _os.name == 'nt':
164 dirlist.extend([ r'c:\temp', r'c:\tmp', r'\temp', r'\tmp' ])
165 else:
166 dirlist.extend([ '/tmp', '/var/tmp', '/usr/tmp' ])
167
168 # As a last resort, the current directory.
169 try:
170 dirlist.append(_os.getcwd())
171 except (AttributeError, _os.error):
172 dirlist.append(_os.curdir)
173
174 return dirlist
175
176def _get_default_tempdir():
177 """Calculate the default directory to use for temporary files.
178 This routine should be called exactly once.
179
180 We determine whether or not a candidate temp dir is usable by
181 trying to create and write to a file in that directory. If this
182 is successful, the test file is deleted. To prevent denial of
183 service, the name of the test file must be randomized."""
184
185 namer = _RandomNameSequence()
186 dirlist = _candidate_tempdir_list()
187 flags = _text_openflags
188
189 for dir in dirlist:
190 if dir != _os.curdir:
191 dir = _os.path.normcase(_os.path.abspath(dir))
192 # Try only a few names per directory.
193 for seq in xrange(100):
194 name = namer.next()
195 filename = _os.path.join(dir, name)
196 try:
197 fd = _os.open(filename, flags, 0o600)
198 try:
199 try:
200 with _io.open(fd, 'wb', closefd=False) as fp:
201 fp.write(b'blat')
202 finally:
203 _os.close(fd)
204 finally:
205 _os.unlink(filename)
206 return dir
207 except (OSError, IOError) as e:
208 if e.args[0] != _errno.EEXIST:
209 break # no point trying more names in this directory
210 pass
211 raise IOError, (_errno.ENOENT,
212 ("No usable temporary directory found in %s" % dirlist))
213
214_name_sequence = None
215
216def _get_candidate_names():
217 """Common setup sequence for all user-callable interfaces."""
218
219 global _name_sequence
220 if _name_sequence is None:
221 _once_lock.acquire()
222 try:
223 if _name_sequence is None:
224 _name_sequence = _RandomNameSequence()
225 finally:
226 _once_lock.release()
227 return _name_sequence
228
229
230def _mkstemp_inner(dir, pre, suf, flags):
231 """Code common to mkstemp, TemporaryFile, and NamedTemporaryFile."""
232
233 names = _get_candidate_names()
234
235 for seq in xrange(TMP_MAX):
236 name = names.next()
237 file = _os.path.join(dir, pre + name + suf)
238 try:
239 fd = _os.open(file, flags, 0600)
240 _set_cloexec(fd)
241 return (fd, _os.path.abspath(file))
242 except OSError, e:
243 if e.errno == _errno.EEXIST:
244 continue # try again
245 if _os.name == 'nt' and e.errno == _errno.EACCES:
246 # On windows, when a directory with the chosen name already
247 # exists, EACCES error code is returned instead of EEXIST.
248 continue
249 raise
250
251 raise IOError, (_errno.EEXIST, "No usable temporary file name found")
252
253
254# User visible interfaces.
255
256def gettempprefix():
257 """Accessor for tempdir.template."""
258 return template
259
260tempdir = None
261
262def gettempdir():
263 """Accessor for tempfile.tempdir."""
264 global tempdir
265 if tempdir is None:
266 _once_lock.acquire()
267 try:
268 if tempdir is None:
269 tempdir = _get_default_tempdir()
270 finally:
271 _once_lock.release()
272 return tempdir
273
274def mkstemp(suffix="", prefix=template, dir=None, text=False):
275 """User-callable function to create and return a unique temporary
276 file. The return value is a pair (fd, name) where fd is the
277 file descriptor returned by os.open, and name is the filename.
278
279 If 'suffix' is specified, the file name will end with that suffix,
280 otherwise there will be no suffix.
281
282 If 'prefix' is specified, the file name will begin with that prefix,
283 otherwise a default prefix is used.
284
285 If 'dir' is specified, the file will be created in that directory,
286 otherwise a default directory is used.
287
288 If 'text' is specified and true, the file is opened in text
289 mode. Else (the default) the file is opened in binary mode. On
290 some operating systems, this makes no difference.
291
292 The file is readable and writable only by the creating user ID.
293 If the operating system uses permission bits to indicate whether a
294 file is executable, the file is executable by no one. The file
295 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 if dir is None:
301 dir = gettempdir()
302
303 if text:
304 flags = _text_openflags
305 else:
306 flags = _bin_openflags
307
308 return _mkstemp_inner(dir, prefix, suffix, flags)
309
310
311def mkdtemp(suffix="", prefix=template, dir=None):
312 """User-callable function to create and return a unique temporary
313 directory. The return value is the pathname of the directory.
314
315 Arguments are as for mkstemp, except that the 'text' argument is
316 not accepted.
317
318 The directory is readable, writable, and searchable only by the
319 creating user.
320
321 Caller is responsible for deleting the directory when done with it.
322 """
323
324 if dir is None:
325 dir = gettempdir()
326
327 names = _get_candidate_names()
328
329 for seq in xrange(TMP_MAX):
330 name = names.next()
331 file = _os.path.join(dir, prefix + name + suffix)
332 try:
333 _os.mkdir(file, 0700)
334 return file
335 except OSError, e:
336 if e.errno == _errno.EEXIST:
337 continue # try again
338 raise
339
340 raise IOError, (_errno.EEXIST, "No usable temporary directory name found")
341
342def mktemp(suffix="", prefix=template, dir=None):
343 """User-callable function to return a unique temporary file name. The
344 file is not created.
345
346 Arguments are as for mkstemp, except that the 'text' argument is
347 not accepted.
348
349 This function is unsafe and should not be used. The file name
350 refers to a file that did not exist at some point, but by the time
351 you get around to creating it, someone else may have beaten you to
352 the punch.
353 """
354
355## from warnings import warn as _warn
356## _warn("mktemp is a potential security risk to your program",
357## RuntimeWarning, stacklevel=2)
358
359 if dir is None:
360 dir = gettempdir()
361
362 names = _get_candidate_names()
363 for seq in xrange(TMP_MAX):
364 name = names.next()
365 file = _os.path.join(dir, prefix + name + suffix)
366 if not _exists(file):
367 return file
368
369 raise IOError, (_errno.EEXIST, "No usable temporary filename found")
370
371
372class _TemporaryFileWrapper:
373 """Temporary file wrapper
374
375 This class provides a wrapper around files opened for
376 temporary use. In particular, it seeks to automatically
377 remove the file when it is no longer needed.
378 """
379
380 def __init__(self, file, name, delete=True):
381 self.file = file
382 self.name = name
383 self.close_called = False
384 self.delete = delete
385
386 def __getattr__(self, name):
387 # Attribute lookups are delegated to the underlying file
388 # and cached for non-numeric results
389 # (i.e. methods are cached, closed and friends are not)
390 file = self.__dict__['file']
391 a = getattr(file, name)
392 if not issubclass(type(a), type(0)):
393 setattr(self, name, a)
394 return a
395
396 # The underlying __enter__ method returns the wrong object
397 # (self.file) so override it to return the wrapper
398 def __enter__(self):
399 self.file.__enter__()
400 return self
401
402 # NT provides delete-on-close as a primitive, so we don't need
403 # the wrapper to do anything special. We still use it so that
404 # file.name is useful (i.e. not "(fdopen)") with NamedTemporaryFile.
405 if _os.name != 'nt' and _os.name != 'os2':
406 # Cache the unlinker so we don't get spurious errors at
407 # shutdown when the module-level "os" is None'd out. Note
408 # that this must be referenced as self.unlink, because the
409 # name TemporaryFileWrapper may also get None'd out before
410 # __del__ is called.
411 unlink = _os.unlink
412
413 def close(self):
414 if not self.close_called:
415 self.close_called = True
416 self.file.close()
417 if self.delete:
418 self.unlink(self.name)
419
420 def __del__(self):
421 self.close()
422
423 # Need to trap __exit__ as well to ensure the file gets
424 # deleted when used in a with statement
425 def __exit__(self, exc, value, tb):
426 result = self.file.__exit__(exc, value, tb)
427 self.close()
428 return result
429 else:
430 def __exit__(self, exc, value, tb):
431 self.file.__exit__(exc, value, tb)
432
433
434def NamedTemporaryFile(mode='w+b', bufsize=-1, suffix="",
435 prefix=template, dir=None, delete=True):
436 """Create and return a temporary file.
437 Arguments:
438 'prefix', 'suffix', 'dir' -- as for mkstemp.
439 'mode' -- the mode argument to os.fdopen (default "w+b").
440 'bufsize' -- the buffer size argument to os.fdopen (default -1).
441 'delete' -- whether the file is deleted on close (default True).
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
445 is accessible as file.name. The file will be automatically deleted
446 when it is closed unless the 'delete' argument is set to False.
447 """
448
449 if dir is None:
450 dir = gettempdir()
451
452 if 'b' in mode:
453 flags = _bin_openflags
454 else:
455 flags = _text_openflags
456
457 # Setting O_TEMPORARY in the flags causes the OS to delete
458 # the file when it is closed. This is only supported by Windows.
459 if _os.name == 'nt' and delete:
460 flags |= _os.O_TEMPORARY
461
462 (fd, name) = _mkstemp_inner(dir, prefix, suffix, flags)
463 file = _os.fdopen(fd, mode, bufsize)
464 return _TemporaryFileWrapper(file, name, delete)
465
466if _os.name != 'posix' or _os.sys.platform == 'cygwin' or _os.sys.platform == 'os2emx' or _os.sys.platform == 'os2knix':
467 # On non-POSIX and Cygwin systems, assume that we cannot unlink a file
468 # while it is open.
469 TemporaryFile = NamedTemporaryFile
470
471else:
472 def TemporaryFile(mode='w+b', bufsize=-1, suffix="",
473 prefix=template, dir=None):
474 """Create and return a temporary file.
475 Arguments:
476 'prefix', 'suffix', 'dir' -- as for mkstemp.
477 'mode' -- the mode argument to os.fdopen (default "w+b").
478 'bufsize' -- the buffer size argument to os.fdopen (default -1).
479 The file is created as mkstemp() would do it.
480
481 Returns an object with a file-like interface. The file has no
482 name, and will cease to exist when it is closed.
483 """
484
485 if dir is None:
486 dir = gettempdir()
487
488 if 'b' in mode:
489 flags = _bin_openflags
490 else:
491 flags = _text_openflags
492
493 (fd, name) = _mkstemp_inner(dir, prefix, suffix, flags)
494 try:
495 _os.unlink(name)
496 return _os.fdopen(fd, mode, bufsize)
497 except:
498 _os.close(fd)
499 raise
500
501class SpooledTemporaryFile:
502 """Temporary file wrapper, specialized to switch from
503 StringIO to a real file when it exceeds a certain size or
504 when a fileno is needed.
505 """
506 _rolled = False
507
508 def __init__(self, max_size=0, mode='w+b', bufsize=-1,
509 suffix="", prefix=template, dir=None):
510 self._file = _StringIO()
511 self._max_size = max_size
512 self._rolled = False
513 self._TemporaryFileArgs = (mode, bufsize, suffix, prefix, dir)
514
515 def _check(self, file):
516 if self._rolled: return
517 max_size = self._max_size
518 if max_size and file.tell() > max_size:
519 self.rollover()
520
521 def rollover(self):
522 if self._rolled: return
523 file = self._file
524 newfile = self._file = TemporaryFile(*self._TemporaryFileArgs)
525 del self._TemporaryFileArgs
526
527 newfile.write(file.getvalue())
528 newfile.seek(file.tell(), 0)
529
530 self._rolled = True
531
532 # The method caching trick from NamedTemporaryFile
533 # won't work here, because _file may change from a
534 # _StringIO instance to a real file. So we list
535 # all the methods directly.
536
537 # Context management protocol
538 def __enter__(self):
539 if self._file.closed:
540 raise ValueError("Cannot enter context with closed file")
541 return self
542
543 def __exit__(self, exc, value, tb):
544 self._file.close()
545
546 # file protocol
547 def __iter__(self):
548 return self._file.__iter__()
549
550 def close(self):
551 self._file.close()
552
553 @property
554 def closed(self):
555 return self._file.closed
556
557 def fileno(self):
558 self.rollover()
559 return self._file.fileno()
560
561 def flush(self):
562 self._file.flush()
563
564 def isatty(self):
565 return self._file.isatty()
566
567 @property
568 def mode(self):
569 try:
570 return self._file.mode
571 except AttributeError:
572 return self._TemporaryFileArgs[0]
573
574 @property
575 def name(self):
576 try:
577 return self._file.name
578 except AttributeError:
579 return None
580
581 def next(self):
582 return self._file.next
583
584 def read(self, *args):
585 return self._file.read(*args)
586
587 def readline(self, *args):
588 return self._file.readline(*args)
589
590 def readlines(self, *args):
591 return self._file.readlines(*args)
592
593 def seek(self, *args):
594 self._file.seek(*args)
595
596 @property
597 def softspace(self):
598 return self._file.softspace
599
600 def tell(self):
601 return self._file.tell()
602
603 def truncate(self):
604 self._file.truncate()
605
606 def write(self, s):
607 file = self._file
608 rv = file.write(s)
609 self._check(file)
610 return rv
611
612 def writelines(self, iterable):
613 file = self._file
614 rv = file.writelines(iterable)
615 self._check(file)
616 return rv
617
618 def xreadlines(self, *args):
619 if hasattr(self._file, 'xreadlines'): # real file
620 return iter(self._file)
621 else: # StringIO()
622 return iter(self._file.readlines(*args))
Note: See TracBrowser for help on using the repository browser.