blob: dd7e8643e694d938e09a7ef628c7459c0a49ddd7 [file] [log] [blame]
Guido van Rossum0e548712002-08-09 16:14:33 +00001"""Temporary files.
Guido van Rossume7b146f2000-02-04 15:28:42 +00002
Guido van Rossum0e548712002-08-09 16:14:33 +00003This 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.
Guido van Rossumeee94981991-11-12 15:38:08 +00008
Guido van Rossum0e548712002-08-09 16:14:33 +00009This module also provides some data items to the user:
Guido van Rossumeee94981991-11-12 15:38:08 +000010
Guido van Rossum0e548712002-08-09 16:14:33 +000011 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"""
Skip Montanaro40fc1602001-03-01 04:27:19 +000019
Guido van Rossum0e548712002-08-09 16:14:33 +000020__all__ = [
21 "NamedTemporaryFile", "TemporaryFile", # high level safe interfaces
22 "mkstemp", "mkdtemp", # low level safe interfaces
23 "mktemp", # deprecated unsafe interface
24 "TMP_MAX", "gettempprefix", # constants
25 "tempdir", "gettempdir"
26 ]
Guido van Rossum41f95031992-03-31 19:02:01 +000027
Tim Peters4fd5a062002-01-28 23:11:23 +000028
Guido van Rossum0e548712002-08-09 16:14:33 +000029# Imports.
Tim Peters4fd5a062002-01-28 23:11:23 +000030
Guido van Rossum0e548712002-08-09 16:14:33 +000031import os as _os
32import errno as _errno
33from random import Random as _Random
34
35if _os.name == 'mac':
Jack Jansenbb829b72003-03-21 12:55:38 +000036 import Carbon.Folder as _Folder
37 import Carbon.Folders as _Folders
Guido van Rossum0e548712002-08-09 16:14:33 +000038
39try:
40 import fcntl as _fcntl
Tim Peters90ee7eb2004-07-18 23:58:17 +000041except ImportError:
Tim Peters291f14e2003-07-22 02:50:01 +000042 def _set_cloexec(fd):
43 pass
44else:
Guido van Rossum0e548712002-08-09 16:14:33 +000045 def _set_cloexec(fd):
Tim Peters90ee7eb2004-07-18 23:58:17 +000046 try:
47 flags = _fcntl.fcntl(fd, _fcntl.F_GETFD, 0)
48 except IOError:
49 pass
Alex Martellif09994e2003-11-09 16:44:09 +000050 else:
Guido van Rossum0e548712002-08-09 16:14:33 +000051 # flags read successfully, modify
52 flags |= _fcntl.FD_CLOEXEC
53 _fcntl.fcntl(fd, _fcntl.F_SETFD, flags)
Tim Peters291f14e2003-07-22 02:50:01 +000054
Guido van Rossum0e548712002-08-09 16:14:33 +000055
56try:
57 import thread as _thread
Guido van Rossuma0934242002-12-30 22:36:09 +000058except ImportError:
59 import dummy_thread as _thread
60_allocate_lock = _thread.allocate_lock
Guido van Rossum0e548712002-08-09 16:14:33 +000061
62_text_openflags = _os.O_RDWR | _os.O_CREAT | _os.O_EXCL
Tim Petersa0d55de2002-08-09 18:01:01 +000063if hasattr(_os, 'O_NOINHERIT'):
64 _text_openflags |= _os.O_NOINHERIT
65if hasattr(_os, 'O_NOFOLLOW'):
66 _text_openflags |= _os.O_NOFOLLOW
Guido van Rossum0e548712002-08-09 16:14:33 +000067
68_bin_openflags = _text_openflags
Tim Petersa0d55de2002-08-09 18:01:01 +000069if hasattr(_os, 'O_BINARY'):
70 _bin_openflags |= _os.O_BINARY
Guido van Rossum0e548712002-08-09 16:14:33 +000071
72if hasattr(_os, 'TMP_MAX'):
73 TMP_MAX = _os.TMP_MAX
74else:
75 TMP_MAX = 10000
76
Tim Petersbd7b4c72002-08-13 23:33:56 +000077template = "tmp"
Guido van Rossum0e548712002-08-09 16:14:33 +000078
79tempdir = None
80
81# Internal routines.
82
83_once_lock = _allocate_lock()
84
Guido van Rossumb256159392003-11-10 02:16:36 +000085if hasattr(_os, "lstat"):
86 _stat = _os.lstat
87elif hasattr(_os, "stat"):
88 _stat = _os.stat
89else:
90 # Fallback. All we need is something that raises os.error if the
91 # file doesn't exist.
92 def _stat(fn):
93 try:
94 f = open(fn)
95 except IOError:
96 raise _os.error
97 f.close()
98
99def _exists(fn):
100 try:
101 _stat(fn)
102 except _os.error:
103 return False
104 else:
105 return True
106
Guido van Rossum0e548712002-08-09 16:14:33 +0000107class _RandomNameSequence:
108 """An instance of _RandomNameSequence generates an endless
109 sequence of unpredictable strings which can safely be incorporated
110 into file names. Each string is six characters long. Multiple
111 threads can safely use the same instance at the same time.
112
113 _RandomNameSequence is an iterator."""
114
Tim Peters97701b52002-11-21 15:59:59 +0000115 characters = ("abcdefghijklmnopqrstuvwxyz" +
116 "ABCDEFGHIJKLMNOPQRSTUVWXYZ" +
117 "0123456789-_")
Guido van Rossum0e548712002-08-09 16:14:33 +0000118
119 def __init__(self):
120 self.mutex = _allocate_lock()
121 self.rng = _Random()
122 self.normcase = _os.path.normcase
Tim Peters97701b52002-11-21 15:59:59 +0000123
Guido van Rossum0e548712002-08-09 16:14:33 +0000124 def __iter__(self):
125 return self
126
127 def next(self):
128 m = self.mutex
129 c = self.characters
Tim Peters97701b52002-11-21 15:59:59 +0000130 choose = self.rng.choice
Guido van Rossum0e548712002-08-09 16:14:33 +0000131
Tim Peters97701b52002-11-21 15:59:59 +0000132 m.acquire()
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000133 try:
Tim Peters97701b52002-11-21 15:59:59 +0000134 letters = [choose(c) for dummy in "123456"]
Guido van Rossum0e548712002-08-09 16:14:33 +0000135 finally:
136 m.release()
137
Tim Peters97701b52002-11-21 15:59:59 +0000138 return self.normcase(''.join(letters))
Guido van Rossum0e548712002-08-09 16:14:33 +0000139
140def _candidate_tempdir_list():
141 """Generate a list of candidate temporary directories which
142 _get_default_tempdir will try."""
143
144 dirlist = []
145
146 # First, try the environment.
147 for envname in 'TMPDIR', 'TEMP', 'TMP':
148 dirname = _os.getenv(envname)
149 if dirname: dirlist.append(dirname)
150
151 # Failing that, try OS-specific locations.
152 if _os.name == 'mac':
153 try:
Jack Jansenbb829b72003-03-21 12:55:38 +0000154 fsr = _Folder.FSFindFolder(_Folders.kOnSystemDisk,
155 _Folders.kTemporaryFolderType, 1)
156 dirname = fsr.as_pathname()
Guido van Rossum0e548712002-08-09 16:14:33 +0000157 dirlist.append(dirname)
Jack Jansenbb829b72003-03-21 12:55:38 +0000158 except _Folder.error:
Guido van Rossum0e548712002-08-09 16:14:33 +0000159 pass
160 elif _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
Tim Petersa0d55de2002-08-09 18:01:01 +0000175
Guido van Rossum0e548712002-08-09 16:14:33 +0000176def _get_default_tempdir():
177 """Calculate the default directory to use for temporary files.
Guido van Rossume888cdc2002-08-17 14:50:24 +0000178 This routine should be called exactly once.
Guido van Rossum0e548712002-08-09 16:14:33 +0000179
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, 0600)
198 fp = _os.fdopen(fd, 'w')
Tim Petersb90f89a2001-01-15 03:26:36 +0000199 fp.write('blat')
200 fp.close()
Guido van Rossum0e548712002-08-09 16:14:33 +0000201 _os.unlink(filename)
202 del fp, fd
203 return dir
204 except (OSError, IOError), e:
205 if e[0] != _errno.EEXIST:
206 break # no point trying more names in this directory
207 pass
208 raise IOError, (_errno.ENOENT,
209 ("No usable temporary directory found in %s" % dirlist))
210
Guido van Rossume888cdc2002-08-17 14:50:24 +0000211_name_sequence = None
212
Guido van Rossum0e548712002-08-09 16:14:33 +0000213def _get_candidate_names():
214 """Common setup sequence for all user-callable interfaces."""
215
Guido van Rossume888cdc2002-08-17 14:50:24 +0000216 global _name_sequence
217 if _name_sequence is None:
218 _once_lock.acquire()
219 try:
220 if _name_sequence is None:
221 _name_sequence = _RandomNameSequence()
222 finally:
223 _once_lock.release()
Guido van Rossum0e548712002-08-09 16:14:33 +0000224 return _name_sequence
Guido van Rossum41f95031992-03-31 19:02:01 +0000225
226
Guido van Rossum0e548712002-08-09 16:14:33 +0000227def _mkstemp_inner(dir, pre, suf, flags):
228 """Code common to mkstemp, TemporaryFile, and NamedTemporaryFile."""
Tim Peters9fadfb02001-01-13 03:04:02 +0000229
Guido van Rossum0e548712002-08-09 16:14:33 +0000230 names = _get_candidate_names()
231
232 for seq in xrange(TMP_MAX):
233 name = names.next()
234 file = _os.path.join(dir, pre + name + suf)
235 try:
236 fd = _os.open(file, flags, 0600)
237 _set_cloexec(fd)
Martin v. Löwisd6625482003-10-12 17:37:01 +0000238 return (fd, _os.path.abspath(file))
Guido van Rossum0e548712002-08-09 16:14:33 +0000239 except OSError, e:
240 if e.errno == _errno.EEXIST:
241 continue # try again
242 raise
243
244 raise IOError, (_errno.EEXIST, "No usable temporary file name found")
Tim Petersa0d55de2002-08-09 18:01:01 +0000245
Guido van Rossum0e548712002-08-09 16:14:33 +0000246
247# User visible interfaces.
Guido van Rossumb0e57181998-10-14 20:27:05 +0000248
Guido van Rossum41f95031992-03-31 19:02:01 +0000249def gettempprefix():
Guido van Rossum0e548712002-08-09 16:14:33 +0000250 """Accessor for tempdir.template."""
251 return template
Tim Peters9fadfb02001-01-13 03:04:02 +0000252
Guido van Rossume888cdc2002-08-17 14:50:24 +0000253tempdir = None
254
Guido van Rossum0e548712002-08-09 16:14:33 +0000255def gettempdir():
256 """Accessor for tempdir.tempdir."""
Guido van Rossume888cdc2002-08-17 14:50:24 +0000257 global tempdir
258 if tempdir is None:
259 _once_lock.acquire()
260 try:
261 if tempdir is None:
262 tempdir = _get_default_tempdir()
263 finally:
264 _once_lock.release()
Guido van Rossum0e548712002-08-09 16:14:33 +0000265 return tempdir
266
Guido van Rossume888cdc2002-08-17 14:50:24 +0000267def mkstemp(suffix="", prefix=template, dir=None, text=False):
Tim Peters04490bf2002-08-14 15:41:26 +0000268 """mkstemp([suffix, [prefix, [dir, [text]]]])
Guido van Rossum0e548712002-08-09 16:14:33 +0000269 User-callable function to create and return a unique temporary
270 file. The return value is a pair (fd, name) where fd is the
271 file descriptor returned by os.open, and name is the filename.
272
273 If 'suffix' is specified, the file name will end with that suffix,
274 otherwise there will be no suffix.
275
276 If 'prefix' is specified, the file name will begin with that prefix,
277 otherwise a default prefix is used.
278
279 If 'dir' is specified, the file will be created in that directory,
280 otherwise a default directory is used.
281
Tim Peters04490bf2002-08-14 15:41:26 +0000282 If 'text' is specified and true, the file is opened in text
283 mode. Else (the default) the file is opened in binary mode. On
284 some operating systems, this makes no difference.
Guido van Rossum0e548712002-08-09 16:14:33 +0000285
286 The file is readable and writable only by the creating user ID.
287 If the operating system uses permission bits to indicate whether a
288 file is executable, the file is executable by no one. The file
289 descriptor is not inherited by children of this process.
290
291 Caller is responsible for deleting the file when done with it.
Tim Peters9fadfb02001-01-13 03:04:02 +0000292 """
293
Guido van Rossume888cdc2002-08-17 14:50:24 +0000294 if dir is None:
295 dir = gettempdir()
296
Tim Peters04490bf2002-08-14 15:41:26 +0000297 if text:
Guido van Rossum0e548712002-08-09 16:14:33 +0000298 flags = _text_openflags
Tim Peters04490bf2002-08-14 15:41:26 +0000299 else:
300 flags = _bin_openflags
Guido van Rossum0e548712002-08-09 16:14:33 +0000301
302 return _mkstemp_inner(dir, prefix, suffix, flags)
Guido van Rossumcff34541992-01-14 18:31:56 +0000303
Guido van Rossumeee94981991-11-12 15:38:08 +0000304
Guido van Rossume888cdc2002-08-17 14:50:24 +0000305def mkdtemp(suffix="", prefix=template, dir=None):
Guido van Rossum0e548712002-08-09 16:14:33 +0000306 """mkdtemp([suffix, [prefix, [dir]]])
307 User-callable function to create and return a unique temporary
308 directory. The return value is the pathname of the directory.
309
Tim Peters04490bf2002-08-14 15:41:26 +0000310 Arguments are as for mkstemp, except that the 'text' argument is
Guido van Rossum0e548712002-08-09 16:14:33 +0000311 not accepted.
312
313 The directory is readable, writable, and searchable only by the
314 creating user.
315
316 Caller is responsible for deleting the directory when done with it.
317 """
318
Guido van Rossume888cdc2002-08-17 14:50:24 +0000319 if dir is None:
320 dir = gettempdir()
321
Guido van Rossum0e548712002-08-09 16:14:33 +0000322 names = _get_candidate_names()
Tim Petersa0d55de2002-08-09 18:01:01 +0000323
Guido van Rossum0e548712002-08-09 16:14:33 +0000324 for seq in xrange(TMP_MAX):
325 name = names.next()
326 file = _os.path.join(dir, prefix + name + suffix)
327 try:
328 _os.mkdir(file, 0700)
329 return file
330 except OSError, e:
331 if e.errno == _errno.EEXIST:
332 continue # try again
333 raise
334
335 raise IOError, (_errno.EEXIST, "No usable temporary directory name found")
336
Guido van Rossume888cdc2002-08-17 14:50:24 +0000337def mktemp(suffix="", prefix=template, dir=None):
Guido van Rossum0e548712002-08-09 16:14:33 +0000338 """mktemp([suffix, [prefix, [dir]]])
339 User-callable function to return a unique temporary file name. The
340 file is not created.
341
Tim Peters04490bf2002-08-14 15:41:26 +0000342 Arguments are as for mkstemp, except that the 'text' argument is
Guido van Rossum0e548712002-08-09 16:14:33 +0000343 not accepted.
344
345 This function is unsafe and should not be used. The file name
346 refers to a file that did not exist at some point, but by the time
347 you get around to creating it, someone else may have beaten you to
348 the punch.
349 """
350
Guido van Rossum44f602d2002-11-22 15:56:29 +0000351## from warnings import warn as _warn
352## _warn("mktemp is a potential security risk to your program",
353## RuntimeWarning, stacklevel=2)
Guido van Rossum0e548712002-08-09 16:14:33 +0000354
Guido van Rossume888cdc2002-08-17 14:50:24 +0000355 if dir is None:
356 dir = gettempdir()
357
Guido van Rossum0e548712002-08-09 16:14:33 +0000358 names = _get_candidate_names()
359 for seq in xrange(TMP_MAX):
360 name = names.next()
361 file = _os.path.join(dir, prefix + name + suffix)
Guido van Rossumb256159392003-11-10 02:16:36 +0000362 if not _exists(file):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000363 return file
Guido van Rossumca549821997-08-12 18:00:12 +0000364
Guido van Rossum0e548712002-08-09 16:14:33 +0000365 raise IOError, (_errno.EEXIST, "No usable temporary filename found")
Guido van Rossumca549821997-08-12 18:00:12 +0000366
Guido van Rossum0e548712002-08-09 16:14:33 +0000367class _TemporaryFileWrapper:
Guido van Rossumca549821997-08-12 18:00:12 +0000368 """Temporary file wrapper
369
Guido van Rossum0e548712002-08-09 16:14:33 +0000370 This class provides a wrapper around files opened for
371 temporary use. In particular, it seeks to automatically
372 remove the file when it is no longer needed.
Guido van Rossumca549821997-08-12 18:00:12 +0000373 """
Tim Petersa255a722001-12-18 22:32:40 +0000374
Guido van Rossum0e548712002-08-09 16:14:33 +0000375 def __init__(self, file, name):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000376 self.file = file
Guido van Rossum0e548712002-08-09 16:14:33 +0000377 self.name = name
Tim Peters6ef966e2002-11-21 15:48:33 +0000378 self.close_called = False
Guido van Rossumca549821997-08-12 18:00:12 +0000379
Guido van Rossumca549821997-08-12 18:00:12 +0000380 def __getattr__(self, name):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000381 file = self.__dict__['file']
382 a = getattr(file, name)
Guido van Rossum6b708d51999-06-01 18:55:36 +0000383 if type(a) != type(0):
384 setattr(self, name, a)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000385 return a
Guido van Rossumca549821997-08-12 18:00:12 +0000386
Guido van Rossum0e548712002-08-09 16:14:33 +0000387 # NT provides delete-on-close as a primitive, so we don't need
388 # the wrapper to do anything special. We still use it so that
389 # file.name is useful (i.e. not "(fdopen)") with NamedTemporaryFile.
390 if _os.name != 'nt':
Guido van Rossumca549821997-08-12 18:00:12 +0000391
Guido van Rossum0e548712002-08-09 16:14:33 +0000392 # Cache the unlinker so we don't get spurious errors at
393 # shutdown when the module-level "os" is None'd out. Note
394 # that this must be referenced as self.unlink, because the
395 # name TemporaryFileWrapper may also get None'd out before
396 # __del__ is called.
397 unlink = _os.unlink
Tim Peters1baa22a2001-01-12 10:02:46 +0000398
Guido van Rossum0e548712002-08-09 16:14:33 +0000399 def close(self):
400 if not self.close_called:
Tim Peters6ef966e2002-11-21 15:48:33 +0000401 self.close_called = True
Guido van Rossum0e548712002-08-09 16:14:33 +0000402 self.file.close()
403 self.unlink(self.name)
Tim Peters1baa22a2001-01-12 10:02:46 +0000404
Guido van Rossum0e548712002-08-09 16:14:33 +0000405 def __del__(self):
406 self.close()
Tim Peters1baa22a2001-01-12 10:02:46 +0000407
Guido van Rossum0e548712002-08-09 16:14:33 +0000408def NamedTemporaryFile(mode='w+b', bufsize=-1, suffix="",
Guido van Rossume888cdc2002-08-17 14:50:24 +0000409 prefix=template, dir=None):
Guido van Rossum0e548712002-08-09 16:14:33 +0000410 """Create and return a temporary file.
411 Arguments:
412 'prefix', 'suffix', 'dir' -- as for mkstemp.
413 'mode' -- the mode argument to os.fdopen (default "w+b").
414 'bufsize' -- the buffer size argument to os.fdopen (default -1).
415 The file is created as mkstemp() would do it.
Tim Peters1baa22a2001-01-12 10:02:46 +0000416
Raymond Hettingerfaa10eb2005-01-11 15:33:03 +0000417 Returns an object with a file-like interface; the name of the file
418 is accessible as file.name. The file will be automatically deleted
419 when it is closed.
Guido van Rossum0e548712002-08-09 16:14:33 +0000420 """
Tim Peters1baa22a2001-01-12 10:02:46 +0000421
Guido van Rossume888cdc2002-08-17 14:50:24 +0000422 if dir is None:
423 dir = gettempdir()
424
Tim Petersc21ea742002-08-13 23:36:01 +0000425 if 'b' in mode:
426 flags = _bin_openflags
427 else:
428 flags = _text_openflags
Tim Peters1baa22a2001-01-12 10:02:46 +0000429
Guido van Rossum0e548712002-08-09 16:14:33 +0000430 # Setting O_TEMPORARY in the flags causes the OS to delete
431 # the file when it is closed. This is only supported by Windows.
432 if _os.name == 'nt':
433 flags |= _os.O_TEMPORARY
Tim Peters1baa22a2001-01-12 10:02:46 +0000434
Guido van Rossum0e548712002-08-09 16:14:33 +0000435 (fd, name) = _mkstemp_inner(dir, prefix, suffix, flags)
436 file = _os.fdopen(fd, mode, bufsize)
437 return _TemporaryFileWrapper(file, name)
438
Jason Tishler80c02af2002-08-14 15:10:09 +0000439if _os.name != 'posix' or _os.sys.platform == 'cygwin':
440 # On non-POSIX and Cygwin systems, assume that we cannot unlink a file
441 # while it is open.
Guido van Rossum0e548712002-08-09 16:14:33 +0000442 TemporaryFile = NamedTemporaryFile
Tim Peters1baa22a2001-01-12 10:02:46 +0000443
444else:
Guido van Rossum0e548712002-08-09 16:14:33 +0000445 def TemporaryFile(mode='w+b', bufsize=-1, suffix="",
Guido van Rossume888cdc2002-08-17 14:50:24 +0000446 prefix=template, dir=None):
Guido van Rossum0e548712002-08-09 16:14:33 +0000447 """Create and return a temporary file.
448 Arguments:
449 'prefix', 'suffix', 'directory' -- as for mkstemp.
450 'mode' -- the mode argument to os.fdopen (default "w+b").
451 'bufsize' -- the buffer size argument to os.fdopen (default -1).
452 The file is created as mkstemp() would do it.
Tim Peters1baa22a2001-01-12 10:02:46 +0000453
Raymond Hettingerfaa10eb2005-01-11 15:33:03 +0000454 Returns an object with a file-like interface. The file has no
455 name, and will cease to exist when it is closed.
Guido van Rossum0e548712002-08-09 16:14:33 +0000456 """
457
Guido van Rossume888cdc2002-08-17 14:50:24 +0000458 if dir is None:
459 dir = gettempdir()
460
Tim Petersc21ea742002-08-13 23:36:01 +0000461 if 'b' in mode:
462 flags = _bin_openflags
463 else:
464 flags = _text_openflags
Guido van Rossum0e548712002-08-09 16:14:33 +0000465
466 (fd, name) = _mkstemp_inner(dir, prefix, suffix, flags)
467 try:
468 _os.unlink(name)
469 return _os.fdopen(fd, mode, bufsize)
470 except:
471 _os.close(fd)
472 raise