Автоматический запуск Libre/OpenOffice в режиме прослушивания из Python

от автора

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/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *