【问题标题】:Using tempfile to create pdf/xls documents in flask使用 tempfile 在烧瓶中创建 pdf/xls 文档
【发布时间】:2015-10-02 04:31:02
【问题描述】:

我想问是否可以将 PDF/XLS 文档创建为临时文件。我这样做是为了之后使用烧瓶发送它们。对于 pdf/xls 文件的创建,我分别使用 reportlabxlsxwriter 包。当我使用他们的方法保存文档时,我收到“Python 临时文件权限被拒绝”错误。当我尝试使用 tempfile 方法关闭时,文件已损坏。有什么办法可以克服这个吗?还是有其他合适的解决方案?

编辑:

一些代码sn-ps:

import xlswriter
import tempfile
from flask import after_this_request


@app.route('/some_url', method=['POST'])
def create_doc_function():
    @after_this_request
    def cleanup(response):
        temp.close()
        return response

    temp = tempfile.TemporaryFile()
    book = xlsxwriter.Workbook(temp.name)
    # some actions here ...
    book.close()  # raises "Python temporaty file permission denied" error.
                  # If missed, Excel book is gonna be corrupted, 
                  # i.e. blank, which make sense
    return send_file(temp, as_attachment=True, 
                     attachment_filename='my_document_name.xls')

pdf 文件的类似故事。

【问题讨论】:

  • 你能发布一个你到目前为止的代码示例吗?
  • @matthewatabet,当然。检查更新的帖子。
  • 谢谢!我在下面使用持久临时文件的答案应该可以解决问题。

标签: python excel pdf flask temporary-files


【解决方案1】:

使用tempfile.mkstemp(),它将在磁盘上创建一个标准临时文件,该文件将持续存在直到被删除:

import tempfile
import os

handle, filepath = tempfile.mkstemp()
f = os.fdopen(handle)  # convert raw handle to file object
...

编辑 tempfile.TemporaryFile() 将在关闭后立即销毁,这就是您上面的代码失败的原因。

【讨论】:

  • 谢谢,这是一个很好的起点。我在这里找到了更多:logilab.org/blogentry/17873
  • 或使用 tempfile.NamedTemporaryFile()
【解决方案2】:

您可以通过上下文管理器(或 atexit 模块)使用和删除 NamedTemporaryFile。它可能会为您完成肮脏的工作。
示例 1:

import os
from tempfile import NamedTemporaryFile

# define class, because everyone loves objects
class FileHandler():

    def __init__(self):
        '''
        Let's create temporary file in constructor
        Notice that there is no param (delete=True is not necessary) 
        '''
        self.file = NamedTemporaryFile()

    # write something funny into file...or do whatever you need
    def write_into(self, btext):
        self.file.write(btext)

    def __enter__(self):
        '''
        Define simple but mandatory __enter__ function - context manager will require it.
        Just return the instance, nothing more is requested.
        '''
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        '''
        Also define mandatory __exit__ method which is called at the end.
        NamedTemporaryFile is deleted as soon as is closed (function checks it before and after close())
        '''
        print('Calling __exit__:')
        print(f'File exists = {os.path.exists(self.file.name)}')
        self.file.close()
        print(f'File exists = {os.path.exists(self.file.name)}')


# use context mamager 'with' to create new instance and do something
with FileHandler() as fh:
    fh.write_into(b'Hi happy developer!')

print(f'\nIn this point {fh.file.name} does not exist (exists = {os.path.exists(fh.file.name)})')

输出:

Calling __exit__:
File exists = True
File exists = False

In this point D:\users\fll2cj\AppData\Local\Temp\tmpyv37sp58 does not exist (exists = False)

或者您可以使用 atexit 模块,该模块在程序 (cmd) 退出时调用定义的函数。
示例 2:

import os, atexit
from tempfile import NamedTemporaryFile

class FileHandler():

    def __init__(self):
        self.file = NamedTemporaryFile()
        # register function called when quit
        atexit.register(self._cleanup)

    def write_into(self, btext):
        self.file.write(btext)

    def _cleanup(self):
        # because self.file has been created without delete=False, closing the file causes its deletion 
        self.file.close()

# create new instance and do whatever you need
fh = FileHandler()
fh.write_into(b'Hi happy developer!')
# now the file still exists, but when program quits, _cleanup() is called and file closed and automaticaly deleted.

【讨论】:

    猜你喜欢
    • 2020-07-19
    • 2019-04-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-04
    相关资源
    最近更新 更多