*Python-UNO 概要 [#fe118d8d] OpenOffice.org と Python 関連概要 #contents **概要 [#obd8ed6e] Python-UNO (Py-UNO) は Python-UNO ブリッジを介して python から OpenOffice.org API を利用する OOo-Python 間の仲立ちをしてくれます。単純に Python から OOo を操作できるとみなしてかまいません。 使い方は自分で調べるという人のためにいくつかページを挙げておきます。 -Python-UNO bridge --http://udk.openoffice.org/python/python-bridge.html -Python (OpenOffice.org Wiki) --http://wiki.services.openoffice.org/wiki/Extensions_development_python -OOoPython --[[OOoPython]] -Script locations --http://udk.openoffice.org/python/scriptingframework/index.html //-Python 2.5 へのアップデート関連 issue //-http://www.openoffice.org/issues/show_bug.cgi?id=71327 Python-UNO ブリッジは C++ で書かれたコードなので高速に動作します。また、スクリプトの実行速度は OOo Basic と比較できないほど早いです (C++、Java などとは比較しません)。 OpenOffice.org の Windows パッケージではわざわざ取り除かなければ Python が一緒にインストールされます。Python 2.3.4 の実行環境がついてきます。OOo 3.1 から Python 2.6.1 になりました。Python 標準モジュールのうち利用できないものがいくつかあります。 また、Linux などの環境では Py-UNO パッケージをインストールしておく必要があります。 ***Py-UNO でできること [#w59468b2] Py-UNO では次の三種類のことができます。 -[[Scripting Framework スクリプトのマクロとして動作>../Macro]] -[[UNO コンポーネント作成>../UNOComponent]] -[[Py-UNO bridge を介して外部 Python から OOo オートメーション>../Automation]] マクロとしてというのは、OOo Basic で書いたマクロのように実行できるということです。また、UNO コンポーネント作成は新しいサービスを実装できます。Py-UNO bridge を介してというのは、OOo と関係の無い Python スクリプトからドキュメントを作成するために OOo を利用できることになります。 //***その他 [#w79e3cf5] //OOo Con 2007 のスライドを見ていると Python を利用した ConfigurationManager //-http://marketing.openoffice.org/ooocon2007/programme/thursday__170.pdf //この中で Why Python? "It's cooler than StarBasic." や "Hight-level data types like dictionaries etc." とあります。 *** 日本語 [#l90aeb7b] OOo に付属している Python は 2.3.5 のため日本語文字コードの取り扱いがデフォルトではうまくいきません。 OOo に付属している Python は 2.3.5 のため日本語文字コードの取り扱いがデフォルトではうまくいきません。OOo 3.1 以降では Python 2.6.1 なので問題ありません。 日本語などの文字列をソースに入れる場合には次のようにエンコードを utf8 に設定します。 #code(python){{ #! # -*- coding: utf_8 -*- }} また、shift_jis や euc_jp などの文字コードを指定して decode や encode もできません。OOo に付属のPython が 2.4 系以上にアップデートされればデフォルトで利用できるようになります。 また、OOo 2.4 系では各 Linux ディストリビューションが独自にビルドしている OOo ではシステムの Python を利用していて Python 2.4, 2.5 系を使用している場合もあります。Ubuntu 8.0.2 (?) では Python 2.5.2、Momonga Linux 5 beta1 では Python 2.5.1 ? などが利用されています。 **各種取得 [#kaa762da] 各種いろいろなものを Py-Uno で利用する方法。OOo Basic で行う場合と対比させてみます。 uno や unohelper は OOo の program ディレクトリに置かれています。利用に際して import しておきます。 import uno import unohelper ***XSCRIPTCONTEXT [#x2a62fa2] Scripting Framework のスクリプトで使われる XSCRIPTCONTEXT グローバル変数は Py-UNO でも利用できます。これを使うのはマクロとして実行するときです。 現在のドキュメントを取得します。 document = XSCRIPTCONTEXT.getDocument() StarDesktop.getCurrentComponent() 'OOo Basic デスクトップ com.sun.star.frame.Desktop サービスを取得します。 desktop = XSCRIPTCONTEXT.getDesktop() StarDesktop 'OOo Basic CreateUnoService("com.sun.star.frame.Desktop") 'another コンポーネントコンテキストを取得します。 ctx = XSCRIPTCONTEXT.getComponentContext() GetDefaultContext() 'OOo Basic ***サービスマネージャ [#ff55347d] MultiServiceFactory を利用するには次のようにします。ctx はコンポーネントコンテキストです。 smgr = ctx.ServiceManager oServiceManager = GetProcessServiceManager() ' OOo Basic ***サービス [#b528d707] サービスマネージャから createInstanceWithContext メソッドで作成します。 desktop = smgr.createInstanceWithContext("com.sun.star.frame.Desktop",ctx) oDesktop = CreateUnoService("com.sun.star.frame.Desktop") 'OOo Basic ***struct [#maceb9a8] struct の作成 uno.createUnoStruct("com.sun.star.awt.Size") または、 from com.sun.star.beans import PropertyValue porp = PropertyValue() () が必要です。 OOo Basic では CreateUnoStruct("com.sun.star.awt.Size") や Dim ... New As ... タイプ名が []com.sun.star.beans.PropertyValue などのシークエンスが必要な時には一つずつ作成します。 from com.sun.star.beans import PropertyValue args = [] a1 = PropertyValue() a1.Name = "InputStream" a1.Value = ioin a2 = PropertyValue() a2.Name = "FilterName" a2.Value = "calc8" args.append(a1) args.append(a2) desktop.loadComponentFromURL("private:stream", "_blank",0, tuple(args)) Basic では簡単に Dim args(1) As New com.sun.star.beans.PropertyValue ***enum [#o8363580] enum は import します。 from com.sun.star.awt.WindowClass import TOP as UNO_WC_TOP また、次のようにも出来ます。 uno.Enum("com.sun.star.awt.WindowClass","TOP") OOo Basic では nEnum = com.sun.star.awt.WindowClass.TOP With ステートメントも利用できます。 ***Constants [#bb6344c5] enum 同様に import します。 from com.sun.star.beans.MethodConcept import ALL as UNO_MC_ALL また、 uno.getConstantByName("com.sun.star.beans.MethodConcept.ALL") OOo Basic は enum と同様。 ***配列 [#a0a5e59e] 配列というより UNO の sequence 型。API 関数から戻される sequence は Py-UNO ではタプルになります。また、メソッドの引数として与えるときもタプルで与えます。tuple、list などで必要に応じて変換したりしなければいけません。 edit_model.setPropertyValues( ("MultiLine",), (True,) ) oEdit_model.setPropertyValues( _ Array("MultiLine"), Array(true) ) ' OOo Basic ***boolean [#s48fefad] True または False OOo Basic だと大文字と小文字に依存しませんが、python だと syntax error になります。 ***string [#we8b94e2] 文字列は python unicode。8 bit を与えたときは自動的に変換されます。 ***Char [#re0fd7f0] 文字というか char は uno.py で定義されている Char クラスのインスタンスです。実際の文字を取得するには value attribute を取得します。Char は普段は見かけませんがキーリスナーやマウスリスナーを利用しているとと時々遭遇します。 ***ByteSequence [#ce24419e] Python ではバイトは文字として扱うが、UNO 側から渡されたバイトシークエンスは uno.py で定義された ByteSequence クラスのインスタンスになっている。値を取得するには value attribute を参照する。詳細は uno.py 参照。 ***インターフェース [#w6f75959] サービスを実装したり、リスナーを利用するときにはインターフェースを継承したクラスを作成する必要があります。インターフェースはインポートします。 import unohelper from com.sun.star.awt import XActionListener class aclistener(unohelper.Base,XActionListener): def __init__(self,ctx): self.ctx = ctx return def actionPerformed(self,ev): pass def disposing(self,ev): pass ***URL <-> System FilePath [#g8257503] システムパスから URL unohelper.systemPathToFileUrl( systemPath ) URL からシステムパス unohelper.fileUrlToSystemPath( url ) ***引数と返り値 [#d0d6671f] API メソッドの引数に [out] のものが時々ありますが、Py-UNO では元々の返り値を加えたタプルで返ります。 Basic では aURL = CreateUnoStruct("com.sun.star.util.URL") aURL.Complete = ".uno:Paste" CreateUnoService("com.sun.star.util.URLTransformer")._ parseStrict(aURL) 'parseStrict の返り値は void で、最初の引数が [inout] Py-UNO だと aURL = uno.createUnoStruct("com.sun.star.util.URL") aURL.Complete = ".uno:Paste" transformer = smgr.createInstanceWithContext( "com.sun.star.util.URLTransformer",ctx) dummy,aURL = transformer.parseStrict(aURL) # 元々の返り値,out のある引数の値 # ここでは dummy は void (Python では None) 詳細は上記リンク参照。 ***ダイアログ [#k28f0023] com.sun.star.awt.DialogProvider サービスを利用してダイアログエディタで作成したダイアログが利用できます。ボタンなどのリスナーは UNO コンポーネントを設定していないのであればリスナーを設定する必要があります。 def dialog_test(): ctx = XSCRIPTCONTEXT.getComponentContext() smgr = ctx.ServiceManager dialogprovider = smgr.createInstanceWithContext( "com.sun.star.awt.DialogProvider",ctx) url = "vnd.sun.star.script:Standard.Dialog1?location=application" dialog = dialogprovider.createDialog(url) dialog.execute() ダイアログを指定する URL はダイアログライブラリの URI でなくローカルファイルでも可能です。たとえば、file:///home/huga/Desktop/dlg.xdl などとします。拡張機能でダイアログを利用するがダイアログライブラリとしてインストールしたくないときに利用できます。 ***実行するスクリプト一覧に表示する関数名 [#h14f3d66] OOo で python スクリプトをマクロとして実行するときは関数定義を実行する形になります。一覧に表示したい名前を制限するには次のようにします。 g_exportedScripts = calc_thread, タプルで表示したい関数名を指定します。g_exportedScripts の変数名を変えてはいけません。 ***import [#r82840b6] 2.4 から Python の標準ライブラリ以外の独自のファイルインポートが容易になりました。 実行するスクリプトファイルと同じディレクトリに pythonpath ディレクトリを作成してインポートしたいファイルを配置します。 test.py (実行するスクリプトファイル) --pythonpath/inc.py (インポートするファイル) import inc ディレクトリの代わりに pythonpath.zip ファイルを作成してインポートしたいファイルを入れておくこともできます。 Framework script でなく Py-UNO コンポーネントのときにも同様にインポートできます。 2.4 で修正済み該当 issue [[i76281>http://www.openoffice.org/issues/show_bug.cgi?id=76281]] import したファイルは拡張機能パッケージがインストールされるときにバイトコードにコンパイルされます。 ***メッセージボックス [#vda709dc] 簡単なメッセージボックスは 2.3 以降では次のように簡単に表示できます。 #code(python){{ import uno def test10(): message(XSCRIPTCONTEXT.getDesktop(),"message","title") def message(desktop,msg="",title=""): frame = desktop.getCurrentFrame() win = frame.getContainerWindow() toolkit = win.getToolkit() rect = uno.createUnoStruct("com.sun.star.awt.Rectangle") msgbox = toolkit.createMessageBox( win,rect,"messbox",1,title,msg) msgbox.execute() }} **例外 [#r5a8fe63] 基本的に Python の try、except、else、raise を使う。UNO での例外は com.sun.star.uno.Exception をすべての親クラスとなっているが、Py-UNO では Python の Exception も継承されているので同じように取り扱えます。 また、利用する例外は struct と同じように import しておきます。例は以下参照。 http://udk.openoffice.org/python/python-bridge.html#exception 例外を raise で送出できます。 #code(python){{ import uno import unohelper from com.sun.star.lang import XServiceInfo from com.sun.star.container import XIndexContainer from com.sun.star.uno.TypeClass import STRING as TC_STRING from com.sun.star.lang import \ IndexOutOfBoundsException as UNO_IndexOutOfBoundsException, \ IllegalArgumentException as UNO_IllegalArgumentException, \ IndexOutOfBoundsException as UNO_IndexOutOfBoundsException IMPLE_NAME = u'mytools.service.Test1' class new_service(unohelper.Base, XIndexContainer, XServiceInfo): """This service implements container that retains strings with their indexes.""" def __init__(self): print "initialize..." self.cont = [] def getImplementationName(self): return IMPLE_NAME def supportsService(self, name): return name == IMPLE_NAME def getSupportedServiceNames(self): return (IMPLE_NAME,) def insertByIndex(self, i, item): if isinstance(item, basestring): if 0 <= i <= len(self.cont): self.cont.insert(i, item) else: uno_e = UNO_IndexOutOfBoundsException() uno_e.Message = u'Index out of bounds. %s' % len(self.cont) raise uno_e else: uno_e = UNO_IllegalArgumentException() uno_e.ArgumentPosition = 1 raise uno_e def removeByIndex(self, i): if 0 <= i < len(self.cont): del self.cont[i] else: uno_e = UNO_IndexOutOfBoundsException() uno_e.Message = u'Index out of bounds. %s' % len(self.cont) raise uno_e def replaceByIndex(self, i, item): if isinstance(item, basestring): if 0 <= i < len(self.cont): self.cont[i] = item else: uno_e = UNO_IndexOutOfBoundsException() uno_e.Message = u'Index out of bounds. %s' % len(self.cont) raise uno_e else: uno_e = UNO_IllegalArgumentException() uno_e.ArgumentPosition = 1 raise uno_e def getCount(self): return len(self.cont) def getByIndex(self, i): try: return self.cont.get(i) except ValueError,e: uno_e = UNO_IndexOutOfBoundsException() uno_e.Message = u'Index out of bounds. %s' % len(self.cont) raise uno_e def getElementType(self): return uno.Type(u'string', TC_STRING) def hasElements(self): if len(self.cont) > 0: return True return False }} **標準出力 [#rf334ae9] Windows 環境では標準出力が利用できません。一方、Linux などの環境ではシェルから OpenOffice.org を起動すれば標準出力が利用できます。 sys.stdout を適当な I/O オブジェクトと置き換えると Windows 環境でもログを取らずにリアルタイムで標準出力が参照できます。[[OOoPython/mytools/sstdout]] |