### Navigation

- index
- modules |
- next |
- previous |
- Miscellaneous »

# Temporary file handling

AUTHORS:

- Volker Braun, Jeroen Demeyer (2012-10-18): move these functions here from sage/misc/misc.py and make them secure, see trac ticket #13579.
- Jeroen Demeyer (2013-03-17): add class:\(atomic_write\), see trac ticket #14292.

class `sage.misc.temporary_file.``atomic_write`(target_filename, append=False)

  Write to a given file using a temporary file and then rename it to the target file. This renaming should be atomic on modern operating systems. Therefore, this class can be used to avoid race conditions when a file might be read while it is being written. It also avoids having partially written files due to exceptions or crashes.

  This is to be used in a `with` statement, where a temporary file is created when entering the `with` and is moved in place of the target file when exiting the `with` (if no exceptions occured).

  INPUT:

  - `target_filename` – the name of the file to be written. Normally, the contents of this file will be overwritten.
  - `append` – (boolean, default: False) if True and `target_filename` is an existing file, then copy the current contents of `target_filename` to the temporary file when entering the `with` statement. Otherwise, the temporary file is initially empty.

  EXAMPLES:

      sage: from sage.misc.temporary_file import atomic_write
      sage: target_file = tmp_filename()
      sage: open(target_file, "w").write("Old contents")
      sage: with atomic_write(target_file) as f:
      ....:     f.write("New contents")
      ....:     f.flush()
      ....:     open(target_file, "r").read()
      'Old contents'
      sage: open(target_file, "r").read()
      'New contents'

  The name of the temporary file can be accessed using `f.name`. It is not a problem to close and re-open the temporary file:

      sage: from sage.misc.temporary_file import atomic_write
      sage: target_file = tmp_filename()
      sage: open(target_file, "w").write("Old contents")
      sage: with atomic_write(target_file) as f:
      ....:     f.close()
      ....:     open(f.name, "w").write("Newer contents")
      sage: open(target_file, "r").read()
      'Newer contents'

  If an exception occurs while writing the file, the target file is not touched:

      sage: with atomic_write(target_file) as f:
      ....:     f.write("Newest contents")
      ....:     raise RuntimeError
      Traceback (most recent call last):
      ...
      RuntimeError
      sage: open(target_file, "r").read()
      'Newer contents'

  Some examples of using the `append` option. Note that the file is never opened in “append” mode, it is possible to overwrite existing data:

      sage: target_file = tmp_filename()
      sage: with atomic_write(target_file, append=True) as f:
      ....:     f.write("Hello")
      sage: with atomic_write(target_file, append=True) as f:
      ....:     f.write(" World")
      sage: open(target_file, "r").read()
      'Hello World'
      sage: with atomic_write(target_file, append=True) as f:
      ....:     f.seek(0)
      ....:     f.write("HELLO")
      sage: open(target_file, "r").read()
      'HELLO World'

  If the target file is a symbolic link, the link is kept and the target of the link is written to:

      sage: link_to_target = os.path.join(tmp_dir(), "templink")
      sage: os.symlink(target_file, link_to_target)
      sage: with atomic_write(link_to_target) as f:
      ....:     f.write("Newest contents")
      sage: open(target_file, "r").read()
      'Newest contents'

  Test writing twice to the same target file. The outermost `with` “wins”:

      sage: open(target_file, "w").write(">>> ")
      sage: with atomic_write(target_file, append=True) as f,         ....:          atomic_write(target_file, append=True) as g:
      ....:     f.write("AAA"); f.close()
      ....:     g.write("BBB"); g.close()
      sage: open(target_file, "r").read()
      '>>> AAA'

`sage.misc.temporary_file.``delete_tmpfiles`()

  Remove the directory `SAGE_TMP`.

  TESTS:

  This is automatically run when Sage exits, test this by running a separate session of Sage:

      sage: from sage.tests.cmdline import test_executable
      sage: child_SAGE_TMP, err, ret = test_executable(["sage", "-c", "print SAGE_TMP"])
      sage: err, ret
      ('', 0)
      sage: os.path.exists(child_SAGE_TMP)  # indirect doctest
      False

  The parent directory should exist:

      sage: parent_SAGE_TMP = os.path.normpath(child_SAGE_TMP + '/..')
      sage: os.path.isdir(parent_SAGE_TMP)
      True

`sage.misc.temporary_file.``graphics_filename`(ext='png')

  When run from the Sage notebook, return the next available canonical filename for a plot/graphics file in the current working directory. Otherwise, return a temporary file inside `SAGE_TMP`.

  INPUT:

  - `ext` – (default: `"png"`) A file extension (without the dot) for the filename.

  OUTPUT:

  The path of the temporary file created. In the notebook, this is a filename without path in the current directory. Otherwise, this an absolute path.

  EXAMPLES:

      sage: from sage.misc.temporary_file import graphics_filename
      sage: print graphics_filename()  # random, typical filename for sagenb
      sage0.png

  TESTS:

  When doctesting, this returns instead a random temporary file. We check that it’s a file inside `SAGE_TMP` and that the extension is correct:

      sage: fn = graphics_filename(ext="jpeg")
      sage: fn.startswith(str(SAGE_TMP))
      True
      sage: fn.endswith('.jpeg')
      True

`sage.misc.temporary_file.``tmp_dir`(name='dir_', ext='')

  Create and return a temporary directory in `$HOME/.sage/temp/hostname/pid/`

  The temporary directory is deleted automatically when Sage exits.

  INPUT:

  - `name` – (default: `"dir_"`) A prefix for the directory name.
  - `ext` – (default: `""`) A suffix for the directory name.

  OUTPUT:

  The absolute path of the temporary directory created, with a trailing slash (or whatever the path separator is on your OS).

  EXAMPLES:

      sage: d = tmp_dir('dir_testing_', '.extension')
      sage: d   # random output
      '/home/username/.sage/temp/hostname/7961/dir_testing_XgRu4p.extension/'
      sage: os.chdir(d)
      sage: _ = open('file_inside_d', 'w')

  Temporary directories are unaccessible by other users:

      sage: os.stat(d).st_mode & 0o077
      0

`sage.misc.temporary_file.``tmp_filename`(name='tmp_', ext='')

  Create and return a temporary file in `$HOME/.sage/temp/hostname/pid/`

  The temporary file is deleted automatically when Sage exits.

  Warning

  If you need a particular file extension always use `tmp_filename(ext=".foo")`, this will ensure that the file does not yet exist. If you were to use `tmp_filename()+".foo"`, then you might overwrite an existing file!

  INPUT:

  - `name` – (default: `"tmp_"`) A prefix for the file name.
  - `ext` – (default: `""`) A suffix for the file name. If you want a filename extension in the usual sense, this should start with a dot.

  OUTPUT:

  The absolute path of the temporary file created.

  EXAMPLES:

      sage: fn = tmp_filename('just_for_testing_', '.extension')
      sage: fn  # random
      '/home/username/.sage/temp/hostname/8044/just_for_testing_tVVHsn.extension'
      sage: _ = open(fn, 'w')

  Temporary files are unaccessible by other users:

      sage: os.stat(fn).st_mode & 0o077
      0

### Navigation

- index
- modules |
- next |
- previous |
- Miscellaneous »