You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

PHP调用Python脚本无法生成PDF文件的技术求助

解决PHP调用Python脚本转换Docx到PDF无输出的问题

我来帮你梳理下这个问题的核心:你的Python脚本单独执行时能正常完成Docx转PDF,但通过PHP调用时,脚本执行到打开文档就卡住了,没有完成保存操作。结合你的环境和测试情况,我整理了几个可能的解决方向:

1. Office COM对象在服务环境下的交互限制

Windows的Office COM组件(比如Word)本质上是为桌面交互设计的,即使你用指定用户身份启动Apache服务,也可能因为桌面交互权限缺失Office安全策略拦截导致SaveAs操作静默失败。

解决步骤:

  • 开启Apache服务的桌面交互权限:
    1. 打开Windows服务管理器,找到Apache服务右键选择「属性」
    2. 切换到「登录」选项卡,勾选「允许服务与桌面交互」
    3. 重启Apache服务
  • 调整Word的安全设置(测试用,后续可恢复安全配置):
    1. 打开Word,依次点击「文件」→「选项」→「信任中心」→「信任中心设置」
    2. 关闭「受保护视图」下的所有选项
    3. 在「宏设置」中选择「启用所有宏」

2. 给Python脚本添加错误捕获,排查具体问题

你的Python脚本没有异常处理逻辑,一旦SaveAs出错会直接崩溃,但PHP调用时无法看到错误详情。建议添加异常捕获,输出错误信息:

修改后的Python脚本:

import sys
import os
import win32com.client
import traceback

wdFormatPDF = 17
in_file = 'C:\\Users\\fake_user\\OneDrive\\Stuff\\f1.docx'
out_file = 'C:\\Users\\fake_user\\OneDrive\\Stuff\\f3.pdf'

try:
    print('BEGIN<br>\n')
    word = win32com.client.Dispatch('Word.Application')
    word.Visible = False
    # 禁用Word的警告弹窗,避免阻塞脚本
    word.DisplayAlerts = 0
    doc = word.Documents.Open(in_file)
    print('\nOpened Docx\n<br>')
    print(in_file)
    doc.SaveAs(out_file, FileFormat=wdFormatPDF)
    print('\nSaved\n<br>')
    doc.Close()
    word.Quit()
    print('DONE\n')
except Exception as e:
    print(f'Error occurred: {str(e)}<br>')
    print(traceback.format_exc().replace('\n', '<br>'))
    # 确保Word进程强制退出,避免残留
    if 'word' in locals():
        word.Quit()

3. 修复PHP调用时的环境变量与路径问题

Apache的运行环境可能没有加载Python的完整环境变量,或者找不到Word组件。建议:

  • 在PHP中使用Python的绝对路径调用脚本:
exec('C:\\Python38\\python.exe "C:\\Users\\fake_user\\OneDrive\\Stuff\\dp.py"');
  • 捕获Python的错误输出,方便排查:
exec('python dp.py 2>&1', $output, $return_var);
echo '<pre>';
var_dump($output);
var_dump($return_var);
echo '</pre>';

2>&1会把错误流重定向到标准输出,你就能看到脚本执行的具体错误了。

4. 规避OneDrive同步的文件锁定问题

OneDrive的实时同步可能会锁定原文件或目标文件,导致Word无法完成保存。建议先将文件复制到本地非OneDrive目录转换,完成后再复制回去:

修改Python脚本的路径处理逻辑:

import shutil

# 临时目录(非OneDrive路径)
temp_dir = 'C:\\Temp\\docx_convert'
os.makedirs(temp_dir, exist_ok=True)
temp_in = os.path.join(temp_dir, 'f1.docx')
temp_out = os.path.join(temp_dir, 'f3.pdf')

# 复制原文件到临时目录
shutil.copy(in_file, temp_in)

# 使用临时文件执行转换
doc = word.Documents.Open(temp_in)
doc.SaveAs(temp_out, FileFormat=wdFormatPDF)

# 复制转换后的PDF回OneDrive目录
shutil.copy(temp_out, out_file)

替代方案:使用非Office工具转换(更稳定)

如果以上方法都无法解决,推荐使用不需要Office的转换工具,比如LibreOffice,这类工具更适合服务器环境:

  1. 安装与系统位数匹配的LibreOffice
  2. 在PHP中直接调用转换命令:
exec('"C:\\Program Files\\LibreOffice\\program\\soffice.exe" --headless --convert-to pdf "C:\\Users\\fake_user\\OneDrive\\Stuff\\f1.docx" --outdir "C:\\Users\\fake_user\\OneDrive\\Stuff\\"');

内容的提问来源于stack exchange,提问作者Rafał Szczechowski

火山引擎 最新活动