使用 python 启动 openoffice 进程以使用子进程与 pyuno 一起使用

Posted

技术标签:

【中文标题】使用 python 启动 openoffice 进程以使用子进程与 pyuno 一起使用【英文标题】:start openoffice process with python to use with pyuno using subprocess 【发布时间】:2013-12-26 16:11:19 【问题描述】:

我用这个命令来启动openoffice:

soffice --accept="socket,host=localhost,port=8100;urp;StarOffice.Service" --headless --nofirststartwizard

以下命令将确保 openoffice 接受端口 8100 上的连接:

netstat -nap | grep office

输出:

tcp        0      0 127.0.0.1:8100          0.0.0.0:* LISTEN     2467/soffice.bin 

启动openoffice进程的Python脚本:

command = [
    'soffice',
    '--accept=socket,host=localhost,port=8100;urp;StarOffice.Service',
    '--headless',
    '--nofirststartwizard'
]
subprocess.Popen(command, shell=True)

由于某种原因,当我尝试使用这个 python 脚本启动 openoffice 时,netstat 命令什么也没输出。该过程在那里,但它不接受连接。 我做错了什么?

【问题讨论】:

命令看起来不一样:Popen 命令使用单破折号而不是双破折号(-headless vs --headless)并添加了-nologo 选项。首先尝试运行完全相同的命令。 已经试过了。看起来 popen args 正在被解雇 您应该使用实际使用的代码更新问题。您是否在与 soffice 命令完全相同的环境中运行 Python 脚本(即没有 cron、supervisor、init 脚本...)? 是的,更新了。我不确定环境。我只是打开一个 python 控制台并输入它 确实,popen args 被传递给 shell。请参阅下面的答案。 【参考方案1】:

来自documentation:

在 shell=True 的 Unix 上,shell 默认为 /bin/sh。如果 args 是字符串,则该字符串指定要通过 shell 执行的命令。

如果 args 是一个序列,第一项指定命令字符串,任何附加项将被视为 shell 本身的附加参数。

在这里,您应该只删除 shell=True 以将参数传递给 soffice,而不是将参数传递给 shell:

subprocess.Popen(command)

要使用shell=True,您需要将所有参数构建到一个命令中(当然需要对参数进行转义):

subprocess.Popen(command.join(' '), shell=True)

【讨论】:

但请注意,如果使用shell=False,第一个参数可能需要到可执行文件的完整路径。【参考方案2】:

以下执行,但与管道的 UNO 连接不起作用:

soffice = subprocess.Popen([ '/usr/bin/soffice', '--accept="pipe,name=hello;urp;"', '--norestore', '--nologo', '--nodefault', '--headless', ])

如果我从终端管道连接执行此操作就可以了:

/usr/bin/soffice --accept="pipe,name=hello;urp;" --norestore --nologo --nodefault --headless

我可以从我的调试器中看到 subprocess.Popen 已成功创建,并且 args 看起来正确并且它有一个 pid。我不确定为什么会这样。谁能解释一下?

我最终让它按如下方式工作:

soffice = subprocess.Popen(' '.join([ '/usr/bin/soffice', '--accept="pipe,name=hello;urp;"', '--norestore', '--nologo', '--nodefault', '--headless', ]), shell=True)

但请注意,使用 soffice.kill() 关闭 pid 会留下一些进程。

在此处查看有关此问题的问题: OpenOffice Forum Question 29873

【讨论】:

【参考方案3】:

我遇到了一个几乎相同的问题,它让我发疯,直到我弄清楚了。幸运的是,修复很简单。

有两种方法可以修复原始问题中对Popen 的调用:

    要么取出, shell=True

    或像这样在command 中的第二个项目中添加引号:

    '--accept="socket,host=localhost,port=8100;urp;StarOffice.Service"'

问题在于,如果没有这些引号,shell 无法正确解析 args,因此要么不使用 shell(更好的方法),要么像上面那样引用一个参数。我说不使用 shell 是更好的方法,因为这样可以很简单地使用 Popen 返回的对象的 .terminate() 方法关闭 soffice。否则,您需要使用 psutil 之类的库来查找所有子进程并自己杀死它们,因为正如 Scott P. 指出的那样,终止 shell 并不会停止 soffice。

Scott P:您第一次致电Popen 不起作用的原因是您在第二项中使用了引号,但没有使用贝壳。 shell 在解析命令行时会删除引号,但是因为您没有使用它,所以它们仍然存在,然后 soffice 不会按照您期望的方式解释参数。同样,这就是为什么您第二次致电 Popen确实 有效。

这个问题的另一个例子在这里:Error calling LibreOffice from Python

【讨论】:

以上是关于使用 python 启动 openoffice 进程以使用子进程与 pyuno 一起使用的主要内容,如果未能解决你的问题,请参考以下文章

从后面的代码启动 OpenOffice 作为服务不起作用

openoffice在linux下无法启动服务

为啥我的启动 OpenOffice 服务的调用在开发中有效,但在服务器上无效?

我如何在 Windows 7 中启动服务 openOffice,我有这条线命令,但我不知道如何使用它

excel 和 openoffice calc 的宏

保证金 Openoffice python