blob: eef6bffe11ed4adbf284704bdcfa8383624ac482 [file] [log] [blame]
Guido van Rossume7b146f2000-02-04 15:28:42 +00001"""Temporary files and filenames."""
2
Guido van Rossum41f95031992-03-31 19:02:01 +00003# 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
Guido van Rossum41f95031992-03-31 19:02:01 +000017def gettempdir():
Guido van Rossume7b146f2000-02-04 15:28:42 +000018 """Function to calculate the directory to use."""
Guido van Rossumf4aaf861996-05-28 23:31:34 +000019 global tempdir
Guido van Rossum4033ad71996-08-08 18:33:56 +000020 if tempdir is not None:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000021 return tempdir
Guido van Rossum29e5f5d1998-04-09 14:27:57 +000022 try:
23 pwd = os.getcwd()
24 except (AttributeError, os.error):
25 pwd = os.curdir
26 attempdirs = ['/usr/tmp', '/tmp', pwd]
Guido van Rossum3e065ad1996-08-20 20:38:59 +000027 if os.name == 'nt':
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000028 attempdirs.insert(0, 'C:\\TEMP')
29 attempdirs.insert(0, '\\TEMP')
Guido van Rossumf4f756c1997-04-11 19:00:53 +000030 elif os.name == 'mac':
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000031 import macfs, MACFS
32 try:
33 refnum, dirid = macfs.FindFolder(MACFS.kOnSystemDisk,
Guido van Rossum57a06611998-04-28 16:03:34 +000034 MACFS.kTemporaryFolderType, 1)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000035 dirname = macfs.FSSpec((refnum, dirid, '')).as_pathname()
36 attempdirs.insert(0, dirname)
37 except macfs.error:
38 pass
Guido van Rossumca549821997-08-12 18:00:12 +000039 for envname in 'TMPDIR', 'TEMP', 'TMP':
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000040 if os.environ.has_key(envname):
41 attempdirs.insert(0, os.environ[envname])
Guido van Rossum3e065ad1996-08-20 20:38:59 +000042 testfile = gettempprefix() + 'test'
Guido van Rossumf4aaf861996-05-28 23:31:34 +000043 for dir in attempdirs:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000044 try:
Guido van Rossum00f09b32000-04-24 13:28:02 +000045 filename = os.path.join(dir, testfile)
46 if os.name == 'posix':
47 try:
48 fd = os.open(filename, os.O_RDWR|os.O_CREAT|os.O_EXCL, 0700)
49 except OSError:
50 pass
51 else:
52 fp = os.fdopen(fd, 'w')
53 fp.write('blat')
54 fp.close()
55 os.unlink(filename)
56 del fp, fd
57 tempdir = dir
58 break
59 else:
60 fp = open(filename, 'w')
61 fp.write('blat')
62 fp.close()
63 os.unlink(filename)
64 tempdir = dir
65 break
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000066 except IOError:
67 pass
Guido van Rossumf4aaf861996-05-28 23:31:34 +000068 if tempdir is None:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000069 msg = "Can't find a usable temporary directory amongst " + `attempdirs`
70 raise IOError, msg
Guido van Rossumf4aaf861996-05-28 23:31:34 +000071 return tempdir
Guido van Rossum41f95031992-03-31 19:02:01 +000072
73
Guido van Rossumb0e57181998-10-14 20:27:05 +000074_pid = None
75
Guido van Rossum41f95031992-03-31 19:02:01 +000076def gettempprefix():
Guido van Rossume7b146f2000-02-04 15:28:42 +000077 """Function to calculate a prefix of the filename to use."""
Guido van Rossumb0e57181998-10-14 20:27:05 +000078 global template, _pid
79 if os.name == 'posix' and _pid and _pid != os.getpid():
80 # Our pid changed; we must have forked -- zap the template
81 template = None
82 if template is None:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000083 if os.name == 'posix':
Guido van Rossumb0e57181998-10-14 20:27:05 +000084 _pid = os.getpid()
85 template = '@' + `_pid` + '.'
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000086 elif os.name == 'nt':
87 template = '~' + `os.getpid()` + '-'
88 elif os.name == 'mac':
89 template = 'Python-Tmp-'
90 else:
91 template = 'tmp' # XXX might choose a better one
92 return template
Guido van Rossumcff34541992-01-14 18:31:56 +000093
Guido van Rossumeee94981991-11-12 15:38:08 +000094
Guido van Rossum4a3a41f1991-12-26 13:10:50 +000095# Counter for generating unique names
Guido van Rossumeee94981991-11-12 15:38:08 +000096
Guido van Rossum4a3a41f1991-12-26 13:10:50 +000097counter = 0
Guido van Rossumeee94981991-11-12 15:38:08 +000098
99
Guido van Rossumb8c42c91997-12-19 04:29:50 +0000100def mktemp(suffix=""):
Guido van Rossume7b146f2000-02-04 15:28:42 +0000101 """User-callable function to return a unique temporary file name."""
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000102 global counter
103 dir = gettempdir()
104 pre = gettempprefix()
105 while 1:
106 counter = counter + 1
107 file = os.path.join(dir, pre + `counter` + suffix)
108 if not os.path.exists(file):
109 return file
Guido van Rossumca549821997-08-12 18:00:12 +0000110
111
112class TemporaryFileWrapper:
113 """Temporary file wrapper
114
115 This class provides a wrapper around files opened for temporary use.
116 In particular, it seeks to automatically remove the file when it is
117 no longer needed.
118 """
119 def __init__(self, file, path):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000120 self.file = file
121 self.path = path
Guido van Rossumca549821997-08-12 18:00:12 +0000122
123 def close(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000124 self.file.close()
125 os.unlink(self.path)
Guido van Rossumca549821997-08-12 18:00:12 +0000126
127 def __del__(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000128 try: self.close()
129 except: pass
Guido van Rossumca549821997-08-12 18:00:12 +0000130
131 def __getattr__(self, name):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000132 file = self.__dict__['file']
133 a = getattr(file, name)
Guido van Rossum6b708d51999-06-01 18:55:36 +0000134 if type(a) != type(0):
135 setattr(self, name, a)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000136 return a
Guido van Rossumca549821997-08-12 18:00:12 +0000137
138
Guido van Rossumb8c42c91997-12-19 04:29:50 +0000139def TemporaryFile(mode='w+b', bufsize=-1, suffix=""):
Guido van Rossume7b146f2000-02-04 15:28:42 +0000140 """Create and return a temporary file (opened read-write by default)."""
Guido van Rossumb8c42c91997-12-19 04:29:50 +0000141 name = mktemp(suffix)
Guido van Rossumdce3d551998-10-24 01:34:45 +0000142 if os.name == 'posix':
143 # Unix -- be very careful
144 fd = os.open(name, os.O_RDWR|os.O_CREAT|os.O_EXCL, 0700)
Guido van Rossum2457fc21998-10-24 15:02:59 +0000145 try:
146 os.unlink(name)
147 return os.fdopen(fd, mode, bufsize)
148 except:
149 os.close(fd)
150 raise
Guido van Rossumca549821997-08-12 18:00:12 +0000151 else:
Guido van Rossumdce3d551998-10-24 01:34:45 +0000152 # Non-unix -- can't unlink file that's still open, use wrapper
153 file = open(name, mode, bufsize)
154 return TemporaryFileWrapper(file, name)