1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

OpenUSD python API でエラーメッセージが読めないことがある件

Posted at

ご無沙汰しております。
2023年3月より、オフィシャルに Pixar USD は OpenUSD と呼ぶ方向になっていくそうなので、なるべく OpenUSD と書いていこうと思います。ようやく検索しやすくなって助かりますね。

エラーメッセージを読みたい

OpenUSD は python API が充実していて、たいていの処理は python で書けば済んでしまいます。とても便利でよいのですが、ここに日本語ユーザ固有の問題が一つひそんでいます。

特に OpenUSD のプラグイン開発やちょっと込み入った使い方をしている大手ユーザで遭遇しやすいと思うのですが、python スクリプト中に USD でエラーが発生した際に

pxr.Tf.ErrorException: <unprintable ErrorException object>
UnicodeDecodeError: 'utf-8' codec can't decode byte 0x8e in position 152: invalid start byte

と出て、はて何のことやら、となることがありませんか。
(このメッセージをググってここに来た人、手を挙げて)

これは今(USD 2302)のところ、Windows 日本語環境で python 3.x で OpenUSD を使っているときに発生する問題です。USD 処理中のエラーメッセージでプラットフォーム固有部分のエラー(入出力とか、DLLとか)に Windows のエラーメッセージが混ざって出力されることがあるのですが、その際に SJIS で生成された文字列が python3 用に utf-8 文字列として渡されてしまった結果、python3 処理系がデコードできずにエラーになっているのでした。

この例は DLL が読めなかったケースなのですが、実際には

ImportError: DLL load failed: 指定されたモジュールが見つかりません。

という文字列です。「指」の字は SJIS では 0x8e77 なので、上のエラーでは 0x8e が utf-8 でデコードできないよ、と言ってるのですね。

USD レベルが上達してくるとこの1バイトの情報でどんなエラーかおおよそ想像できるようになってくる場合がありますが、さすがにみんなにそれを強いるのはしんどいので、対策を考えたいと思います。

このメッセージを処理している部分は base/arch/errno.cpp です。
https://github.com/PixarAnimationStudios/USD/blob/release/pxr/base/arch/errno.cpp#L73

size_t len = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
                           FORMAT_MESSAGE_FROM_SYSTEM |
                           FORMAT_MESSAGE_IGNORE_INSERTS,
                           nullptr,
                           errorCode,
                           MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
                           (LPSTR)&buffer,
                           0,
                           nullptr);

この MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT) が、ユーザ環境指定の言語のメッセージを作って buffer にポインタを返してくれます。したがって windows を英語環境に切り替えればもちろん英語メッセージになって解決するのですが、日本語環境で仕事している私たちにとってはあまりうれしい解決ではありません。

この言語指定は WinAPI の setThreadUILanguage でスレッド単位に行えるようです。python の locale モジュールでできるのかな、と思って試したのですがうまくいきませんでした。どなたか正しい方法ご存じでしたら教えて下さい。とりあえず僕らは winapi をたたきます。

import ctypes
ctypes.windll.kernel32.SetThreadUILanguage(1033)  #1033 は en-US の言語 ID

これを各スクリプトの先頭で実行すればいいんですが、USD グルたる我々としては、OpenUSD にパッチ当てちゃうのが美しい解決でしょう。オープンソース万歳。

上記のファイルの MAKELANGID 部分を
MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
と書き換えて OpenUSD(正確には lib_arch.dll) をビルドします。

これでめでたく、winapi を呼び出さずとも、上記エラーも

Error in 'pxrInternal_v0_22__pxrReserved__::PlugPlugin::_Load' at line 258 in file pxr\base\plug\plugin.cpp
: Failed to load plugin : The specified module could not be found.

となって、Windows の出すエラーメッセージも、その前の OpenUSD の出す情報も無事見ることができるようになりました。

めでたしめでたし。
というか windows はいつ SJIS から解放されるのでしょうか。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?