📜 ⬆️ ⬇️

Automatically launching Libre / OpenOffice in listening mode from Python

Libre / Open Office provides the ability to work with the office through the UNO API. In order to be able to contact the office, you must start it in listening mode.

For example:
soffice --accept="socket,host=localhost,port=2002;urp;" 

This approach is quite logical and understandable from the point of view of office developers, but it carries a number of inconveniences. In particular, you need to run Libre / Open Office yourself in listening mode. Personally, I don’t understand why the developers were too lazy and didn’t provide the office launch functions. Well, okay, everything would be done, no programmers would be needed. Therefore, we will solve the problem on our own.

The easiest way to solve this problem is to place the office launch line in a script file. In it, run the office first, and then your application. But what if it is, for example, a library and there is no possibility to access it through a script file. In addition, you need not just wait for the launch of the office, but also wait until it is in listening mode. In general, this approach is suitable only for test problems, no more.
I stopped at the following implementation:
1. The fork of the process that starts the office in listening mode.
2. At certain intervals, try to contact the office until the attempt is successful.
3. If after a certain time the attempt to connect to the office is not successful, then generate an exception 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() 

')
This example will try to launch Libre / Open Office at intervals of 0.1 seconds for 30 seconds.
The function init_office () is used as a test for the presence of an office running in listening mode. Any other from your library can be used instead.

Earlier, in the article " PyOOCalc - Library for generating reports, Libre / Open Office Calc accounts in Python ", I described how easier it is to work with Libre / OpenOffice for a specific category of tasks. But the PyOOCalc library did not have the ability to automatically start the office in listening mode, and the above code can be rewritten as follows.
Instead of the init_office () function, you can write:
 import pyoocalc pyoocalc.Document() 

It can also be any other library. You must call the method that will try to connect to the libre / open office.

I also added the ability to automatically start an office in the PyOOCalc library.
Usage example:
 import pyoocalc doc = pyoocalc.Document(autostart=True) doc.new_document() 

Source: https://habr.com/ru/post/274775/


All Articles