Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ユーザー辞書で traceback.print_exc() をする意図は何か #1332

Closed
2 tasks done
tarepan opened this issue May 26, 2024 · 5 comments
Closed
2 tasks done

ユーザー辞書で traceback.print_exc() をする意図は何か #1332

tarepan opened this issue May 26, 2024 · 5 comments
Labels
要議論 実行する前に議論が必要そうなもの

Comments

@tarepan
Copy link
Contributor

tarepan commented May 26, 2024

質問の内容

VOICEVOX ENGINE では基本的にエラー内容を HTTP で返している。
しかしユーザー辞書では例外的に、一部エラーに対して traceback.print_exc() を用いたエラーロギングを併用している。
一見すると HTTP で十分に感じる。

このような背景から、次の質問があります:

  • traceback.print_exc() を用いたエラーロギングは意図された実装か否か
  • traceback.print_exc() は廃止可能か否か

VOICEVOXのバージョン

0.19.0

@tarepan tarepan added the 要議論 実行する前に議論が必要そうなもの label May 26, 2024
@sabonerune
Copy link
Contributor

これはロギングというより意図的な例外の握り潰しです。

実装時点の考えでは起動時に辞書の更新に失敗してもそのまま起動できるようにするという意図がありました。
(Windowsではエンジンを複数起動するとpyopenjtalk内のmecabが辞書を排他的に開いてしまうためこの問題が起こる可能性が高いです)

しかしリファクタリングを繰り返したことでこの意図が抜け必要以上の例外を握りつぶすようになった感じがします。
(変更のPRの確認をしていませんが)


もう一つ気づいたことなのですがこの例外処理の握りつぶしによってAPI側からは辞書の更新が行われたかどうか一切分からないという問題に気づきました。
辞書の更新を実行するとuser_dict.jsonのみが更新され適用中の辞書は更新することができません。

また、迂闊にエラーを返すとエンジンが複数起動している場合Windows環境ではエディタが起動不可能になる可能性もあります。

@tarepan
Copy link
Contributor Author

tarepan commented May 27, 2024

意図的な例外の握り潰し

なるほどです。情報ありがとうございます!

確認したところ、delete_file() でのみエラー握り潰しがおこなわれており、他では別エラー即時再送出をおこなっていました。つまり、握り潰しは意図した箇所でのみおこなわれていそうです。

他の箇所で握りつぶさないのに traceback.print_exc() があるのは…後世の人がノリで付けてみた、って感じですかね…?削除できそうに感じました。


辞書の更新が行われたかどうか一切分からない

👍️
重大な問題であることに同意です。
起きうる事象、その際に望ましい振る舞い、現在の実装、などを一度整理する必要がありそうです。

@Hiroshiba
Copy link
Member

Hiroshiba commented May 28, 2024

整理してきました!
@sabonerune さんのおっしゃってるとこと @tarepan さんがおっしゃってるとこがずれてそうです。

@tarepan
user_dict router上のtraceback.print_exc()は、確かに名残で残っているだけだと思うので、他に合わせて消してしまって問題ないと思います!
というより多分本当は、エラーが起こったらエラーをロギングしてあげた方が良いかも、とかちょっと思いました。
でも大多数がエラーログはいてないので、合わせる形が合理的だと思います!

@sabonerune
issue側にコメントしてきました! #620 (comment)
で、このコードは現在のmainブランチにないですね・・・。
探してみたら僕のプルリクエストによって消されてました。
https://github.com/VOICEVOX/voicevox_engine/pull/630/files?w=1#diff-ea1c0fdbfa9b5315be723416f7738fe4f40e54b8b5c3a01b9c0845b6358c2531L103-L106
当時の記憶があまりないですが、たぶんコードの意図を把握できず消してしまったかもです。
(意図コメントを足しといたら防げてたかもな~と感じました)

ちょっとissue違いな気がしますが、色々調べたのでまとめてみます

  • 目指す UX
    • ユーザーが意図していない挙動になっているのに、エラーや通知がないのは避けたい
    • エンジンの多重起動でエラーになるのも避けたい
    • ↑のUXが衝突する場合どっちが優先の高いかはエラー次第
  • 挙動の整理
    • update_dict、つまり保存した辞書などをopenjtalkに読み込ませる部分で、多重起動している場合にエラーになる
      • pyopenjtalk.set_user_dictしたものはopenjtalk側でずっとファイルハンドラが必要で、同じファイルに書き込めないから
    • 以前一瞬握りつぶすコードがあったが、今はなくなってる
  • 多重起動時の読み込みエラーを握りつぶすべきか
    • もし握りつぶした場合の意図しない挙動は「エンジンが2つ起動している時、辞書登録できたのに辞書が反映されない」になる
      • 後から起動したエンジンに対してVOICEVOX用の辞書には登録できるけど、openjtalk用の辞書には反映されない&エラーにもならないので、登録できたのに反映されない形になる
    • でも辞書登録しない人には関係ない
    • 判断つかない。。。迂回方法を探りたい。

とりあえず、同じファイルに対してpyopenjtalk.set_user_dictしまうのが問題なので、コンパイルしたユーザー辞書を保存するパスをランダムにすれば問題は起きない。
でもどんどんファイルが溜まっていってしまう・・・。

迂回作としては、ちょっと雑なアイデアだけど、compiled-0.diccompiled-4.dicまで空いてるパスを探して使うとか・・・?
ちょっとissue作ります!

issue作りました!

@sabonerune
Copy link
Contributor

@Hiroshiba

@sabonerune さんのおっしゃってるとこと @tarepan さんがおっしゃってるとこがずれてそうです。

except Exception as e:
print("Error: Failed to update dictionary.", file=sys.stderr)
traceback.print_exc(file=sys.stderr)
raise e

すみません、ここと混ざっていました。(しかもraseしているので握りつぶしていない)

@tarepan
Copy link
Contributor Author

tarepan commented May 29, 2024

となりました。
この issue は resolve につき close とします。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
要議論 実行する前に議論が必要そうなもの
Projects
None yet
Development

No branches or pull requests

3 participants