How can i find the path of tempfile in django - python

I am using pdftk like this
pdftk template.pdf fill_form /temp/input.fdf output /temp/output.pdf
Now this is working fine
But now i have generated the temporary file instead of /temp/input.fdf with this
myfile = tempfile.NamedTemporaryFile()
myfile.write(fdf)
myfile.seek(0)
myfile.close()
Now i don't know how can i pass myfile as input to the pdftk

myfile.name will get you the file path.
Note that tempfiles do not exist after close(). From the docs:
tempfile.TemporaryFile([mode='w+b'[, bufsize=-1[, suffix=''[,
prefix='tmp'[, dir=None]]]]])
Return a file-like object that can be used as a temporary storage
area. The file is created using mkstemp(). It will be destroyed as
soon as it is closed (including an implicit close when the object is
garbage collected). Under Unix, the directory entry for the file is
removed immediately after the file is created. Other platforms do not
support this; your code should not rely on a temporary file created
using this function having or not having a visible name in the file
system.
Source: http://docs.python.org/2/library/tempfile.html

Can't you get the name using
myfile = tempfile.NamedTemporaryFile()
myfile.write(fdf)
myfile.seek(0)
myfile.close()
print(myfile.name)

Related

Create file in memory using python and assign a name to file (universal naming convention)?

Using a library such as Python's io, I can create a file e.g. csv format, in memory. However, I cannot get a UNC (Universal Naming Convention) referencing this file. How would I be able to assign such a name to an in-memory file created by Python?
A "file" created in memory using the io module is not a "file" as far as the OS is concerned. You can't open it by name or access it from outside the process. This file only exists as a variable in the program.
You can get the string contents directly, as in the example # https://docs.python.org/3/library/io.html#io.StringIO
import io
output = io.StringIO()
output.write('First line.\n')
print('Second line.', file=output)
contents = output.getvalue()
or you can rewind the file and read it back:
output.seek(0)
contents = output.read()

Python--best way to use "open" command with in-memory str

I have a library I need to call that takes a local file path as input and runs open(local_path, 'rb'). However, I don't have a local file--I have an in memory text string. Right now I am writing that to a temp file and passing that, but it seems wasteful. Is there a better way to do this, given that I need to be able to run open(local_path, 'rb') on it?
Current code:
text = "Some text"
temp = tempfile.TemporaryFile(delete=False)
temp.write(bytes(text, 'UTF-8'))
temp.seek(0)
temp.close()
#call external lib here, passing in temp.name as the local_path input
Later, inside the lib I need to use (I can't edit this):
with open(local_path, 'rb') as content_file:
file_content = content_file.read()
Since the function you call in turn calls open() with the passed parameter, you must give it a str or a PathLike. This means you basically need a file which exists in the file system. You won't be able to pass an in-memory object like I was originally thinking.
Original answer:
I suggest looking at the io package. Specifically, StringIO provides a file-like wrapper on an in-memory string object. If you need binary, then try BytesIO.

Do I need to close the OS-level handle returned to me by tempfile.mkstemp if not using it?

I need to create a temporary file to write some data out to in Python 3. The file will be written to via a separate module which deals with opening the file from a path given as a string.
I'm using tempfile.mkstemp() to create this temporary file and according to the docs:
mkstemp() returns a tuple containing an OS-level handle to an open file (as would be returned by os.open()) and the absolute pathname of that file, in that order.
Given I'm not going to be using the open OS-level file handle given to me, do I need to close it? I understand about regular Python file handles and closing them but I'm not familiar with OS-level file descriptors/handles.
So is this better:
fd, filename = tempfile.mkstemp()
os.close(fd)
Or can I simply just do this:
_, output_filename = tempfile.mkstemp()
The returned file descriptor is not a file object, the garbage collector will not close it for you.
You should use:
fd, filename = tempfile.mkstemp()
os.close(fd)
The returned file descriptor is useful to avoid race conditions where the filename is replaced with a symbolic link to a file that the attacker can not read but you can which can result in data exposure.

Change open file access mode

Is it possible to change file access mode after the file has been opened?
f=open(my_file, 'r')
change f to be able to write to it, or to declare that the file should be opened in universal newline mode?
Since changing file descriptor's permissions is not supported by Linux nor Windows. (there is no posix function to change open mode in linux at least), it's not possible to change it's permissions once the file descriptor have been set (Some OS specific tricks exists but I wouldn't recommend it).
You will need to reopen it with other permissions.
While there doesn't seem to be any way of changing the access mode on the underlying descriptor you could do the work somewhat at the python object level if you want to restrict the access (if you want to make a readonly file writable you're out of luck). Something like this:
f=open(my_file, 'w+')
f.write = None
f.writelines = None
# etc...
If you're using python2 you would need to wrap the file object to be able to disable the writing methods.
While you could restore a such modified file object to be writable again (and thereby you could circumvent the block - which by the way is almost always the case in python), it could be made to emulate the behaviour of a read-only file (which would be good enough for many cases).
You can open file as follows to be able to read and write
f = open(my_file, 'r+')
Assuming you've closed the file, just reassign to a new file object:
f = open(my_file, 'w')
Given that you have a file object f_r that was opened only for reading, you can use os.fdopen() to get file object f_w that is associated with the same file, but has different mode:
f_r = open(filename, "r")
f_w = os.fdopen(f_read.fileno(), "a+")
f_w.write("Here I come\n")
However, this path can lead to misery and suffering when misused. Since file objects do some buffering (if not disabled), simultaneous use of both f_r and f_w can cause unexpected results. Also reopening <stdin> or <stdout> may or may not do what you need or expect.
Here's how I solved this problem. For context, in my case, the file was only stored in memory, not on the disk, so I wasn't able to just reopen it from there.
from io import StringIO
...
bytes = file.read()
string = bytes.decode("utf-8") # or whatever encoding you wanna use
file = StringIO(string)
If you do not want to reopen it, use:
f.mode = "mode-to-change-to"#w, a, r, ect.
for mode,
f.name = "file_name"
for name, and:
f.encoding = "encoding"#default is UTF-8
for encoding.
Edit
you should use:
with open("filename", "mode") as f:
#do something
f.mode = "another-mode"
#do something else
so that the file closes automaticly when you are finished

How to generate temporary file in django and then destroy

I am doing some file processing and for generating the file i need to generate some temporary file from existing data and then use that file as input to my function.
But i am confused where should i save that file and then delete it.
Is there any temp location where files automatically gets deleted after user session
Python has the tempfile module for exactly this purpose. You do not need to worry about the location/deletion of the file, it works on all supported platforms.
There are three types of temporary files:
tempfile.TemporaryFile - just basic temporary file,
tempfile.NamedTemporaryFile - "This function operates exactly as TemporaryFile() does, except that the file is guaranteed to have a visible name in the file system (on Unix, the directory entry is not unlinked). That name can be retrieved from the name attribute of the file object.",
tempfile.SpooledTemporaryFile - "This function operates exactly as TemporaryFile() does, except that data is spooled in memory until the file size exceeds max_size, or until the file’s fileno() method is called, at which point the contents are written to disk and operation proceeds as with TemporaryFile().",
EDIT: The example usage you asked for could look like this:
>>> with TemporaryFile() as f:
f.write('abcdefg')
f.seek(0) # go back to the beginning of the file
print(f.read())
abcdefg
You should use something from the tempfile module. I think that it has everything you need.
I would add that Django has a built-in NamedTemporaryFile functionality in django.core.files.temp which is recommended for Windows users over using the tempfile module. This is because the Django version utilizes the O_TEMPORARY flag in Windows which prevents the file from being re-opened without the same flag being provided as explained in the code base here.
Using this would look something like:
from django.core.files.temp import NamedTemporaryFile
temp_file = NamedTemporaryFile(delete=True)
Here is a nice little tutorial about it and working with in-memory files, credit to Mayank Jain.
I just added some important changes: convert str to bytes and a command call to show how external programs can access the file when a path is given.
import os
from tempfile import NamedTemporaryFile
from subprocess import call
with NamedTemporaryFile(mode='w+b') as temp:
# Encode your text in order to write bytes
temp.write('abcdefg'.encode())
# put file buffer to offset=0
temp.seek(0)
# use the temp file
cmd = "cat "+ str(temp.name)
print(os.system(cmd))

Categories

Resources