使用 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 服务的调用在开发中有效,但在服务器上无效?