Запустить процесс openoffice с python для использования с pyuno с использованием подпроцесса
Я использую эту команду для запуска 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
Скрипт Python для запуска процесса openoffice:
command = [
'soffice',
'--accept=socket,host=localhost,port=8100;urp;StarOffice.Service',
'--headless',
'--nofirststartwizard'
]
subprocess.Popen(command, shell=True)
По какой-то причине команда netstat ничего не выдает, когда я пытаюсь запустить openoffice с этим скриптом python. процесс есть, но он не принимает соединения. Что я делаю неправильно?
3 ответа
Из документации:
В Unix с shell=True оболочкой по умолчанию является /bin/sh. Если args является строкой, строка определяет команду для выполнения через оболочку.
Если args является последовательностью, первый элемент задает командную строку, и любые дополнительные элементы будут рассматриваться как дополнительные аргументы самой оболочки.
Здесь вы должны просто удалить shell=True
передать аргументы soffice
вместо передачи аргументов в оболочку:
subprocess.Popen(command)
Использовать shell=True
вам нужно собрать все аргументы в одну команду (аргументы, конечно, должны быть экранированы):
subprocess.Popen(command.join(' '), shell=True)
Я столкнулся с почти идентичной проблемой, и это сводило меня с ума, пока я не понял это. К счастью, исправить это просто.
Есть два способа исправить звонок Popen
в оригинальном вопросе:
- либо вывезти
, shell=True
или добавить цитаты ко второму элементу в
command
как это:'--accept="socket,host=localhost,port=8100;urp;StarOffice.Service"'
Проблема в том, что оболочка неправильно разбирает аргументы без этих кавычек, поэтому либо не используйте оболочку (лучший способ), либо указывайте один аргумент, как указано выше. Я говорю, что лучше не использовать оболочку, потому что тогда просто отключить soffice, используя .terminate()
метод объекта, возвращаемого Popen
, В противном случае вам нужно использовать библиотеку, такую как psutil, чтобы найти все ваши дочерние процессы и уничтожить их самостоятельно, потому что, как указал Скотт П., завершение оболочки не остановит soffice.
Скотт П: причина вашего первого звонка Popen
не работает, потому что у вас есть кавычки во втором элементе, но вы не используете оболочку. Оболочка удаляет кавычки, когда анализирует командную строку, но, поскольку вы ее не используете, они остаются, и тогда soffice не интерпретирует аргумент так, как вы ожидаете. И именно поэтому ваш второй звонок Popen
работает
Другая иллюстрация этой проблемы здесь: Ошибка вызова LibreOffice из Python
Выполняется следующее, но 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 успешно создан и что аргументы выглядят правильно и что у него есть pid. Я не уверен, почему это происходит. Кто-нибудь может объяснить это?
В конце концов я получил это работать следующим образом:
soffice = subprocess.Popen(' '.join([
'/usr/bin/soffice',
'--accept="pipe,name=hello;urp;"',
'--norestore',
'--nologo',
'--nodefault',
'--headless',
]), shell=True)
Обратите внимание, однако, что закрытие пид с soffice.kill()
оставляет позади некоторые процессы.
Смотрите вопрос здесь относительно этой проблемы: OpenOffice Forum Question 29873