Creating an .odt document using python

Creating a macro - Writing a Script - Using the API (OpenOffice Basic, Python, BeanShell, JavaScript)
Post Reply
tolliob
Posts: 13
Joined: Wed Jul 08, 2015 3:56 pm

Creating an .odt document using python

Post by tolliob »

Hello everyboby,

I'm trying to create an .odt document just using python. But, I'm completely stuck for the moment, and this main goal seems to be still a long way to go...

I'm using a mac os x 10.9.5 computer, and my AOO version is the 4.1.1

Let me explain what I have done.

First of all, I've opened a terminal to launch OpenOffice, with the following:

Code: Select all

$ cd ../../Applications/OpenOffice.app/Contents/MacOS/
$ ./soffice.bin -headless -nofirststartwizard -accept="uno:socket,host=localhost,port=8100;urp;StarOffice.ServiceManager"
I have to confess that I've found this on the web and do not really understand what the second line is doing... Probably, it's because I do not know what the file soffice.bin contains... For me, it opens a socket in order to communicate with OpenOffice. Am I write? If you can explain me precisely this, I would be wonderful actually!

Secondly, I open an other terminal, go in the same folder than in the first terminal, then launch python, import the uno package and declare a class whose goal is to create OpenOffice easily. Here is the code:

Code: Select all

$ cd ../../Applications/OpenOffice.app/Contents/MacOS/
$ python
>>> import uno
>>> class UnoClient:
...       def __init__(self):
...           localContext = uno.getComponentContext()
...           resolver = localContext.ServiceManager.createInstanceWithContext("com.sun.star.bridge.UnoUrlResolver", localContext)
...           self.smgr = resolver.resolve("uno:socket,host=localhost,port=8100;urp;StarOffice.ServiceManager")
...    def create_document(self, app):
...        remoteContext = self.smgr.getPropertyValue("DefaultContext")
...        desktop = self.smgr.createInstanceWithContext( "com.sun.star.frame.Desktop",remoteContext)
...        url = "private:factory/{0}".format(app)
...        return desktop.loadComponentFromURL(url,"_blank", 0, () )
Once again, I don't understand all the detail of this code and would not have been able to code it myself...I think that it's like a client, the other terminal being the server. The line "self.smgr = ..." should be here to try to "connect" to the "server socket", or something like that...

Finally, I'm trying to declare a UnoClient objet by

Code: Select all

unoClient = UnoClient()
Of course, it would have been too simple if this code would have be correct... Python answer me

Code: Select all

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 6, in __init__
__main__.NoConnectException: Connector : couldn't connect to socket (Undefined error: 0)
Does anyone has some ideas, advices or references to understand what I am doing?

Thanks very much for all your answer,

Tolliob
Tolliob, with OpenOffice 4.1.1, on Mac os x 10.9.5
User avatar
Villeroy
Volunteer
Posts: 31269
Joined: Mon Oct 08, 2007 1:35 am
Location: Germany

Re: Creating an .odt document using python

Post by Villeroy »

Please, edit this topic's initial post and add "[Solved]" to the subject line if your problem has been solved.
Ubuntu 18.04 with LibreOffice 6.0, latest OpenOffice and LibreOffice
tolliob
Posts: 13
Joined: Wed Jul 08, 2015 3:56 pm

Re: Creating an .odt document using python

Post by tolliob »

Villeroy, thank you very much for this link.

Of course, I've tried to understand it, but I haven't... And it does not explain anything about my traceback issue...

Anyway, for anyone who will see this topic a moment after, you have to read it (or to try to read it...)
Tolliob, with OpenOffice 4.1.1, on Mac os x 10.9.5
User avatar
Villeroy
Volunteer
Posts: 31269
Joined: Mon Oct 08, 2007 1:35 am
Location: Germany

Re: Creating an .odt document using python

Post by Villeroy »

I get the same socket error on Linux with simplified Python code. No, I don't understand anything of that context and resolver shit. In fact, I gave up writing extensions and external scripts. This is for professionals only who have a deeper understanding of the underlying application.
On rare occasions I write some very simplistic macro stuff where the context and the runtime is a given matter of fact.

The simple, strictly procedural code I've tried is this:

Code: Select all

import uno
localContext = uno.getComponentContext()
resolver = localContext.ServiceManager.createInstanceWithContext(
    "com.sun.star.bridge.UnoUrlResolver", localContext)
ctx = resolver.resolve("uno:socket,host=localhost,port=8100;urp;StarOffice.ComponentContext")
dtp = ctx.ServiceManager.createInstanceWithContext("com.sun.star.frame.Desktop",ctx)
doc = dtp.loadComponentFromURL("private:factory/swriter", "_blank", 0, ())
and it fails at resolver.resolve(...) with error "__main__.NoConnectException: Connector : couldn't connect to socket (Success)" while my soffice process eats up half of my CPU.
Please, edit this topic's initial post and add "[Solved]" to the subject line if your problem has been solved.
Ubuntu 18.04 with LibreOffice 6.0, latest OpenOffice and LibreOffice
User avatar
karolus
Volunteer
Posts: 1158
Joined: Sat Jul 02, 2011 9:47 am

Re: Creating an .odt document using python

Post by karolus »

Here is my `Develop-setup` from a interactive IPython notebook session:

Code: Select all

from subprocess import Popen

officepath = '/opt/libreoffice4.4/program/soffice'
#replace with your path and try with `soffice` instead `soffice.bin` directly
calc = '--calc'
pipe = "--accept=pipe,name=abraxas;urp;StarOffice.Servicemanager"
# simple pipe-mode with free choosable Name, here: `abraxas`

# starts soffice as server
Popen([officepath,  calc, pipe]) 
Now the "client-code":

Code: Select all

import uno
from pythonscript import ScriptContext

local = uno.getComponentContext()
resolver = local.ServiceManager.createInstance("com.sun.star.bridge.UnoUrlResolver")

client = resolver.resolve("uno:pipe,"
                           "name=abraxas;"
                           "urp;"
                           "StarOffice.ComponentContext")
createUnoService = client.ServiceManager.createInstance
(desktop,
 file_access,
 pathsubstitution,
 mri,
 pipe,
 textout,
 textin,
 contentfactory,
 core,
 intro) = map(   createUnoService,
            ("com.sun.star.frame.Desktop",
             "com.sun.star.ucb.SimpleFileAccess",
             "com.sun.star.util.PathSubstitution",
             "mytools.Mri",
             "com.sun.star.io.Pipe",
             "com.sun.star.io.TextOutputStream",
             "com.sun.star.io.TextInputStream",
             "com.sun.star.frame.TransientDocumentsDocumentContentFactory",
             "com.sun.star.reflection.CoreReflection",
             "com.sun.star.beans.Introspection")
             )
# most of mapping in the last statement is not essential, but show how it works.

XSCRIPTCONTEXT = ScriptContext(client, None, None)
# for the purpose having `XSCRIPTCONTEXT` similar to the Namespace from "inside soffice"
 
AOO4, Libreoffice 6.1 on Rasbian OS (on ARM)
Libreoffice 7.4 on Debian 12 (Bookworm) (on RaspberryPI4)
Libreoffice 7.6 flatpak on Debian 12 (Bookworm) (on RaspberryPI4)
User avatar
Villeroy
Volunteer
Posts: 31269
Joined: Mon Oct 08, 2007 1:35 am
Location: Germany

Re: Creating an .odt document using python

Post by Villeroy »

So the hidden secret is that sockets are no longer supported and we've got to use pipes instead?
Please, edit this topic's initial post and add "[Solved]" to the subject line if your problem has been solved.
Ubuntu 18.04 with LibreOffice 6.0, latest OpenOffice and LibreOffice
tolliob
Posts: 13
Joined: Wed Jul 08, 2015 3:56 pm

Re: Creating an .odt document using python

Post by tolliob »

Many thanks Karolus and Villeroy,

Using some pipe instead of socket seems to be OK. Unfortunately, I'm not able to connect the client to the server with you code Karolus...
The server is OK, but the client blows up at the line

Code: Select all

client = resolver.resolve("uno:pipe,"
...                            "name=abraxas;"
...                            "urp;"
...                            "StarOffice.ComponentContext")

Code: Select all

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
__main__.NoConnectException: Connector : couldn't connect to pipe abraxas(10)
Do you have some ideas explaining this???
Tolliob, with OpenOffice 4.1.1, on Mac os x 10.9.5
User avatar
karolus
Volunteer
Posts: 1158
Joined: Sat Jul 02, 2011 9:47 am

Re: Creating an .odt document using python

Post by karolus »

villeroy wrote:So the hidden secret is that sockets are no longer supported and we've got to use pipes instead?
No, As far I know, both socket and pipe are supported, but pipe is by definition restrictet on connections to|from same machine.
in socket you have the additional property to set `host` to other targets than 'localhost'
AOO4, Libreoffice 6.1 on Rasbian OS (on ARM)
Libreoffice 7.4 on Debian 12 (Bookworm) (on RaspberryPI4)
Libreoffice 7.6 flatpak on Debian 12 (Bookworm) (on RaspberryPI4)
tolliob
Posts: 13
Joined: Wed Jul 08, 2015 3:56 pm

Re: Creating an .odt document using python

Post by tolliob »

Maybe I have one ideas explaining my traceback issue.

In the client, I just launch my os Python, even if I'm localized inside my OpenOffice distribution (/Applications/OpenOffice.app/Contents/MacOS/)

It seems as if I should have a python distribution related to OpenOffice, no? But I have not.

All the file I obtain after these instructions

Code: Select all

*cd /Applications/OpenOffice.app/Contents
$ls -R | grep python
are

Code: Select all

pythonloader.py
pythonloader.pyc
pythonloader.uno.dylib
pythonloader.unorc
pythonscript.py
pythonscript.pyc
python
./share/Scripts/python:
pythonSamples
./share/Scripts/python/pythonSamples
But
python
is not an executable, it's just a folder where are some available python script (HelloWorld.py, for instance)...

Is it normal? Is it the correct way to launch my os python installation?

Many thanks in advance,
Tolliob, with OpenOffice 4.1.1, on Mac os x 10.9.5
User avatar
karolus
Volunteer
Posts: 1158
Joined: Sat Jul 02, 2011 9:47 am

Re: Creating an .odt document using python

Post by karolus »

Hallo
Do you have some ideas explaining this???
Sorry, I cannot because I'm working on Linux and mostly with Libreoffice.
Im not familiar with details on MacOs with OpenOffice.


First, did you use the very same Python-Interpreter as used by your AOO-version ??

Did the first (the server part) Code-example run without Error-messages, and does Office start ?
please post your whole actual code for this and not only parts of it


If Office starts and no Errors appears run the client-part, and post your whole actual code and the whole traceback.
AOO4, Libreoffice 6.1 on Rasbian OS (on ARM)
Libreoffice 7.4 on Debian 12 (Bookworm) (on RaspberryPI4)
Libreoffice 7.6 flatpak on Debian 12 (Bookworm) (on RaspberryPI4)
tolliob
Posts: 13
Joined: Wed Jul 08, 2015 3:56 pm

Re: Creating an .odt document using python

Post by tolliob »

First, did you use the very same Python-Interpreter as used by your AOO-version ??
No... I'm not sure... I do not know how to use the interpreter used by my AOO version...
Did the first (the server part) Code-example run without Error-messages, and does Office start ?
please post your whole actual code for this and not only parts of it
Yes, it is! It opens a window where normally we choose the type of the document we want (calc, writer, and so on)
Here is the code I have used:

Code: Select all

$ cd ~
$ ../../Applications/OpenOffice.app/Contents/MacOS/soffice.bin
$ python
>>> from subprocess import Popen
>>> officepath = '../../Applications/OpenOffice.app/Contents/MacOS/soffice.bin'
>>> calc = '--calc'
>>> pipe = "--accept=pipe,name=abraxas;urp;StarOffice.Servicemanager"
>>> Popen([officepath,  calc, pipe]) 
<subprocess.Popen object at 0x104264090>
>>> 
My code for the client part is exactly yours:

Code: Select all

$ cd ../../Applications/OpenOffice.app/Contents/MacOS/
$ python
>>> import uno
>>> from pythonscript import ScriptContext
>>> local = uno.getComponentContext()
>>> resolver = local.ServiceManager.createInstance("com.sun.star.bridge.UnoUrlResolver")
>>> client = resolver.resolve("uno:pipe,"
...                            "name=abraxas;"
...                            "urp;"
...                            "StarOffice.ComponentContext")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
__main__.NoConnectException: Connector : couldn't connect to pipe abraxas(10)
The problem is probably to find how to launch the python interpreter from the AOO-distribution on Mac os X...
Tolliob, with OpenOffice 4.1.1, on Mac os x 10.9.5
User avatar
Villeroy
Volunteer
Posts: 31269
Joined: Mon Oct 08, 2007 1:35 am
Location: Germany

Re: Creating an .odt document using python

Post by Villeroy »

Thank you for the code, karolus. It works fine and I can use it literally with the "abraxas" pipe and with a socket on port 2002. And my snippet from 09 09 Jul 2015, 01:02 connects to your server as well on port 2002.

Port 8100 fails again although it is not used by any other process. But what do I know about net sockets? Not enough, I'm afraid.
Please, edit this topic's initial post and add "[Solved]" to the subject line if your problem has been solved.
Ubuntu 18.04 with LibreOffice 6.0, latest OpenOffice and LibreOffice
User avatar
Villeroy
Volunteer
Posts: 31269
Joined: Mon Oct 08, 2007 1:35 am
Location: Germany

Re: Creating an .odt document using python

Post by Villeroy »

tolliob wrote:The problem is probably to find how to launch the python interpreter from the AOO-distribution on Mac os X...
Here I start the script with

Code: Select all

/opt/libreoffice4.4/program/python karolus_client.py
/opt/libreoffice4.4 is the directory where libreoffice is installed.
 Edit: and no, I can't do the same with OpenOffice. The server script starts OpenOffice but I can not connect the client script (same error as always. 
Please, edit this topic's initial post and add "[Solved]" to the subject line if your problem has been solved.
Ubuntu 18.04 with LibreOffice 6.0, latest OpenOffice and LibreOffice
User avatar
karolus
Volunteer
Posts: 1158
Joined: Sat Jul 02, 2011 9:47 am

Re: Creating an .odt document using python

Post by karolus »

tolliob wrote:
First, did you use the very same Python-Interpreter as used by your AOO-version ??
No... I'm not sure... I do not know how to use the interpreter used by my AOO version...
Did the first (the server part) Code-example run without Error-messages, and does Office start ?
please post your whole actual code for this and not only parts of it
Yes, it is! It opens a window where normally we choose the type of the document we want (calc, writer, and so on)
Here is the code I have used:

Code: Select all

$ cd ~
$ ../../Applications/OpenOffice.app/Contents/MacOS/soffice.bin
$ python
>>> from subprocess import Popen
>>> officepath = '../../Applications/OpenOffice.app/Contents/MacOS/soffice.bin'
>>> calc = '--calc'
>>> pipe = "--accept=pipe,name=abraxas;urp;StarOffice.Servicemanager"
>>> Popen([officepath,  calc, pipe]) 
<subprocess.Popen object at 0x104264090>
>>> 
hum, that should start directly with a new Calc-document ??
please try without .bin at the end of officepath
tolliob wrote: My code for the client part is exactly yours:

Code: Select all

$ cd ../../Applications/OpenOffice.app/Contents/MacOS/
$ python
>>> import uno
>>> from pythonscript import ScriptContext
>>> local = uno.getComponentContext()
>>> resolver = local.ServiceManager.createInstance("com.sun.star.bridge.UnoUrlResolver")
>>> client = resolver.resolve("uno:pipe,"
...                            "name=abraxas;"
...                            "urp;"
...                            "StarOffice.ComponentContext")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
__main__.NoConnectException: Connector : couldn't connect to pipe abraxas(10)
The problem is probably to find how to launch the python interpreter from the AOO-distribution on Mac os X...
What tells you `which python` from Commandline?
and what shows a new writer-document if you execute via soffice-GUI:

Code: Select all

import sys

def interpreter_path():
    doc = XSCRIPTCONTEXT.getDocument()
    doc.Text.String = sys.executable
???
AOO4, Libreoffice 6.1 on Rasbian OS (on ARM)
Libreoffice 7.4 on Debian 12 (Bookworm) (on RaspberryPI4)
Libreoffice 7.6 flatpak on Debian 12 (Bookworm) (on RaspberryPI4)
User avatar
karolus
Volunteer
Posts: 1158
Joined: Sat Jul 02, 2011 9:47 am

Re: Creating an .odt document using python

Post by karolus »

Ok, I probable found some differences:
the server Part for Apache-OpenOffice( recognize the single dashes in front of optional Arguments***)

Code: Select all

/opt/openoffice4/program/python
Python 2.7.6 (default, Jul 28 2014, 18:07:00) 
[GCC 4.1.2 20080704 (Red Hat 4.1.2-54)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from subprocess import Popen
>>> officepath = '/opt/openoffice4/program/soffice'
>>> calc = '-calc'  # not '--calc' as for Libreoffice
>>> pipe = '-accept=pipe,name=apache;urp;StarOffice.Servicemanager' # here also only single -dash 
>>> # realize the new name `apache`
>>> Popen([officepath, calc, pipe])
***in opposite to common Agreement to use double slashes -- as prefix of LongOptional Arguments

the Client-part is unchanged:

Code: Select all

>>> import uno
>>> from pythonscript import ScriptContext
>>> local = uno.getComponentContext()
>>> resolver = local.ServiceManager.createInstance("com.sun.star.bridge.UnoUrlResolver")
>>> client = resolver.resolve("uno:pipe,name=apache;urp;StarOffice.ComponentContext")
AOO4, Libreoffice 6.1 on Rasbian OS (on ARM)
Libreoffice 7.4 on Debian 12 (Bookworm) (on RaspberryPI4)
Libreoffice 7.6 flatpak on Debian 12 (Bookworm) (on RaspberryPI4)
User avatar
Villeroy
Volunteer
Posts: 31269
Joined: Mon Oct 08, 2007 1:35 am
Location: Germany

Re: Creating an .odt document using python

Post by Villeroy »

Indeed, those tiny dashes where LibreOffice follows some conventions make the difference. And the port number. And the python runtime of the respective office suite.
Please, edit this topic's initial post and add "[Solved]" to the subject line if your problem has been solved.
Ubuntu 18.04 with LibreOffice 6.0, latest OpenOffice and LibreOffice
Post Reply