Libre/Open Office предоставляют возможность работы с офисом через UNO API. Для того, чтобы можно было обратиться к офису необходимо запустить его в режиме прослушивания.
Например:
soffice --accept="socket,host=localhost,port=2002;urp;"
Данный подход вполне логичен и понятен с точки зрения разработчиков офиса, но несет ряд неудобств. В частности, нужно самостоятельно запускать Libre/Open Office в режиме прослушивания. Лично мне не понятно, почему разработчики поленились и не предоставили функции запуска офиса. Ну да ладно, было бы все сделано, не нужны были бы программисты. Посему будем решать задачу своими силами.
Самый простой способ решить данную задачу — поместить строку запуска офиса в скриптовый файл. В нем запускать сперва офис, а потом свое приложение. Но что если это, например, библиотека и нет возможности обратиться к ней через скриптовый файл. К тому же нужно не просто дождаться запуска офиса, но еще и дождаться пока он будет в режиме прослушивания. В общем этот подход годится лишь для тестовых задач, не более.
Я остановился на следующей реализации:
1. Форк процесса, который запускает офис в режиме прослушивания.
2. С определенной периодичностью пытаться обращаться к офису, пока попытка не окажется успешной.
3. Если через определенное время попытка подключения к офису не будет успешной, то генерировать исключение com.sun.star.connection.NoConnectException.
# -*- coding: utf-8 -*- import os import subprocess import sys import time import uno NoConnectException = uno.getClass( "com.sun.star.connection.NoConnectException") ############################################################################### def init_office(): """ Test Libre/Open Office to be launched in the listening mode """ connection_string = "uno:socket,host=localhost,port=2002;urp;\ StarOffice.ComponentContext" oLocal = uno.getComponentContext() oResolver = \ oLocal.ServiceManager.createInstanceWithContext( "com.sun.star.bridge.UnoUrlResolver", oLocal) if oResolver: oContext = oResolver.resolve(connection_string) oDesktop = oContext.ServiceManager.\ createInstanceWithContext("com.sun.star.frame.Desktop", oContext) ############################################################################### def start_office(timeout=30, attempt_period=0.1, office='soffice --accept="socket,host=localhost,port=2002;urp;"'): """ Starts Libre/Open Office with a listening socket. @type timeout: int @param timeout: Timeout for starting Libre/Open Office in seconds @type attempt_period: int @param attempt_period: Timeout between attempts in seconds @type office: string @param office: Libre/Open Office startup string """ ########################################################################### def start_office_instance(office): """ Starts Libre/Open Office with a listening socket. @type office: string @param office: Libre/Open Office startup string """ # Fork to execute Office if os.fork(): return # Start OpenOffice.org and report any errors that occur. try: retcode = subprocess.call(office, shell=True) if retcode < 0: print (sys.stderr, "Office was terminated by signal", -retcode) elif retcode > 0: print (sys.stderr, "Office returned", retcode) except OSError as e: print (sys.stderr, "Execution failed:", e) # Terminate this process when Office has closed. raise SystemExit() ########################################################################### waiting = False try: init_office() except NoConnectException as e: waiting = True start_office_instance(office) if waiting: steps = int(timeout/attempt_period) exception = None for i in range(steps + 1): try: init_office() break except NoConnectException as e: exception = e time.sleep(attempt_period) else: if exception: raise NoConnectException(exception) else: raise NoConnectException() ############################################################################### start_office()
Данный пример будет пытаться запустить Libre/Open Office с периодичностью 0.1 секунда на протяжении 30 секунд.
В качестве теста на наличие запущенного в режиме прослушивания офиса используется функция init_office(). Вместо нее может быть использована любая другая из Вашей библиотеки.
Ранее, в статье "PyOOCalc — Библиотека для генерации отчетов, счетов Libre/Open Office Calc на Python", я описал как проще работать с Libre/OpenOffice для определенной категории задач. Но библиотека PyOOCalc на имела возможности автоматического запуска офиса в режиме прослушивания, и вышеприведенный код можно переписать следующим образом.
Вместо функции init_office() можно написать:
import pyoocalc pyoocalc.Document()
Это так же может быть любая другая библиотека. Необходимо вызывать метод, который будет пытаться подключиться к Libre/Open Office.
Так же я добавил возможность автоматического запуска офиса в библиотеку PyOOCalc.
Пример использования:
import pyoocalc doc = pyoocalc.Document(autostart=True) doc.new_document()
ссылка на оригинал статьи http://habrahabr.ru/post/274775/
Добавить комментарий