1 """Temporary files and filenames."""
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...
9 # Parameters that the caller may set to override the defaults
14 """Function to calculate the directory to use."""
16 if tempdir
is not None:
20 except (AttributeError, os
.error
):
22 attempdirs
= ['/var/tmp', '/usr/tmp', '/tmp', pwd
]
24 attempdirs
.insert(0, 'C:\\TEMP')
25 attempdirs
.insert(0, '\\TEMP')
26 elif os
.name
== 'mac':
29 refnum
, dirid
= macfs
.FindFolder(MACFS
.kOnSystemDisk
,
30 MACFS
.kTemporaryFolderType
, 1)
31 dirname
= macfs
.FSSpec((refnum
, dirid
, '')).as_pathname()
32 attempdirs
.insert(0, dirname
)
35 for envname
in 'TMPDIR', 'TEMP', 'TMP':
36 if os
.environ
.has_key(envname
):
37 attempdirs
.insert(0, os
.environ
[envname
])
38 testfile
= gettempprefix() + 'test'
39 for dir in attempdirs
:
41 filename
= os
.path
.join(dir, testfile
)
42 if os
.name
== 'posix':
44 fd
= os
.open(filename
,
45 os
.O_RDWR | os
.O_CREAT | os
.O_EXCL
, 0700)
49 fp
= os
.fdopen(fd
, 'w')
57 fp
= open(filename
, 'w')
66 msg
= "Can't find a usable temporary directory amongst " + `attempdirs`
71 # template caches the result of gettempprefix, for speed, when possible.
72 # XXX unclear why this isn't "_template"; left it "template" for backward
74 if os
.name
== "posix":
75 # We don't try to cache the template on posix: the pid may change on us
76 # between calls due to a fork, and on Linux the pid changes even for
77 # another thread in the same process. Since any attempt to keep the
78 # cache in synch would have to call os.getpid() anyway in order to make
79 # sure the pid hasn't changed between calls, a cache wouldn't save any
80 # time. In addition, a cache is difficult to keep correct with the pid
81 # changing willy-nilly, and earlier attempts proved buggy (races).
84 # Else the pid never changes, so gettempprefix always returns the same
87 template
= '~' + `os
.getpid()`
+ '-'
88 elif os
.name
== 'mac':
89 template
= 'Python-Tmp-'
91 template
= 'tmp' # XXX might choose a better one
94 """Function to calculate a prefix of the filename to use.
96 This incorporates the current process id on systems that support such a
97 notion, so that concurrent processes don't generate the same prefix.
102 return '@' + `os
.getpid()`
+ '.'
107 def mktemp(suffix
=""):
108 """User-callable function to return a unique temporary file name."""
110 pre
= gettempprefix()
112 i
= _counter
.get_next()
113 file = os
.path
.join(dir, pre
+ str(i
) + suffix
)
114 if not os
.path
.exists(file):
118 class TemporaryFileWrapper
:
119 """Temporary file wrapper
121 This class provides a wrapper around files opened for temporary use.
122 In particular, it seeks to automatically remove the file when it is
125 def __init__(self
, file, path
):
137 def __getattr__(self
, name
):
138 file = self
.__dict
__['file']
139 a
= getattr(file, name
)
140 if type(a
) != type(0):
141 setattr(self
, name
, a
)
145 def TemporaryFile(mode
='w+b', bufsize
=-1, suffix
=""):
146 """Create and return a temporary file (opened read-write by default)."""
147 name
= mktemp(suffix
)
148 if os
.name
== 'posix':
149 # Unix -- be very careful
150 fd
= os
.open(name
, os
.O_RDWR|os
.O_CREAT|os
.O_EXCL
, 0700)
153 return os
.fdopen(fd
, mode
, bufsize
)
158 # Non-unix -- can't unlink file that's still open, use wrapper
159 file = open(name
, mode
, bufsize
)
160 return TemporaryFileWrapper(file, name
)
162 # In order to generate unique names, mktemp() uses _counter.get_next().
163 # This returns a unique integer on each call, in a threadsafe way (i.e.,
164 # multiple threads will never see the same integer). The integer will
165 # usually be a Python int, but if _counter.get_next() is called often
166 # enough, it will become a Python long.
167 # Note that the only name that survives this next block of code
170 class _ThreadSafeCounter
:
171 def __init__(self
, mutex
, initialvalue
=0):
173 self
.i
= initialvalue
180 except OverflowError:
181 newi
= long(result
) + 1
196 _counter
= _ThreadSafeCounter(_DummyMutex())
200 _counter
= _ThreadSafeCounter(thread
.allocate_lock())
203 del _ThreadSafeCounter