blob: 2c9ec9b0d1ed8e018b729ff4f9e5661681808365 [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
63def gettempprefix():
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000064 global template
65 if template == None:
66 if os.name == 'posix':
67 template = '@' + `os.getpid()` + '.'
68 elif os.name == 'nt':
69 template = '~' + `os.getpid()` + '-'
70 elif os.name == 'mac':
71 template = 'Python-Tmp-'
72 else:
73 template = 'tmp' # XXX might choose a better one
74 return template
Guido van Rossumcff34541992-01-14 18:31:56 +000075
Guido van Rossumeee94981991-11-12 15:38:08 +000076
Guido van Rossum4a3a41f1991-12-26 13:10:50 +000077# Counter for generating unique names
Guido van Rossumeee94981991-11-12 15:38:08 +000078
Guido van Rossum4a3a41f1991-12-26 13:10:50 +000079counter = 0
Guido van Rossumeee94981991-11-12 15:38:08 +000080
81
Guido van Rossum41f95031992-03-31 19:02:01 +000082# User-callable function to return a unique temporary file name
Guido van Rossumeee94981991-11-12 15:38:08 +000083
Guido van Rossumb8c42c91997-12-19 04:29:50 +000084def mktemp(suffix=""):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000085 global counter
86 dir = gettempdir()
87 pre = gettempprefix()
88 while 1:
89 counter = counter + 1
90 file = os.path.join(dir, pre + `counter` + suffix)
91 if not os.path.exists(file):
92 return file
Guido van Rossumca549821997-08-12 18:00:12 +000093
94
95class TemporaryFileWrapper:
96 """Temporary file wrapper
97
98 This class provides a wrapper around files opened for temporary use.
99 In particular, it seeks to automatically remove the file when it is
100 no longer needed.
101 """
102 def __init__(self, file, path):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000103 self.file = file
104 self.path = path
Guido van Rossumca549821997-08-12 18:00:12 +0000105
106 def close(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000107 self.file.close()
108 os.unlink(self.path)
Guido van Rossumca549821997-08-12 18:00:12 +0000109
110 def __del__(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000111 try: self.close()
112 except: pass
Guido van Rossumca549821997-08-12 18:00:12 +0000113
114 def __getattr__(self, name):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000115 file = self.__dict__['file']
116 a = getattr(file, name)
117 setattr(self, name, a)
118 return a
Guido van Rossumca549821997-08-12 18:00:12 +0000119
120
Guido van Rossumb8c42c91997-12-19 04:29:50 +0000121def TemporaryFile(mode='w+b', bufsize=-1, suffix=""):
122 name = mktemp(suffix)
123 file = open(name, mode, bufsize)
Guido van Rossumca549821997-08-12 18:00:12 +0000124 try:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000125 os.unlink(name)
Guido van Rossumca549821997-08-12 18:00:12 +0000126 except os.error:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000127 # Non-unix -- can't unlink file that's still open, use wrapper
128 return TemporaryFileWrapper(file, name)
Guido van Rossumca549821997-08-12 18:00:12 +0000129 else:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000130 return file