在 Windows 上打印到 NamedTemporaryFile
Printing to NamedTemporaryFile on Windows
原始问题 - MCVE
下面的脚本应该使用 chrome headless,打印成 pdf(我是 运行ning 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)
在 stack-overflow 上搜索并尝试了一些东西后,我仍然无法让原始脚本运行。有任何想法吗?
部分问题是我似乎无法从子进程调用中获得任何有意义的调试。任何帮助也将不胜感激。
我会尝试回答而不是一次又一次地发表评论,但显然我无法对此进行测试。
问题主要是双引号 & 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)
我不满意,但它有很好的工作机会。
事实证明,子进程 运行 不正确的原因是,当 python 在 windows 中创建一个 NamedTemporaryFile 时,它使用 FILE_SHARE_DELETE 标签阻止任何其他进程访问它,除非它也有这个标签。关于这个here的讨论比较多。
幸运的是,Django 自带 NamedTemporaryFile 可以部分解决这个问题,并且在这些方面做得很好。
原始问题 - MCVE
下面的脚本应该使用 chrome headless,打印成 pdf(我是 运行ning 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)
在 stack-overflow 上搜索并尝试了一些东西后,我仍然无法让原始脚本运行。有任何想法吗?
部分问题是我似乎无法从子进程调用中获得任何有意义的调试。任何帮助也将不胜感激。
我会尝试回答而不是一次又一次地发表评论,但显然我无法对此进行测试。
问题主要是双引号 & 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)
我不满意,但它有很好的工作机会。
事实证明,子进程 运行 不正确的原因是,当 python 在 windows 中创建一个 NamedTemporaryFile 时,它使用 FILE_SHARE_DELETE 标签阻止任何其他进程访问它,除非它也有这个标签。关于这个here的讨论比较多。
幸运的是,Django 自带 NamedTemporaryFile 可以部分解决这个问题,并且在这些方面做得很好。