85

I want to use tempfile.NamedTemporaryFile() to write some contents into it and then open that file. I have written following code:

tf = tempfile.NamedTemporaryFile()
tfName = tf.name
tf.seek(0)
tf.write(contents)
tf.flush()

but I am unable to open this file and see its contents in Notepad or similar application. Is there any way to achieve this? Why can't I do something like:

os.system('start notepad.exe ' + tfName)

at the end.

I don't want to save the file permanently on my system. I just want the contents to be opened as a text in Notepad or similar application and delete the file when I close that application.

0

3 Answers 3

85

This could be one of two reasons:

Firstly, by default the temporary file is deleted as soon as it is closed. To fix this use:

tf = tempfile.NamedTemporaryFile(delete=False)

and then delete the file manually once you've finished viewing it in the other application.

Alternatively, it could be that because the file is still open in Python Windows won't let you open it using another application.

Edit: to answer some questions from the comments:

As of the docs from 2 when using delete=False the file can be removed by using:

 tf.close()
 os.unlink(tf.name)
Sign up to request clarification or add additional context in comments.

4 Comments

So what is the best way to remove it when I'm done with it? tf.unlink? os.remove? path.remove?
@ThomasAhle What would you use?
You need add the import: import tempfile to use.
If I use delete=False, but use the context manager (with tempfile.NamedTemporaryFile() as temp:), will it still delete the file when it goes out of scope (as opposed to when it is closed), or do I still have to delete it manually?
83

You can also use it with a context manager so that the file will be closed/deleted when it goes out of scope. It will also be cleaned up if the code in the context manager raises.

import tempfile
with tempfile.NamedTemporaryFile() as temp:
    temp.write('Some data')
    temp.flush()

    # do something interesting with temp before it is destroyed

5 Comments

Keep in mind that you can't really pass temp.name to other processes to do something with it on Windows (which seems to be OP's platform). From the manual: "Whether the name can be used to open the file a second time, while the named temporary file is still open, varies across platforms (it can be so used on Unix; it cannot on Windows NT or later)."
Not sure if it would help in any way, but Django overwrote the NamedTemporaryFile so it would work with Windows so it might be worth looking at what they did to make that happen: code.djangoproject.com/wiki/NamedTemporaryFile
It appears that calling flush is necessary (Otherwise, I get an error in a subprocess called to read from the file).
Flush won't write the file to disk necessarily
You should use with tempfile.NamedTemporaryFile(mode='w+t') as temp: so that you can actually write string text to the file. What you have now opens the temp file in binary mode.
31

Here is a useful context manager for this. (In my opinion, this functionality should be part of the Python standard library.)

# python2 or python3
import contextlib
import os

@contextlib.contextmanager
def temporary_filename(suffix=None):
  """Context that introduces a temporary file.

  Creates a temporary file, yields its name, and upon context exit, deletes it.
  (In contrast, tempfile.NamedTemporaryFile() provides a 'file' object and
  deletes the file as soon as that file object is closed, so the temporary file
  cannot be safely re-opened by another library or process.)

  Args:
    suffix: desired filename extension (e.g. '.mp4').

  Yields:
    The name of the temporary file.
  """
  import tempfile
  try:
    f = tempfile.NamedTemporaryFile(suffix=suffix, delete=False)
    tmp_name = f.name
    f.close()
    yield tmp_name
  finally:
    os.unlink(tmp_name)

# Example:
with temporary_filename() as filename:
  os.system('echo Hello >' + filename)
  assert 6 <= os.path.getsize(filename) <= 8  # depending on text EOL
assert not os.path.exists(filename)

2 Comments

Should definitely go into the standard library!
Great code. Could be improved by 1. using pathlib 2. adding robustness in the finally (case where tmp_name is not defined)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.