如何从 Python Pyramid 提供临时文件 [英] How can I serve temporary files from Python Pyramid
问题描述
目前,我只是提供这样的文件:
Currently, I'm just serving files like this:
# view callable
def export(request):
response = Response(content_type='application/csv')
# use datetime in filename to avoid collisions
f = open('/temp/XML_Export_%s.xml' % datetime.now(), 'r')
# this is where I usually put stuff in the file
response.app_iter = f
response.headers['Content-Disposition'] = ("attachment; filename=Export.xml")
return response
这样做的问题是我无法在响应返回后关闭或删除文件.该文件变得孤立.我可以想到一些解决这个问题的hacky方法,但我希望在某个地方有一个标准的方法.任何帮助都会很棒.
The problem with this is that I can't close or, even better, delete the file after the response has been returned. The file gets orphaned. I can think of some hacky ways around this, but I'm hoping there's a standard way out there somewhere. Any help would be awesome.
推荐答案
您不想将文件指针设置为 app_iter
.这将导致 WSGI 服务器逐行读取文件(与 for line in file
相同),这通常不是控制文件上传的最有效方法(想象每行一个字符).Pyramid 支持的文件服务方式是通过 pyramid.response.FileResponse
.您可以通过传递文件对象来创建其中之一.
You do not want to set a file pointer as the app_iter
. This will cause the WSGI server to read the file line by line (same as for line in file
), which is typically not the most efficient way to control a file upload (imagine one character per line). Pyramid's supported way of serving files is via pyramid.response.FileResponse
. You can create one of these by passing a file object.
response = FileResponse('/some/path/to/a/file.txt')
response.headers['Content-Disposition'] = ...
另一种选择是将文件指针传递给 app_iter
,但将其包装在 pyramid.response.FileIter
对象中,该对象将使用合理的块大小以避免仅读取一行一行的文件.
Another option is to pass a file pointer to app_iter
but wrap it in the pyramid.response.FileIter
object, which will use a sane block size to avoid just reading the file line by line.
WSGI 规范严格要求包含 close
方法的响应迭代器将在响应结束时被调用.因此设置 response.app_iter = open(...)
不应该导致任何内存泄漏.FileResponse
和 FileIter
都支持 close
方法,因此会按预期清理.
The WSGI specification has strict requirements that response iterators which contain a close
method will be invoked at the end of the response. Thus setting response.app_iter = open(...)
should not cause any memory leaks. Both FileResponse
and FileIter
also support a close
method and will thus be cleaned up as expected.
作为对这个答案的一个小更新,我想我会解释为什么 FileResponse
采用文件路径而不是文件指针.WSGI 协议为服务器提供了一个可选的能力,通过 environ['wsgi.file_wrapper']
提供一种优化机制来服务静态文件.FileResponse
如果您的 WSGI 服务器提供了该支持,将自动处理此问题.考虑到这一点,您会发现将数据保存到 ramdisk 上的 tmpfile 并为 FileResponse
提供完整路径,而不是尝试将文件指针传递给 FileIter
.
As a minor update to this answer I thought I'd explain why FileResponse
takes a file path and not a file pointer. The WSGI protocol provides servers an optional ability to provide an optimized mechanism for serving static files via environ['wsgi.file_wrapper']
. FileResponse
will automatically handle this if your WSGI server has provided that support. With this in mind, you find it to be a win to save your data to a tmpfile on a ramdisk and providing the FileResponse
with the full path, instead of trying to pass a file pointer to FileIter
.
这篇关于如何从 Python Pyramid 提供临时文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!