はじめに
PythonのRPA用ライブラリ、pywinauto
は非常に便利なライブラリであり、WindowsのGUI操作に強力な機能があります。
しかし、そのドキュメントは日本語で十分に充実しているとは言えず、GitHubのREADME.md
にある"Simple Example"は日本語環境では動きません。
これがなぜ動かないかをエラーメッセージやソースコードから見抜くのは非常に困難なので、技術選定の段階で挫折しているプロジェクトが多いのではと考えています。
この記事では、「とりあえず"Simple Example"と同等物を動かせるようにする」ことを目標に解説していきます。
"Simple Example"実行時のエラー
"Simple Example"のコードは、下記のようにシンプルです。
from pywinauto.application import Application
app = Application().start("notepad.exe")
app.UntitledNotepad.menu_select("Help->About Notepad")
app.AboutNotepad.OK.click()
app.UntitledNotepad.Edit.type_keys("pywinauto Works!", with_spaces = True)
仕様がわからなくても、クラス名や関数名、プロパティ名から、なんとなく「メモ帳を起動して、情報ウィンドウを開いて、OKを押下して閉じて、"pywinauto Works!"
と入力するものだ」ということが把握できるかと思います。
しかし、これを実行すると、下記のようなエラーとなります。
Traceback (most recent call last):
...
File "...\pywinauto\controls\hwndwrapper.py", line 1084, in menu_select
self.menu_item(path, exact=exact).select()
File "...\pywinauto\controls\hwndwrapper.py", line 1028, in menu_item
return self.menu().get_menu_path(path, appdata = menu_appdata, exact=exact)[-1]
File "...\pywinauto\controls\menuwrapper.py", line 110, in check
return method(instance, *args, **kwargs)
File "...\pywinauto\controls\menuwrapper.py", line 569, in get_menu_path
best_item = findbestmatch.find_best_match(
File "C:\Users\komoj\pywinauto\pywinauto\findbestmatch.py", line 133, in find_best_match
raise MatchError(items = text_item_map.keys(), tofind = search_text)
pywinauto.findbestmatch.MatchError: Could not find 'Help' in 'dict_keys(['ファイル(&F)', '編集(&E)', '書式(&O)', '表示(&V)', 'ヘルプ(&H)'])'
メッセージから「どうやら操作対象画面要素をマッピングしている辞書のキーに"Help"
がない」からエラーになっていることがわかりますが、ここからどうやってエラーを解決すべきかは、これから開発しようとしているプロジェクト/プロダクトにpywinauto
を使うべきかという技術選定段階ではなかなか見つけられないでしょうし、事実、メソッドの実装はかなり複雑な呼び出し経路をたどっています。
日本語環境で動くコード
動作環境を考慮しつつ、"Simple Example"を日本語環境で動くコードにするとこうなります。
from pywinauto.application import Application
app = Application().start("notepad.exe")
app.UntitledNotepad.menu_select("ヘルプ->バージョン情報")
app.バージョン情報.OK.click()
app.UntitledNotepad.Edit.type_keys("pywinauto Works!", with_spaces=True)
-
menu_select("Help->About Notepad")
->menu_select("ヘルプ->バージョン情報")
これは比較的わかりやすいですが、表示されているメニュー画面の通りに指定する文字列を直しただけです。
menu_select
は、"->"
で渡された文字列を分割して、各文字列で指定されたメニューアイテムを押下し続けていくメソッドです。日本語で指定されたことにより日本語環境メモ帳の「バージョン情報」ウィンドウを開くことができます。 -
app.AboutNotepad.OK.click()
->app.バージョン情報.OK.click()
日本語で属性の指定を行っている、少し奇妙なコードとなります。これはApplication
には__getattr__
や__getattribute__
が実装されており、動的な属性アクセスを行うためです。
Application
は指定された属性と同名(.
や-
や
展望
現在、実行環境の言語に関する言及をREADMEに導入することを、discussionsで提案しています。
これが受け入れられれば、「しょっぱなサンプルコードが動かない!」で導入をあきらめるプロジェクトが減って、pywinauto
コミュニティが活性化するのではと期待しています。