在Windows上打印到NamedTemporaryFile

时间:2017-11-30 14:37:05

标签: python django python-3.x subprocess temporary-files

原始问题 - MCVE

以下脚本应使用chrome headless,打印到pdf(我正在运行Windows 10和python 3.6):

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 个答案:

答案 0 :(得分:3)

我会一次又一次地回答而不是评论,但很明显我无法测试。

问题主要是强制引用双引号和& 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)

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

答案 1 :(得分:1)

事实证明,子进程没有正常运行的原因是,当python在windows中创建NamedTemporaryFile时,它会使用FILE_SHARE_DELETE标记来阻止任何其他进程访问它,除非它也有此标记。有关此here的更多讨论。

幸运的是,Django有自己的NamedTemporaryFile,它可以部分地解决这个问题,并且在这方面做得非常好。