LibreOffice5(83)linuxBeanでは動くのにWindows10では動かないマクロ

2017-09-11

旧ブログ

t f B! P L
どうもlinuxBeanで使うよりもWindows10で使うときの方が厳密な文法が求められるようで、linuxBeanでは動くのにWindows10では動かないマクロがあります。しかもエラーがでてこないのもあるので、デバッガにかけないと原因が追究できません。

前の関連記事:LibreOffice5(82)Javaの例:GUIをPythonにする その8


Windows10のLibreOfficeマクロをlinuxBeanでリモートデバッグする


Windows10でまた開発環境を立ち上げるのは面倒なのでlinxBeanからWindow10のマクロをリモートデバッグできるようにします。

linuxBean14.04(136)WindowsのLibreOfficeマクロをlinuxBeanでリモートデバッグするでやったことと同じことです。

VirtualBox5.1.22のゲストOSのlinuxBean14.04のEclipse4.6.2、PyDev5.6.0からホストOSのWindows10 Home 64bitのlibreOffice 5.2.4.2のマクロに接続します。

仮想マシンのネットワークはブリッジアアダプターにしています。

pydevd.pyのあるフォルダをWindows10にコピペする

linuxBean14.04(136)WindowsのLibreOfficeマクロをlinuxBeanでリモートデバッグするのときはPYTHONPATHの意味がわからなかったので、sites.pthを利用しましたが、LibreOffice5(47)拡張機能のソースをオートメーションでも実行するで意味がわかったので、PYTHONPATHを使います、、、と思ってやりかけましたが、デバッグするマクロのサブフォルダにいちいちPYTHONPATHフォルダを作成しないといけないようなのでやっぱりsites.pthを使います。

まずlinuxBeanにインストールしてあるpydevd.pyファイルがあるフォルダ(今回は/opt/eclipse4.6jee/plugins/org.python.pydev_5.6.0.201703221358/pysrc)をWindows10にコピペします。

今回はマイクロフォルダ(C:\Users\pq\AppData\Roaming\LibreOffice\4\user\Scripts\python)にコピペしました。

Windows10でデバッグするマクロもWindows10のマイマクロフォルダにコピペしておきます。

次にsites.pthファイルにpydevd.pyへのパスを登録します。

単にpydevd.pyがあるフォルダへのパスを書くだけです。

C:\Users\pq\AppData\Roaming\LibreOffice\4\user\Scripts\python\pysrc

C:\Program Files (x86)\LibreOffice 5\program\python-core-3.3.0\lib\site-packages\sites.pthをこのように書き換えました。

ちゃんとインポートできるか確認してみます。

Windows10のスタートボタンをクリック→cmdと打ち込む→コマンドプロンプトを起動。

"C:\Program Files (x86)\LibreOffice 5\program\python.exe"

これでLibreOfficeのバンドルPythonが起動します。

import pydevd

これでエラーがでてこなければちゃんとインポートされています。
Microsoft Windows [Version 10.0.15063]
(c) 2017 Microsoft Corporation. All rights reserved.

C:\Users\pq>"C:\Program Files (x86)\LibreOffice 5\program\python.exe"
Python 3.3.5 (default, Dec 20 2016, 00:04:55) [MSC v.1800 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import pydevd
warning: Debugger speedups using cython not found. Run '"C:\Program Files (x86)\LibreOffice 5\program\python-core-3.3.0\bin\python.exe" "C:\Users\pq\AppData\Roaming\LibreOffice\4\user\Scripts\python\pysrc\setup_cython.py" build_ext --inplace' to build.
>>>
warningがでてきますがこれはしなくてもデバッグできます。

exit()でPythonプロンプトを抜けます。

それぞれのOSでのマクロのあるフォルダまでのパスを確認します。

Eclipse側のマクロのパス

/home/pq/.config/libreoffice/4/user/Scripts/python/GUI/GUI/src/imagecontrol

Pythonプロセス側のマクロのパス

C:\Users\pq\AppData\Roaming\LibreOffice\4\user\Scripts\python

これらを確認したらC:\Users\pq\AppData\Roaming\LibreOffice\4\user\Scripts\python\pysrcにあるpydevd_file_utils.pyをメモ帳などで開きます。
#example:
#PATHS_FROM_ECLIPSE_TO_PYTHON = [
#  (r'd:\temp\temp_workspace_2\test_python\src\yyy\yyy',
#   r'd:\temp\temp_workspace_2\test_python\src\hhh\xxx')
#]
この下にそれぞれのマクロへのパスが記入した以下のコードを追加します。
PATHS_FROM_ECLIPSE_TO_PYTHON = [
  (r'/home/pq/.config/libreoffice/4/user/Scripts/python/GUI/GUI/src/imagecontrol',
   r'C:\Users\pq\AppData\Roaming\LibreOffice\4\user\Scripts\python')
]
あとはlinuxBean14.04(136)WindowsのLibreOfficeマクロをlinuxBeanでリモートデバッグするの「Eclipseを動かしているlinuxBeanのIPの確認とファイアフォールの設定」以下の設定をします。

ファイアフォールの設定はポート番号だけの指定なので一度したらもうする必要はないはずです。

IPアドレスはDHCPを使っていると変化している可能性があるので調べておきます。

192.168.10.105

ifconfigででてくるinetアドレスをみるとやっぱり前回設定したときと変わっていました。

linuxBeanのEclipseでPydev→Start Debug Server、でデバッグサーバを起動しておきます。

import pydevd; pydevd.settrace('192.168.10.105')

settrace()メソッドの引数にIPアドレスを指定してマクロのブレークしたいところに挿入してWindows10のLibreOfficeでマクロを起動します。

今回はLibreOffice5(81)Javaの例:GUIをPythonにする その7のenableRemoteDebugging()を使っているのでそのなかのデバッグコードを書き換えました。

import pydevd; pydevd.settrace('192.168.10.105', stdoutToServer=True, stderrToServer=True)

これでEclipseのデバッガでブレークできました。

待っていても動かない時は、マクロを起動しているLibreOfficeのウィンドウのどこかをクリックするとデバッガとつながるときがありました。

linuxBeanでは動くのにWindows10では動かないマクロの原因例


これまで遭遇した原因について記録しておきます。

結論としてはきちんと文法を守っていれば問題は起きないということです。

unohelper.fileUrlToSystemPath()にfileurl以外の文字列を渡すとエラーになる
(2017.9.21追記。エラーになるのは文字列によるようです。)

unohelper moduleのfileUrlToSystemPath()はfileurl("file://"から始まる文字列)をシステム固有のパスに変換して返します。

linuxBeanではfileurl以外の文字列を渡すとその文字列をそのまま返してきます。

しかしWindows10ではfileurl以外のものを渡すとエラーになりました。

さすがのlinuxBeanであっても「vnd.sun.star.expand:$BUNDLED_EXTENSIONS/wiki-publisher/templates」という文字列を渡すとuno.RuntimeException: Couldn't convert file url  to a system path for reason (21)というエラーになります(LibreOffice5(75)thePathSettingsシングルトンで既定のパスを取得参照)。

いろいろ文字列を削った結果、linuxBeanでも"d:"という文字列が渡した時はこのエラーがでることがわかりました。

代入文の右辺でタプルをアスタリスクでアンパックできない

(2017.11.6追記。これはLibreOffice5.3以下ではWindows版だけバンドルPythonのバージョンが3.3になっているのが原因でした。LibreOffice5.4ではWindows版もLinux版と同じPyhton3.5になっているので問題は起きないと思います。SyntaxError: can use starred expression only as assignment target · Issue #37 · bastibe/transplant · GitHub)

In [1]:
margin_width, margin_height = 100, 200
maxwidth, maxheight = 300, 400
margin_width, margin_height, maxwidth, maxheightという4つの変数に値を代入しておきます。
In [2]:
consts = margin_width, margin_height, maxwidth, maxheight
consts
Out[2]:
(100, 200, 300, 400)
constsにこの4つの変数をタプルにして代入しました。
これは普通の使い方です。
In [3]:
imagecontrolmargins = margin_width, margin_height
imagecontrolmargins
Out[3]:
(100, 200)
margin_widthとmargin_heightだけをまずimagecontrolmarginsというタプルに代入します。
今度はこのimagecontrolmarginsを使ってconstsを得る方法を考えます。
In [4]:
consts = imagecontrolmargins, maxwidth, maxheight
consts
Out[4]:
((100, 200), 300, 400)
imagecontrolmarginsをそのまま使うと要素がタプルになってしまいますのでダメです。
In [5]:
consts = *imagecontrolmargins, maxwidth, maxheight
consts
Out[5]:
(100, 200, 300, 400)
引数リストのアンパックと同様にしてタプルの前にアスタリスクをつけるとうまくいきました、、、
linuxBeanでは問題なく動きました。

しかしPyDevはアスタリスクを付けた *imagecontrolmarginsがunused variableという警告がでてきます。

本来アスタリスクを使ったアンパックは代入されるものに使うもの、つまり引数とか、代入式の左辺に使うもの、のようです。

それでもlinuxBeanではPyDevで警告がでるもののそのまま使えてしまいます。
Microsoft Windows [Version 10.0.15063]
(c) 2017 Microsoft Corporation. All rights reserved.

C:\Users\pq>"C:\Program Files (x86)\LibreOffice 5\program\python.exe"
Python 3.3.5 (default, Dec 20 2016, 00:04:55) [MSC v.1800 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> margin_width, margin_height = 100, 200
>>> maxwidth, maxheight = 300, 400
>>> imagecontrolmargins = margin_width, margin_height
>>> consts = imagecontrolmargins, maxwidth, maxheight
>>> consts
((100, 200), 300, 400)
>>> consts = *imagecontrolmargins, maxwidth, maxheight
  File "<stdin>", line 1
SyntaxError: can use starred expression only as assignment target
>>>
Windows10では規則通りstarred expression(アスタリスクを付けた変数)は代入される方にしか使えないというエラーがでてきます。

FilePickerサービスのインスタンスをデータ属性に保存しておくと表示されない


LibreOffice: FilePicker Service Referenceにちゃんと「ファイルピッカーインスタンスへの参照をキャッシュすることはお勧めしません。 基礎となるシステムによる制限のため、特定の制限がある可能性があります。 これらの問題を解決するには、必要に応じて新しいインスタンスを作成することをお勧めします。」と書いてあります。

linuxBeanではとくに支障がでなかったので気にせず、リスナーの__init__()でFilePickerサービスをインスタンス化してデータ属性に保存しておいて、メソッドが呼ばれたときにそれを呼び出して使っていました。

ところがWindows10でLibreOffice5(81)Javaの例:GUIをPythonにする その7imagecontrolsample_taskcreator.pyのBrowseボタンをクリックしてもFilePickerで表示されるはずのファイル選択ダイアログは表示されませんでした。

調べてみるとexecute()メソッドは勝手に0を返していました。

ということでAPIリファレンスに書いてある通り、Browseボタンをクリックするたびに新しいインスタンスを作成するようにしたらWindows10でもファイル選択ダイアログが表示されるようになりました(imagecontrolsample_taskcreator_forWin.py)。

Windows10であっても、UnoControlDialog上のボタンからはlinuxBeanのときと同じようにデータ属性に保存したFilePickerでもファイル選択ダイアログが表示されました(imagecontrolsample.py)。

結局Windows10でも動くマクロにするにはちゃんと規則を守ってコードを書きましょうということでした。

参考にしたサイト


Python-UNO bridge
unohelper moduleのfileUrlToSystemPath()がlinuxBeanとWindows10で少し挙動が異なりました。

4. その他の制御フローツール — Python 3.6.1 ドキュメント
引数リストのアッパックは代入文の右辺には使わない方がよいです。

LibreOffice: FilePicker Service Reference
FilePickerは使うたびにインスタンス化したほうがよいです。

SyntaxError: can use starred expression only as assignment target · Issue #37 · bastibe/transplant · GitHub
Python3.5からタプルのアンパックを使える場合が増えました。

次の関連記事:LibreOffice5(84)Javaの例:GUIをPythonにする その9

ブログ検索 by Blogger

Translate

最近のコメント

Created by Calendar Gadget

QooQ