blob: 1f301262db8390fe3900e440a5879e46db6cb50d [file] [log] [blame]
Guido van Rossumeee94981991-11-12 15:38:08 +00001# Temporary file name allocation
Guido van Rossum41f95031992-03-31 19:02:01 +00002#
3# XXX This tries to be not UNIX specific, but I don't know beans about
4# how to choose a temp directory or filename on MS-DOS or other
5# systems so it may have to be changed...
Guido van Rossumeee94981991-11-12 15:38:08 +00006
7
Guido van Rossum41f95031992-03-31 19:02:01 +00008import os
Guido van Rossumeee94981991-11-12 15:38:08 +00009
Guido van Rossumeee94981991-11-12 15:38:08 +000010
Guido van Rossum41f95031992-03-31 19:02:01 +000011# Parameters that the caller may set to override the defaults
Guido van Rossumcff34541992-01-14 18:31:56 +000012
Guido van Rossum41f95031992-03-31 19:02:01 +000013tempdir = None
14template = None
15
16
17# Function to calculate the directory to use
18
19def gettempdir():
Guido van Rossumf4aaf861996-05-28 23:31:34 +000020 global tempdir
Guido van Rossum4033ad71996-08-08 18:33:56 +000021 if tempdir is not None:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000022 return tempdir
Guido van Rossum29e5f5d1998-04-09 14:27:57 +000023 try:
24 pwd = os.getcwd()
25 except (AttributeError, os.error):
26 pwd = os.curdir
27 attempdirs = ['/usr/tmp', '/tmp', pwd]
Guido van Rossum3e065ad1996-08-20 20:38:59 +000028 if os.name == 'nt':
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000029 attempdirs.insert(0, 'C:\\TEMP')
30 attempdirs.insert(0, '\\TEMP')
Guido van Rossumf4f756c1997-04-11 19:00:53 +000031 elif os.name == 'mac':
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000032 import macfs, MACFS
33 try:
34 refnum, dirid = macfs.FindFolder(MACFS.kOnSystemDisk,
Guido van Rossum57a06611998-04-28 16:03:34 +000035 MACFS.kTemporaryFolderType, 1)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000036 dirname = macfs.FSSpec((refnum, dirid, '')).as_pathname()
37 attempdirs.insert(0, dirname)
38 except macfs.error:
39 pass
Guido van Rossumca549821997-08-12 18:00:12 +000040 for envname in 'TMPDIR', 'TEMP', 'TMP':
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000041 if os.environ.has_key(envname):
42 attempdirs.insert(0, os.environ[envname])
Guido van Rossum3e065ad1996-08-20 20:38:59 +000043 testfile = gettempprefix() + 'test'
Guido van Rossumf4aaf861996-05-28 23:31:34 +000044 for dir in attempdirs:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000045 try:
46 filename = os.path.join(dir, testfile)
47 fp = open(filename, 'w')
48 fp.write('blat')
49 fp.close()
50 os.unlink(filename)
51 tempdir = dir
52 break
53 except IOError:
54 pass
Guido van Rossumf4aaf861996-05-28 23:31:34 +000055 if tempdir is None:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000056 msg = "Can't find a usable temporary directory amongst " + `attempdirs`
57 raise IOError, msg
Guido van Rossumf4aaf861996-05-28 23:31:34 +000058 return tempdir
Guido van Rossum41f95031992-03-31 19:02:01 +000059
60
61# Function to calculate a prefix of the filename to use
62
Guido van Rossumb0e57181998-10-14 20:27:05 +000063_pid = None
64
Guido van Rossum41f95031992-03-31 19:02:01 +000065def gettempprefix():
Guido van Rossumb0e57181998-10-14 20:27:05 +000066 global template, _pid
67 if os.name == 'posix' and _pid and _pid != os.getpid():
68 # Our pid changed; we must have forked -- zap the template
69 template = None
70 if template is None:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000071 if os.name == 'posix':
Guido van Rossumb0e57181998-10-14 20:27:05 +000072 _pid = os.getpid()
73 template = '@' + `_pid` + '.'
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000074 elif os.name == 'nt':
75 template = '~' + `os.getpid()` + '-'
76 elif os.name == 'mac':
77 template = 'Python-Tmp-'
78 else:
79 template = 'tmp' # XXX might choose a better one
80 return template
Guido van Rossumcff34541992-01-14 18:31:56 +000081
Guido van Rossumeee94981991-11-12 15:38:08 +000082
Guido van Rossum4a3a41f1991-12-26 13:10:50 +000083# Counter for generating unique names
Guido van Rossumeee94981991-11-12 15:38:08 +000084
Guido van Rossum4a3a41f1991-12-26 13:10:50 +000085counter = 0
Guido van Rossumeee94981991-11-12 15:38:08 +000086
87
Guido van Rossum41f95031992-03-31 19:02:01 +000088# User-callable function to return a unique temporary file name
Guido van Rossumeee94981991-11-12 15:38:08 +000089
Guido van Rossumb8c42c91997-12-19 04:29:50 +000090def mktemp(suffix=""):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000091 global counter
92 dir = gettempdir()
93 pre = gettempprefix()
94 while 1:
95 counter = counter + 1
96 file = os.path.join(dir, pre + `counter` + suffix)
97 if not os.path.exists(file):
98 return file
Guido van Rossumca549821997-08-12 18:00:12 +000099
100
101class TemporaryFileWrapper:
102 """Temporary file wrapper
103
104 This class provides a wrapper around files opened for temporary use.
105 In particular, it seeks to automatically remove the file when it is
106 no longer needed.
107 """
108 def __init__(self, file, path):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000109 self.file = file
110 self.path = path
Guido van Rossumca549821997-08-12 18:00:12 +0000111
112 def close(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000113 self.file.close()
114 os.unlink(self.path)
Guido van Rossumca549821997-08-12 18:00:12 +0000115
116 def __del__(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000117 try: self.close()
118 except: pass
Guido van Rossumca549821997-08-12 18:00:12 +0000119
120 def __getattr__(self, name):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000121 file = self.__dict__['file']
122 a = getattr(file, name)
123 setattr(self, name, a)
124 return a
Guido van Rossumca549821997-08-12 18:00:12 +0000125
126
Guido van Rossumb8c42c91997-12-19 04:29:50 +0000127def TemporaryFile(mode='w+b', bufsize=-1, suffix=""):
128 name = mktemp(suffix)
Guido van Rossumdce3d551998-10-24 01:34:45 +0000129 if os.name == 'posix':
130 # Unix -- be very careful
131 fd = os.open(name, os.O_RDWR|os.O_CREAT|os.O_EXCL, 0700)
Guido van Rossum2457fc21998-10-24 15:02:59 +0000132 try:
133 os.unlink(name)
134 return os.fdopen(fd, mode, bufsize)
135 except:
136 os.close(fd)
137 raise
Guido van Rossumca549821997-08-12 18:00:12 +0000138 else:
Guido van Rossumdce3d551998-10-24 01:34:45 +0000139 # Non-unix -- can't unlink file that's still open, use wrapper
140 file = open(name, mode, bufsize)
141 return TemporaryFileWrapper(file, name)