Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
cpython
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
cpython
Commits
543af759
Commit
543af759
authored
Oct 24, 2010
by
Nick Coghlan
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Issue 5178: Add tempfile.TemporaryDirectory (original patch by Neil Schemenauer)
parent
d4519c14
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
229 additions
and
3 deletions
+229
-3
Doc/library/tempfile.rst
Doc/library/tempfile.rst
+52
-1
Doc/whatsnew/3.2.rst
Doc/whatsnew/3.2.rst
+7
-0
Lib/tempfile.py
Lib/tempfile.py
+64
-1
Lib/test/test_tempfile.py
Lib/test/test_tempfile.py
+103
-1
Misc/NEWS
Misc/NEWS
+3
-0
No files found.
Doc/library/tempfile.rst
View file @
543af759
...
...
@@ -25,7 +25,7 @@ no longer necessary to use the global *tempdir* and *template* variables.
To maintain backward compatibility, the argument order is somewhat odd; it
is recommended to use keyword arguments for clarity.
The module defines the following user-callable
function
s:
The module defines the following user-callable
item
s:
.. function:: TemporaryFile(mode='w+b', buffering=None, encoding=None, newline=None, suffix='', prefix='tmp', dir=None)
...
...
@@ -83,6 +83,24 @@ The module defines the following user-callable functions:
used in a :keyword:`with` statement, just like a normal file.
.. function:: TemporaryDirectory(suffix='', prefix='tmp', dir=None)
This function creates a temporary directory using :func:`mkdtemp`
(the supplied arguments are passed directly to the underlying function).
The resulting object can be used as a context manager (see
:ref:`context-managers`). On completion of the context (or destruction
of the temporary directory object), the newly created temporary directory
and all its contents are removed from the filesystem.
The directory name can be retrieved from the :attr:`name` member
of the returned object.
The directory can be explicitly cleaned up by calling the
:func:`cleanup` method.
.. versionadded:: 3.2
.. function:: mkstemp(suffix='', prefix='tmp', dir=None, text=False)
Creates a temporary file in the most secure manner possible. There are
...
...
@@ -210,3 +228,36 @@ the appropriate function arguments, instead.
Return the filename prefix used to create temporary files. This does not
contain the directory component.
Examples
--------
Here are some examples of typical usage of the :mod:`tempfile` module::
>>> import tempfile
# create a temporary file and write some data to it
>>> fp = tempfile.TemporaryFile()
>>> fp.write('Hello world!')
# read data from file
>>> fp.seek(0)
>>> fp.read()
'Hello world!'
# close the file, it will be removed
>>> fp.close()
# create a temporary file using a context manager
>>> with tempfile.TemporaryFile() as fp:
... fp.write('Hello world!')
... fp.seek(0)
... fp.read()
'Hello world!'
>>>
# file is now closed and removed
# create a temporary directory using the context manager
>>> with tempfile.TemporaryDirectory() as tmpdirname:
... print 'created temporary directory', tmpdirname
>>>
# directory and contents have been removed
Doc/whatsnew/3.2.rst
View file @
543af759
...
...
@@ -496,6 +496,13 @@ New, Improved, and Deprecated Modules
(Contributed by Giampaolo Rodolà; :issue:`6706`.)
* The :mod:`tempfile` module has a new context manager,
:class:`~tempfile.TemporaryDirectory` which provides easy deterministic
cleanup of temporary directories.
(Contributed by Neil Schemenauer and Nick Coghlan; :issue:`5178`.)
Multi-threading
===============
...
...
Lib/tempfile.py
View file @
543af759
...
...
@@ -19,7 +19,7 @@ This module also provides some data items to the user:
__all__
=
[
"NamedTemporaryFile"
,
"TemporaryFile"
,
# high level safe interfaces
"SpooledTemporaryFile"
,
"SpooledTemporaryFile"
,
"TemporaryDirectory"
,
"mkstemp"
,
"mkdtemp"
,
# low level safe interfaces
"mktemp"
,
# deprecated unsafe interface
"TMP_MAX"
,
"gettempprefix"
,
# constants
...
...
@@ -613,3 +613,66 @@ class SpooledTemporaryFile:
def
xreadlines
(
self
,
*
args
):
return
self
.
_file
.
xreadlines
(
*
args
)
class
TemporaryDirectory
(
object
):
"""Create and return a temporary directory. This has the same
behavior as mkdtemp but can be used as a context manager. For
example:
with TemporaryDirectory() as tmpdir:
...
Upon exiting the context, the directory and everthing contained
in it are removed.
"""
def
__init__
(
self
,
suffix
=
""
,
prefix
=
template
,
dir
=
None
):
self
.
name
=
mkdtemp
(
suffix
,
prefix
,
dir
)
self
.
_closed
=
False
def
__enter__
(
self
):
return
self
.
name
def
cleanup
(
self
):
if
not
self
.
_closed
:
self
.
_rmtree
(
self
.
name
)
self
.
_closed
=
True
def
__exit__
(
self
,
exc
,
value
,
tb
):
self
.
cleanup
()
__del__
=
cleanup
# XXX (ncoghlan): The following code attempts to make
# this class tolerant of the module nulling out process
# that happens during CPython interpreter shutdown
# Alas, it doesn't actually manage it. See issue #10188
_listdir
=
staticmethod
(
_os
.
listdir
)
_path_join
=
staticmethod
(
_os
.
path
.
join
)
_isdir
=
staticmethod
(
_os
.
path
.
isdir
)
_remove
=
staticmethod
(
_os
.
remove
)
_rmdir
=
staticmethod
(
_os
.
rmdir
)
_os_error
=
_os
.
error
def
_rmtree
(
self
,
path
):
# Essentially a stripped down version of shutil.rmtree. We can't
# use globals because they may be None'ed out at shutdown.
for
name
in
self
.
_listdir
(
path
):
fullname
=
self
.
_path_join
(
path
,
name
)
try
:
isdir
=
self
.
_isdir
(
fullname
)
except
self
.
_os_error
:
isdir
=
False
if
isdir
:
self
.
_rmtree
(
fullname
)
else
:
try
:
self
.
_remove
(
fullname
)
except
self
.
_os_error
:
pass
try
:
self
.
_rmdir
(
path
)
except
self
.
_os_error
:
pass
Lib/test/test_tempfile.py
View file @
543af759
...
...
@@ -85,7 +85,8 @@ class test_exports(TC):
"gettempdir"
:
1
,
"tempdir"
:
1
,
"template"
:
1
,
"SpooledTemporaryFile"
:
1
"SpooledTemporaryFile"
:
1
,
"TemporaryDirectory"
:
1
,
}
unexp
=
[]
...
...
@@ -889,6 +890,107 @@ class test_TemporaryFile(TC):
if
tempfile
.
NamedTemporaryFile
is
not
tempfile
.
TemporaryFile
:
test_classes
.
append
(
test_TemporaryFile
)
# Helper for test_del_on_shutdown
class
NulledModules
:
def
__init__
(
self
,
*
modules
):
self
.
refs
=
[
mod
.
__dict__
for
mod
in
modules
]
self
.
contents
=
[
ref
.
copy
()
for
ref
in
self
.
refs
]
def
__enter__
(
self
):
for
d
in
self
.
refs
:
for
key
in
d
:
d
[
key
]
=
None
def
__exit__
(
self
,
*
exc_info
):
for
d
,
c
in
zip
(
self
.
refs
,
self
.
contents
):
d
.
clear
()
d
.
update
(
c
)
class
test_TemporaryDirectory
(
TC
):
"""Test TemporaryDirectory()."""
def
do_create
(
self
,
dir
=
None
,
pre
=
""
,
suf
=
""
,
recurse
=
1
):
if
dir
is
None
:
dir
=
tempfile
.
gettempdir
()
try
:
tmp
=
tempfile
.
TemporaryDirectory
(
dir
=
dir
,
prefix
=
pre
,
suffix
=
suf
)
except
:
self
.
failOnException
(
"TemporaryDirectory"
)
self
.
nameCheck
(
tmp
.
name
,
dir
,
pre
,
suf
)
# Create a subdirectory and some files
if
recurse
:
self
.
do_create
(
tmp
.
name
,
pre
,
suf
,
recurse
-
1
)
with
open
(
os
.
path
.
join
(
tmp
.
name
,
"test.txt"
),
"wb"
)
as
f
:
f
.
write
(
b"Hello world!"
)
return
tmp
def
test_explicit_cleanup
(
self
):
# A TemporaryDirectory is deleted when cleaned up
dir
=
tempfile
.
mkdtemp
()
try
:
d
=
self
.
do_create
(
dir
=
dir
)
self
.
assertTrue
(
os
.
path
.
exists
(
d
.
name
),
"TemporaryDirectory %s does not exist"
%
d
.
name
)
d
.
cleanup
()
self
.
assertFalse
(
os
.
path
.
exists
(
d
.
name
),
"TemporaryDirectory %s exists after cleanup"
%
d
.
name
)
finally
:
os
.
rmdir
(
dir
)
@
support
.
cpython_only
def
test_del_on_collection
(
self
):
# A TemporaryDirectory is deleted when garbage collected
dir
=
tempfile
.
mkdtemp
()
try
:
d
=
self
.
do_create
(
dir
=
dir
)
name
=
d
.
name
del
d
# Rely on refcounting to invoke __del__
self
.
assertFalse
(
os
.
path
.
exists
(
name
),
"TemporaryDirectory %s exists after __del__"
%
name
)
finally
:
os
.
rmdir
(
dir
)
@
unittest
.
expectedFailure
# See issue #10188
def
test_del_on_shutdown
(
self
):
# A TemporaryDirectory may be cleaned up during shutdown
# Make sure it works with the relevant modules nulled out
dir
=
tempfile
.
mkdtemp
()
try
:
d
=
self
.
do_create
(
dir
=
dir
)
# Mimic the nulling out of modules that
# occurs during system shutdown
modules
=
[
os
,
os
.
path
]
if
has_stat
:
modules
.
append
(
stat
)
with
NulledModules
(
*
modules
):
d
.
cleanup
()
self
.
assertFalse
(
os
.
path
.
exists
(
d
.
name
),
"TemporaryDirectory %s exists after cleanup"
%
d
.
name
)
finally
:
os
.
rmdir
(
dir
)
def
test_multiple_close
(
self
):
# Can be cleaned-up many times without error
d
=
self
.
do_create
()
d
.
cleanup
()
try
:
d
.
cleanup
()
d
.
cleanup
()
except
:
self
.
failOnException
(
"cleanup"
)
def
test_context_manager
(
self
):
# Can be used as a context manager
d
=
self
.
do_create
()
with
d
as
name
:
self
.
assertTrue
(
os
.
path
.
exists
(
name
))
self
.
assertEqual
(
name
,
d
.
name
)
self
.
assertFalse
(
os
.
path
.
exists
(
name
))
test_classes
.
append
(
test_TemporaryDirectory
)
def
test_main
():
support
.
run_unittest
(
*
test_classes
)
...
...
Misc/NEWS
View file @
543af759
...
...
@@ -51,6 +51,9 @@ Core and Builtins
Library
-------
- Issue #5178: Added tempfile.TemporaryDirectory class that can be used
as a context manager.
- Issue #1349106: Generator (and BytesGenerator) flatten method and Header
encode method now support a 'linesep' argument.
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment