mittels LibreOffice ein Python-Script aufzurufen und Parameter zu übergeben/zurückgeben

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Stephan_2021
User
Beiträge: 52
Registriert: Sonntag 11. Juli 2021, 09:43

Hallo,

ich versuche in LibreOffice mittels StarBasic ein Python-Script aufzurufen und Parameter zu übergeben und im Python-Script dannn (testweise) an LibreOffice/Starbasic zurückzugeben.

In LibreOffice (LO) lautet der (funktionierende) Aufruf eines Python-Scripts z.B. wie folgt:

Code: Alles auswählen

oScriptProvider = ThisComponent.getScriptProvider()
oScript = oScriptProvider.getScript("vnd.sun.star.script:jms1.py$resultx?language=Python&location=user")
erg = oScript.invoke(array(), array(), array())
Msgbox erg
Wenn das Python-Script (jms1.py) den Inhalt hat:

Code: Alles auswählen

import sys

def resultx( ):
 return("nur ein Test")
dann wird in der MsgBox von LO-Basic auch die korrekte Rückgabe "nur ein Test" (natürlich ohne "") angezeigt.

Wenn ich das Python-Script nun ändere zu:

Code: Alles auswählen

import sys

def resultx( ):
 return(sys.argv)
bekomme ich von LO/Basic die Fehlermeldung:

BASIC-Laufzeitfehler.
Es ist eine Ausnahme aufgetreten
Type: com.sun.star.uno.RuntimeException
Message: Error during invoking function resultx in module file:///E:/LO_603/LibreOfficePortable/Data/settings/user/Scripts/python/jms1.py (<class 'AttributeError'>: module 'sys' has no attribute 'argv'
File "E:\LO_603\LibreOfficePortable\App\libreoffice\program\pythonscript.py", line 875, in invoke
ret = self.func( *args )
File "E:\LO_603\LibreOfficePortable\Data\settings\user\Scripts\python\jms1.py", line 10, in resultx
return(sys.argv)
).


OBWOHL dieses Python-Script bei Ausführung mittels Windows-Kommandozeile, zum richtigen Ergebnis führt, d.h. der Pfad/Name des Scripts (Entsprechend sys.argv(0)) werden zurückgegeben.

Code: Alles auswählen

import sys

print(sys.argv)


Was mache ich falsch?


Die interne Python-Version in LO ist 3.5 und ich habe mich überzeugt das "import sys" für dieses(*) Python ausgeführt wird (falls das in Zweifel stehen könnte). Betriebssystem ist Windows 7

(*)
damit meine ich das LO selbst Python mitbringt, ees aber auf demselben System auch weitere Python-Versionen geben kann



Wie eingangs geschrieben, geht es mir eigentlich um Parameterübergabe, aber mein Wissenstand ist das übergebene Parameter über sys.argv ausgelesen werden und sys.argv(0) immer den Pfad+Namen des aktuellen Scripts enthält und deshalb wollte ich zunächst Letzteres testen, hänge aber bereits da fest.


Gruß
Stephan
Benutzeravatar
__blackjack__
User
Beiträge: 13122
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Stephan_2021: Du rufst ja das Skript gar nicht als Programm auf, sondern direkt die Funktion darin, also wird es deswegen wohl auch kein `sys.argv` geben. Du müsstest schauen wie Du der Funktion die Du aufrufst, Argumente mitgeben kannst. Kurzer Blick über die LibreOffice-Dokumentation lässt vermuten, dass es beim `invoke()`-Aufruf übergeben wird.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Stephan_2021
User
Beiträge: 52
Registriert: Sonntag 11. Juli 2021, 09:43

Hallo blackjack, *,
Du rufst ja das Skript gar nicht als Programm auf, sondern direkt die Funktion darin, also wird es deswegen wohl auch kein `sys.argv` geben.
mmh ...
Du müsstest schauen wie Du der Funktion die Du aufrufst, Argumente mitgeben kannst. Kurzer Blick über die LibreOffice-Dokumentation lässt vermuten, dass es beim `invoke()`-Aufruf übergeben wird.
ja, das mit dem .invoke(...) weiß ich, nur gerade weil ein spontaner Versuch mit:

Code: Alles auswählen

erg = oScript.invoke(Array("Test"), array(), array())
zu nichts führte, war ich darauf verfallen erst einmal mit sys.argv testen zu wollen.

Ich weiß derzeitig nicht was an ".invoke(Array("Test"), array(), array())" falsch ist, muss ich weiter nachdenken.

Vielleicht hat jemand einen Tipp dazu? Die Doku zu .invoke() ist hier:
http://www.openoffice.org/api/docs/comm ... tml#invoke


Gruß
Stephan
Stephan_2021
User
Beiträge: 52
Registriert: Sonntag 11. Juli 2021, 09:43

Stephan_2021 hat geschrieben: Sonntag 11. Juli 2021, 12:24
Du rufst ja das Skript gar nicht als Programm auf, sondern direkt die Funktion darin, also wird es deswegen wohl auch kein `sys.argv` geben.
mmh ...
moment mal ... ich wollte schon in meiner Antwort, die ich hier gerade zitiere, fragen ob das hoffentlich nur für sys.argv(0) gilt, habe die FRage aber unterlassen, weil ich zunächst nur an die direkte Rückgabe der Parameter dachte und Diese nicht zwingend benötige.

A B E R ...

wenn ich das mit .invoke(...) hinbekomme, WIE verarbeite ich die übergebenen Paramter denn dann überhaupt im Python Script weiter, d.h. wie kann ich sie ansprechen?

Vielleicht ist ja das hier (Achtung StarBasic):

Code: Alles auswählen

erg = oScript.invoke(Array("Test"), array(), array())
sogar ein richtiger Aufruf und es hängt nur daran, wie ich im Python-.Script nun überhaupt an den Parameter-Wert "Test" rankomme.


Gruß
Stephan
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Laut der Dokumentation musst du auch den Funktionsnamen angeben:

bar.invoke( {"foo", "foo2", "this-is-ignored" }, aOutParamIndex, aOutParam);

ruft die Funktion foo auf. Fehlt bei dir, denn da muss ja resultx vorkommen.

Und die Argumente werden an die aufgerufene Funktion resultx so uebergeben, wie an jede andere Funktion - die muss halt Parameter nehmen, tut sie im Moment nicht.
Stephan_2021
User
Beiträge: 52
Registriert: Sonntag 11. Juli 2021, 09:43

Danke, aber im DEtail weiß ich nicht wie ich das schreiben muss.

sagen wir mein Python-Script wäre:

Code: Alles auswählen

def resultx(a):
 return str(a)
Ist das überhaupt korrekt geschrieben?

WEnn ja, wie muss ich denn dann aufrufen, aus Basic heraus? Ich verstehe es so, das im ersten Array von .invoke() der erste Parameter der Name der Funktion sein muss und danach kommen die Parameter für DIESE Funktion, also so:

Code: Alles auswählen

erg = oScript.invoke(Array("resultx", "Test"), array(), array())
das sollte imho für "erg" also "Test" zurückgeben, liefert aber die (StarBasic)-Fehlermeldung (in LO):

BASIC-Laufzeitfehler.
Es ist eine Ausnahme aufgetreten
Type: com.sun.star.uno.RuntimeException
Message: Error during invoking function resultx in module file:///E:/LO_603/LibreOfficePortable/Data/settings/user/Scripts/python/jms1.py (<class 'TypeError'>: resultx() takes 1 positional argument but 2 were given
File "E:\LO_603\LibreOfficePortable\App\libreoffice\program\pythonscript.py", line 875, in invoke
ret = self.func( *args )
).



Wahrscheinlich ist das Problem ganz banal, aber ich verstehe bisher fast nichts von Python.


Gruß
Stephan
Benutzeravatar
__blackjack__
User
Beiträge: 13122
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

In dem Array darf die Funktion nicht stehen. Die steht doch bereits in der ”URI” mit der `oScript` erstellt wird. Da gibst Du Modul- *und* Funktionsnamen an.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Stephan_2021
User
Beiträge: 52
Registriert: Sonntag 11. Juli 2021, 09:43

Hallo blackjack,

danke, das hat mir geholfen, es funktioniert jetzt wie gewünscht.


Darf ich noch Eines fragen - wenn Du schreibst:

"Da gibst Du Modul- *und* Funktionsnamen an."

Was meint dann "Modul"? Steht das synonym für "Script" oder hat das im Python-Sprachgebrauch eine tiefere Bedeutung?


Gruß
Stephan
Benutzeravatar
__blackjack__
User
Beiträge: 13122
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Stephan_2021: Du hast da kein Skript. Das könnte man ja als Programm ausführen. Ob nun alleinstehend oder im Kontext einer Anwendung, wo das von Anfang bis Ende durchläuft und damit dann das gemacht hat, was man von dem Skript will. Ein Skript würde dann in aller Regel auch Argumente via ``sys.argv`` auslesen können, denn das ist die dafür vorgesehene Schnittstelle dafür.

Du hast da aber zwei Schritte. Laden des Moduls (und einbinden der Funktion). Und Aufruf der Funkton aus dem BASIC-Programmteil heraus. Wann immer Du das dort willst und falls es mehr als eine Funktion im Modul gibt, auch in beliebiger Reihenfolge. Das ist kein Skript, sondern eine Bibliothek im allgemeinen Sprachgebrauch, oder eben Modul in Python-Lingo. Also wenn es nur ein Modul ist. Es gibt in Python auch Packages in denen mehrere Module zusammengefasst werden können — das ist allgemein gesprochen auch eine Bibliothek.

Wenn man ein Skript hat, dann ist das als Modul implementiert. Insorfern ist das in dem Fall schon Synonym, weil man dann ein Modul als Programm ausführt, statt es zu importieren und einzelne Teile davon von einem anderen Modul, oder in diesem Fall BASIC, zu verwenden.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Antworten