Synfig Studioのlottie出力時にPythonのエラーに遭った話
個人開発 トラブルシュート
2024/9/8
要約
- Synfig Studioには、lottie形式で出力する機能がプラグインとして実装されている (コードでいうとこのへん)
- このプラグインはPythonで実行されていて、lottieのプレビュー用のHTMLを出力する際に、JavascriptのコードがUTF-8で書かれているファイルを読み込んで書き込むような処理がある?
- Pythonがシステムのlocaleからデフォルトのエンコード設定を変えるような動きをするので、日本語環境でそのまま使おうとするとShift JISでは読み込めない旨のエラーが発生する
- 回避策として、
コントロール パネル\時計と地域
から「地域」→「システムロケールの変更」→「ベータ: ワールドワイド言語サポートでUnicode UTF-8を使用」にチェックしたら、動作するようになった
エラーの詳細
まず、Synfig Studioで発生した具体的なエラーは以下の通り。
- Synfig Studioのver.1.4.5およびver.1.5.3で確認
- 1.4.5では、「プラグイン」→「Export to lottie format」から実行
- 1.5.3では、「ファイル」→「Export...」からフォーマットを
Lottie HTML Preview (*.html)
あるいはLottie HTML Preview without variable widths (*.html)
を選択して「保存」
- 中心に円を追加しただけの
.sifz
ファイルを使用 (.sif
ファイルでも同様の結果となった) - 以下のようなエラーダイアログが表示される (エラー発生箇所の行数だけ異なる)
1Traceback (most recent call last):
2 File "{installedPath}\share\synfig\plugins\lottie-exporter\lottie-exporter.py", line 167 (1.5.3では"line 147"), in <module>
3 out = gen_html(out)
4 File "{installedPath}\share\synfig\plugins\lottie-exporter\lottie-exporter.py", line 92 (1.5.3では"line 75"), in gen_html
5 bodymovin_script = f.read()
6UnicodeDecodeError: 'cp932' codec can't decode byte 0x93 in position 30346: illegal multibyte sequence
f.read()
でUnicodeDecodeError
が起きているとのことなので、以下のコードの動作を確認してみた。
utf8.txt
とshiftJIS.txt
はそれぞれ、bodymovin_script
という変数から、HTML出力に成功した際のscript
タグの中身を入力した。
encodingTest.py
1import locale
2print("encoding: ", locale.getencoding())
3
4print("--- utf-8 ---")
5try:
6 print("start reading")
7 utf8File = open("./utf8.txt", "r")
8 utf8File.read(-1)
9 print("finish reading")
10except UnicodeDecodeError as e:
11 print("error: ", type(e))
12 print("utf-8 error: ", e)
13finally:
14 utf8File.close()
15
16print("--- shift JIS ---")
17try:
18 print("start reading")
19 shiftJisFile = open("./shiftJIS.txt", "r")
20 shiftJisFile.read(-1)
21 print("finish reading")
22except UnicodeDecodeError as e:
23 print("error: ", type(e))
24 print("shift JIS error: ", e)
25finally:
26 shiftJisFile.close()
結果として、「ベータ: ワールドワイド言語サポートでUnicode UTF-8を使用」が未設定のときには↓のようになり、
1{workingDir}> python .\encodingTest.py
2encoding: cp932
3--- utf-8 ---
4start reading
5error: <class 'UnicodeDecodeError'>
6utf-8 error: 'cp932' codec can't decode byte 0x93 in position 31312: illegal multibyte sequence
7--- shift JIS ---
8start reading
9finish reading
チェックを付けると↓のように変わった。
1encoding: cp65001
2--- utf-8 ---
3start reading
4finish reading
5--- shift JIS ---
6start reading
7finish reading
ということで、
locale.getencoding()
の結果はcp932
→cp65001
へcp932
はShift JIS規格のエンコーディング (cpは"code page"を意味するらしい)cp65001
はWindows内でutf-8を表すエンコーディング? (ちゃんとした情報が見つからなくてよくわかってない)
cp932
(Shift JIS) のエンコーディングになっているときには、'cp932' codec can't decode byte 0x93
という、Synfigで起きているエラーと同じエラーが発生しているcp65001
(utf-8?)になっているときには、いずれのファイルもエラーなく読み込めている (Synfigと動作が同じ)
という結果となった。
このことから、やはりPythonのf.read()
はシステムのロケール情報からデフォルトのエンコーディング設定を変えており、それがSynfig Studioの動作に影響を与えていると見てよさそう。
Synfigのことを調べててもどうしようもなく、Python (環境) 側で対処しないといけないのは不親切では?
と思ったので、Synfigにissueとして報告してみた: #3418
Pythonでファイル読込してるところでエンコーディングを指定すれば、Python側のことは考慮不要になるんだろうなと思ってはいる。 どこを直すべきなのかも頑張ってコード読めばわかる気はするんだよな (このこと考えるにあたってちらっと読んだときには、なんかライブラリ通じて読み込んでる?からよくわかんなくなった)。 なので、「日本語環境のことなんか日本人が直せばいいじゃん」と言われてしまったら、自力で直しにかかってみようかな。 けっこうSynfigのこと好きになってきてるし、OSSにcontributeしてみたいし!