代码之家  ›  专栏  ›  技术社区  ›  tim-mccurrach

在Windows上打印到NamedTemporaryFile

  •  2
  • tim-mccurrach  · 技术社区  · 7 年前

    原始问题-MCVE

    import subprocess
    from tempfile import NamedTemporaryFile
    
    output = NamedTemporaryFile()
    CHROME_PATH=r'"C:\Program Files (x86)\Google\Chrome\Application\chrome"'
    
    chrome_args=[CHROME_PATH,
                 '--headless',
                 r'--print-to-pdf="{}"'.format(output.name),
                 '--disable-gpu',
                 'https://www.google.com/',]
    
    subprocess.call(chrome_args,shell=True)
    

    然而,生成的文件只是空的。

    尝试调试

    为了尝试弄清楚发生了什么,在上一节中,我将脚本改编为以下内容:

    import subprocess
    CHROME_PATH=r'"C:\Program Files (x86)\Google\Chrome\Application\chrome"'
    
    chrome_args=[CHROME_PATH,
                 '--headless',
                 r'--print-to-pdf="c:\Users\timmc\Documents\output.pdf"',
                 '--disable-gpu',
                 'https://www.google.com/',]
    
    print(r" ".join(chrome_args))  #For debuging
    
    subprocess.call(chrome_args,shell=True)
    

    在这种情况下,在预期位置没有生成文件。打印结果为:

    "C:\Program Files (x86)\Google\Chrome\Application\chrome" --headless --print-to-pdf="c:\Users\timmc\Documents\output.pdf" --disable-gpu https://www.google.com/
    

    如果我运行以下命令(创建原始字符串文字),一切都会按预期进行,并生成文件。

    subprocess.call(r'"C:\Program Files (x86)\Google\Chrome\Application\chrome" --headless --print-to-pdf="c:\Users\timmc\Documents\output.pdf" --disable-gpu https://www.google.com/', shell=True)
    

    在搜索了堆栈溢出并尝试了一些方法后,我仍然无法使用原始脚本。有什么想法吗?

    部分问题是,我似乎无法从子进程调用中获得任何有意义的调试。如果有任何帮助,我们将不胜感激。

    2 回复  |  直到 7 年前
        1
  •  3
  •   Jean-François Fabre    7 年前

    问题主要是双引号的强制; shell=True . 将引用留给 subprocess (也在 CHROME_PATH )正确地分割论点通常是有效的。我用这个技巧解决了很多问题。

    由于您的评论指出它没有,并且您找到了一种解决方法,因此我建议对该解决方法进行改进:在有效的命令行中注入输出文件名:

    subprocess.call(r'"C:\Program Files (x86)\Google\Chrome\Application\chrome" --headless --print-to-pdf="{}" --disable-gpu https://www.google.com/'.format(output.name), shell=True)
    

    我不满意,但它有很好的工作机会。

        2
  •  1
  •   tim-mccurrach    7 年前

    结果表明,子进程没有正常运行的原因是,当python在windows中创建NamedTemporaryFile时,它使用FILE\u SHARE\u DELETE标记来执行此操作,该标记阻止任何其他进程访问它,除非它也有此标记。对此还有更多讨论 here .

    幸运的是,Django自带 NamedTemporaryFile 这是为了部分解决这个问题,并且在这些方面做得很好。