Sikuli - 例外処理

合致しなかったときの例外処理

Sikuliでは画像が見つからなかった時に例外が発生し、プログラムが停止します。
これを防ぐ方法としてまず考えられるのが、existsメソッドを使う方法です。existsメソッドを使ってあらかじめ画像が存在するかどうかを確認し、存在するならばクリックするようにプログラミングします。

1
2
3
4
if exists('xxxx.png'):
click(getLastMatch())
else:
popup(u'画像が見つかりませんでした。')

しかしこのようにif文をひとつひとつ記述するのは煩雑で、コードも見づらくなりますので、次の処理を検討した方がよいでしょう。

例外をトラップ

Sikuliは、画像が見つからないときなどに、FindFailedという例外を発生します。
次のコードのようにtry catchで囲って処理します。この方法であれば先に実装したようにひとつひとつexistsメソッドで調べなくてもすみます。

1
2
3
4
try:
click("xxxx.png")
catch FindFailed:
popup(u'画像が見つかりませんでした。')

例外をスキップするか例外ハンドラ処理

画像が見つからない場合は、そのまま無視したり、ユーザにどうするかを尋ねたりするほか、自分が設定した独自の例外ハンドラで処理することもできます。

関数名 解説
setThrowException(f) 例外を発生するかどうかを設定する。
f=Trueで発生させる(既定)
f=Falseで抑制する
setFindFailedResponse(ABORT|SKIP|PROMPT|RETRY) 画像が見つからなかったときにどうするかを設定する。
ABORT=例外を発生し終了する(既定)
SKIP=無視する。戻り値はNone
PROMPT=どのようにするかをユーザに尋ねる
RETRY=見つかるまでリトライする
setFindFailedHandler(handler) 例外が発生したときに実行する独自の例外ハンドラhandlerを設定する。

(1)例外の抑制

setThrowException(False)またはsetFindFailedResponse(SKIP)を実行すると、例外を抑制できます。この場合、戻り値はNoneになります。
clickメソッドやtypeメソッドは、引数がNoneであってもエラーなどは発生せずなにもしないだけです。
特にエラーメッセージを表示する必要がなく、単純に見つからなかったときは何もしないということであれば次のように記述できます。

1
2
setThrowException(False)
click('xxxx.png')

(2)どうするかをユーザに尋ねる

setFindFailedResponse(PROMPT)を実行しておくと、画像が見つからなかったときに確認ダイアログ①が表示されます。

1
2
setFindFailedResponse(PROMPT)
click('xxxx.png')

確認ダイアログ①


[Retry]をクリックすればリトライし、[Abort]をクリックすればプログラムは終了します。
[Capture/Skip]ボタンをクリックするとさらに次の確認ダイアログ②が表示されます。

確認ダイアログ②


[Capture]をクリックすると、この画像を別の画像に差し替えることができます。
Sikuliでは画像の解像度などの違いによって、別の環境に持っていくと画像がマッチしなくなってしまうことがあります。
setFindFailedResponse(PROMPT)としておけば、そのような場合ユーザがマッチする画像を差し替えることができるため大変便利です。

(3)独自の例外ハンドラ設定

setFindFailedHandlerメソッドを使うと、独自の例外ハンドラを設定できます。
ハンドラの書式は以下の通りです。

1
2
3
def handler(event):
#画像が見つからないときの処理をここに書く
event.setResponse(PROMPT) # どうするかをユーザに尋ねる

引数のeventオブジェクトはイベントが発生したときに渡されるObserveEventオブジェクトです。
例外ハンドラではevent.setResponseメソッドを使って、ABORT,SKIP,PROMPT,RETRYのいずれかの値を返さなければなりません。

この方法をとると画像が見つからなかったときに、エラーログを出力したり、メールを送信したりし、その後の処理はユーザに尋ねるといったことができるので個人的には一番お勧めです。