前の関連記事:LibreOffice5(44)createInstanceWithArgumentsAndContext()でインスタンス化
拡張機能内のprint()は出力されない
拡張機能内のPythonコードはUNOコンポーネント内にあるので外部のPythonコードとはUNOIDL越しでしかやりとりできません。
GitHub - p--q/UNOIDLtype at developで実験します。
PyUnoComponent.pyのexcept節のprint()が出力されていなかったためになかなかエラーがわかりませんでした。
PyUnoComponent.pyの8行目のcomponent.create()の引数を削ってエラーを出してみます。
Traceback (most recent call last): File "/home/pq/.config/libreoffice/4/user/Scripts/python/UNOIDLtype/UNOIDLtype/TestPytUnoComponent.py" , line 24 , in <module> s = pycomp.stringTypeArg( "文字列を渡しました。" ) AttributeError: 'NoneType' object has no attribute 'stringTypeArg' |
本来は拡張機能内のcomponent.pyで返しているUNOIDLでインスタンス化すべきクラスの__init()__に渡す引数が足りないので、エラーがでている行の一つ前の23行目でPyUNOオブジェクトがNoneで返っているのが原因です。
24行目で指摘されているエラーではPyUNOオブジェクトがインスタンス化されていない原因がわかりません。
except節のprint()が実行されずにtry文が返って害になっているのでtry文自体消してしまいます。
Traceback (most recent call last): File "/home/pq/.config/libreoffice/4/user/Scripts/python/UNOIDLtype/UNOIDLtype/TestPytUnoComponent.py" , line 23 , in <module> pycomp = smgr.createInstanceWithContext( "UnoInsp" , ctx) # サービス名か実装名でインスタンス化。 uno.com.sun.star.uno.RuntimeException: < class 'TypeError' >: create() missing 1 required positional argument: 'ctx' , traceback follows / home / pq / .config / libreoffice / 4 / user / uno_packages / cache / uno_packages / lu262275y7lhm.tmp_ / UNOIDLtype.oxt / PyUnoComponent.py: 7 in function create() [ return component.create(IMPLE_NAME, ctx, * args)] / opt / libreoffice5. 2 / program / unohelper.py: 292 in function createInstanceWithContext() [ return self .clazz( context )] |
uno.com.sun.star.uno.RuntimeExceptionが発生して、create()の引数が足りないと言ってくれます。
拡張機能内のファイルを展開したキャッシュのpyファイルのエラーがでている部分までわかります。
/opt/libreoffice5.2/program/msgbox.pyを使ってメッセージボックスに表示させる
print()に代わってCalc(2)課題2:選択範囲の行列番号をメッセージボックスに表示で使ったcreateMessageBox()を使ってメッセージボックスを表示させようと思いましたが、TestPytUnoComponent.pyからはフレームを取得できませんでした。
LibreOfficeのウィンドウを表示させていないので、デスクトップからフレームを取得できないということのようです。
代わりに/opt/libreoffice5.2/program/msgbox.pyにあるMsbBoxクラスを使うとうまくいきました。
1 2 3 4 5 6 7 8 9 10 11 |
def create(ctx, * args): try : import component return component.create(IMPLE_NAME, ctx, * args) # この引数を少なくしてエラーがでるようにしている。 except Exception as e: s = str (e) from msgbox import MsgBox myBox = MsgBox(ctx) myBox.addButton( "OK" ) myBox.renderFromBoxSize( len (s) * 3 ) # メッセージボックスの幅を文字列の長さから算出。 myBox.show(s, 0 , "Error" ) |
msgbox.pyを実行すると長い文字列は折り返して表示されますが、どうすると折り返されるのかわからず、文字列ははみ出すので文字列の長さから幅を適当に算出しています。
これがprint(e)で出力されていた内容です。
これよりtry文を削ってスタックトレースの表示をさせた方が得られる情報は多いですね。
createInstanceWithArgumentsAndContext()でインスタンス化している場合
上記のコードミスがあってもTestPytUnoComponent.pyの41行目のcreateInstanceWithArgumentsAndContext()でインスタンス化しているところではこのエラーがでてきません。
createInstanceWithArgumentsAndContext()で渡している引数がcreate()の3つ目の引数として渡されてしまっているからです。
引数の数はあっているのでインスタンス化は成功するのですが、component.py
の8行目のcreate(imple_name, service_name, ctx, *args)のctxにはコンポーネントコンテクストではなくて、createInstanceWithArgumentsAndContext()の引数のタプルが入ってしまいます。
ObjInspクラス内ではコンポーネントコンテクストを使っていないのでエラーはでずに、getInitArgs()メソッドで空のタプルが返ってきてエラーなく終わってしまいます。
でもcreateInstanceWithArgumentsAndContext()でインスタンス化されたオブジェクトをprint()するとterminate called after throwing an instance of 'com::sun::star::uno::RuntimeException'が返ってきてスクリプトが終わります。
print()ではobject.__str__(self)が呼び出されるので、これのエラーですね、おそらく。
どこに原因のコードがあるのかはわかりませんでした。
pyuno object (com.sun.star.uno.XInterface) 0x93eea0c {implementationName = UnoInsp, supportedServices = {com.blogspot.pq.UnoInsp}, supportedInterfaces = {com.sun.star.lang.XServiceInfo,com.blogspot.pq.XUnoInsp,com.sun.star.lang.XTypeProvider}} |
createInstanceWithArgumentsAndContext()の場合はprint()しないとエラーがあることがわからないことになります。
どこかにtry文を仕込んでおけば、エラーのある場所がわかるようにできないか考えてみましたが、わかりませんでした。
この問題はエラーをみてデバッグするのは難しいですね。
次の裸の*の文を書いていて解決法がわかりました。
UNOIDLtype/PyUnoComponent.py at 13060c17034890b49eb55ceb402298cd3525569b · p--q/UNOIDLtype
区別する引数をキーワード引数にしてしまえばキーワード引数が足りないのでちゃんとエラーがでるようになりました。
裸の *はそれ以降はキーワード専用引数のみという意味
Python Cookbook
裸の*はつまり*argsのargsのないバージョンということです。
なのでfunc(*args, *, kwarg1, kwarg2)とするとinvalid syntaxというエラーになります。
0 件のコメント:
コメントを投稿