Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create a temporary file that can be read by a subprocess?

I'm writing a Python script that needs to write some data to a temporary file, then create a subprocess running a C++ program that will read the temporary file. I'm trying to use NamedTemporaryFile for this, but according to the docs,

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).

And indeed, on Windows if I flush the temporary file after writing, but don't close it until I want it to go away, the subprocess isn't able to open it for reading.

I'm working around this by creating the file with delete=False, closing it before spawning the subprocess, and then manually deleting it once I'm done:

fileTemp = tempfile.NamedTemporaryFile(delete = False) try:     fileTemp.write(someStuff)     fileTemp.close()     # ...run the subprocess and wait for it to complete... finally:     os.remove(fileTemp.name) 

This seems inelegant. Is there a better way to do this? Perhaps a way to open up the permissions on the temporary file so the subprocess can get at it?

like image 746
Nathan Reed Avatar asked Mar 02 '13 00:03

Nathan Reed


People also ask

How do I create a tmp file?

To create and use a temporary file The application opens the user-provided source text file by using CreateFile. The application retrieves a temporary file path and file name by using the GetTempPath and GetTempFileName functions, and then uses CreateFile to create the temporary file.

How do I create a temp folder?

Open your File Explorer (it's usually the first button on your desktop taskbar, looks like a folder). Go to the "This PC" section on the left, and then double-click your C: drive. On the Home tab at the top, click "New Folder" and name it "Temp".

What is a temporary file example?

Techopedia Explains Temporary File In terms of backup purposes, Microsoft's Office applications are good examples of this. For example, Microsoft Word and Excel save a temporary file associated with the current open document that it points to after a computer has recovered from a crash or power outage.


2 Answers

Since nobody else appears to be interested in leaving this information out in the open...

tempfile does expose a function, mkdtemp(), which can trivialize this problem:

try:     temp_dir = mkdtemp()     temp_file = make_a_file_in_a_dir(temp_dir)     do_your_subprocess_stuff(temp_file)     remove_your_temp_file(temp_file) finally:     os.rmdir(temp_dir) 

I leave the implementation of the intermediate functions up to the reader, as one might wish to do things like use mkstemp() to tighten up the security of the temporary file itself, or overwrite the file in-place before removing it. I don't particularly know what security restrictions one might have that are not easily planned for by perusing the source of tempfile.

Anyway, yes, using NamedTemporaryFile on Windows might be inelegant, and my solution here might also be inelegant, but you've already decided that Windows support is more important than elegant code, so you might as well go ahead and do something readable.

like image 75
Corbin Avatar answered Sep 21 '22 16:09

Corbin


According to Richard Oudkerk

(...) the only reason that trying to reopen a NamedTemporaryFile fails on Windows is because when we reopen we need to use O_TEMPORARY.

and he gives an example of how to do this in Python 3.3+

import os, tempfile  DATA = b"hello bob"  def temp_opener(name, flag, mode=0o777):     return os.open(name, flag | os.O_TEMPORARY, mode)  with tempfile.NamedTemporaryFile() as f:     f.write(DATA)     f.flush()     with open(f.name, "rb", opener=temp_opener) as f:         assert f.read() == DATA  assert not os.path.exists(f.name) 

Because there's no opener parameter in the built-in open() in Python 2.x, we have to combine lower level os.open() and os.fdopen() functions to achieve the same effect:

import subprocess import tempfile  DATA = b"hello bob"  with tempfile.NamedTemporaryFile() as f:     f.write(DATA)     f.flush()      subprocess_code = \     """import os        f = os.fdopen(os.open(r'{FILENAME}', os.O_RDWR | os.O_BINARY | os.O_TEMPORARY), 'rb')        assert f.read() == b'{DATA}'     """.replace('\n', ';').format(FILENAME=f.name, DATA=DATA)      subprocess.check_output(['python', '-c', subprocess_code]) == DATA 
like image 24
Piotr Dobrogost Avatar answered Sep 19 '22 16:09

Piotr Dobrogost