【问题标题】:python cgi html pdfpython cgi html pdf
【发布时间】:2017-04-19 20:47:05
【问题描述】:

我正在编写一个 python CGI 脚本,它逐行解析 csv 文件并使用 jinja2 创建一个 HTML 表。理想情况下,每个单独的 HTML 实例(每行一个)都将保存为 PDF 报告。

我进行了很多搜索,但我一直无法找到使用 python 从 HTML 转到 PDF 的好方法。是否可以将 CGI 渲染为 PDF?你会推荐什么方法来完成这项任务?

【问题讨论】:

    标签: python html pdf cgi


    【解决方案1】:

    如果您进行了大量搜索,那么我相信您已经看到了将 html 转换为 pdf 的所有非常复杂的选项:ReportLab、weasyprint、pdfkit 等:如本文所述:How to convert webpage into pdf using Python

    然而,我实际上只是在上个月研究了 Jinja2 -> HTML -> PDF 工作流程,所以希望我的解决方案能对您有所帮助。我发现下载 wkhtmltopdf(一个用 C 编写的小型命令行程序 - 它非常棒)并从 subprocess 使用它是到目前为止完成这项任务的最简单方法。我的示例如下:

    import os
    import jinja2
    import subprocess
    
    def render(template_path, context):
        # Context = jinja context dictionary 
        path, filename = os.path.split(template_path)
        return jinja2.Environment(loader=jinja2.FileSystemLoader(path or './')
                                 ).get_template(filename
                                               ).render(context)
    
    def create_pdf(custom_data, template_path, out_dir, context, keep_html=False):
        # Custom data = the part of my workflow that won't matter to you
        report_name = os.path.join(out_dir, custom_data + "_report")
        html_name = report_name + ".html"
        pdf_name = report_name + ".pdf"
    
        def write_html():
            with open(html_name, 'w') as f:
                html = render(template_path, context)
                f.write(html)
        write_html()
    
        args = '"C:\\Program Files\\wkhtmltopdf\\bin\\wkhtmltopdf.exe" --zoom 0.75 -B 0 -L 0 -R 0 -T 0 {} {}'.format(html_name, pdf_name)
        child = subprocess.Popen(args, shell=True, stdout=subprocess.PIPE)
        # Wait for the sub-process to terminate (communicate) then find out the
        # status code
        output, errors = child.communicate()
        if child.returncode or errors:
            # Change this to a log message
            print "ERROR: PDF conversion failed. Subprocess exit status {}".format(
            child.returncode)
        if not keep_html:
            # Try block only to avoid raising an error if you've already moved
            # or deleted the html
            try:
                os.remove(html_name)
            except OSError:
                pass
    

    大部分代码在jinja2subprocess 的文档中都有很好的解释,所以我不会在这里费力地复习。 wkhtmltopdf 中的 arg 标志转换为 Zoom = 75% 和 0 宽度边距(-B、-L 等是底部、左侧等的简写)。 wkhtmltopdf documention也不错。

    已编辑:render 函数的功劳归于Matthias Eisen。用法:

    假设一个模板位于 /some/path/my_tpl.html,包含:

    你好 {{ 名字 }} {{ 姓氏 }}!

    context = {
        'firstname': 'John',
        'lastname': 'Doe'
    }
    result = render('/some/path/my_tpl.html', context)
    
    print(result)
    

    你好约翰·多伊!

    【讨论】:

    • 感谢@HFBrowning。我有一个问题。你如何传递上下文?我在 jinja2 文档中找不到这种渲染技术。我习惯于渲染:\n print("Content-Type: text/html\n\n") print(template.render(ID = ACCESSION_ID, DATE = date.today()) 所以我不确定如果您要渲染多个内容,您是如何渲染“上下文”变量的。如果您可以将我指向 html = render(template_path, context) 的文档,那就太好了!
    • 已编辑以显示该功能的起源和使用 - 好问题。有很多代码 sn-ps 展示了使用 jinja2 的截然不同的策略
    • 如果不清楚(不确定您对 Python 的熟悉程度),上下文就是字典。我的工作流程包括将许多 (~50) 元素保存到该字典中,例如,context["DATE"] = datetime.datetime.now()
    猜你喜欢
    • 1970-01-01
    • 2011-03-11
    • 1970-01-01
    • 2017-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-02
    • 2022-12-27
    相关资源
    最近更新 更多