0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Electron経由で出力したlogが文字化けして困ったときにすること

Posted at

前置き

はいどうも、たねだです。
最近野暮用でまともにjavascriptを触ったこともないのに
ノリで使えると信じてElectronを使用しています。

構造としてはElectron(index.html)にある入力フィールドへ文字列を入力して送信ボタンを押すと
そのデータを取得してPython(FastAPI)に渡すというシンプルな仕組みです。
ところが、何度やっても受け取った値がコンソール上でのみ文字化けしてしまい困ったという話。

このコンソール上でのみ文字化けしていたというのが
今回の問題の最大のポイントでしたので
同じような悩みで右往左往している方のヒントになれば幸いです。
ではやっていきましょう!

環境

  • Windows11 24H2
  • VSCode 1.95.1
  • npm 10.9.0
  • node v22.11.0

試したこと

当然ですが問題が生じてからは
送受信する文字列が関わる処理に片っ端からconsole.log()をおいて確認しました。

コードを全て載せると煩雑になるので
ひとまず重要っぽいところだけ載せて進めていきます。

renderer.js
document.getElementById('sendButton').addEventListener('click', async () => {
    const message = document.getElementById('inputField').value;
    const response = await window.electronAPI.sendData(message);
    document.getElementById('responseField').innerText = `Response from Python: ${response}`;
});

まずは、index.htmlにある送信ボタンを押したときの動作です。
sendButtonがクリックされるとipcMainにvalueを渡します。
そして後述のmain.jsにデータが渡り、そこからさらにPythonサーバーへ送られた後
なんやかんやあってindex.htmlのresponseFieldに
Response from Python: ${response}が表示されるというわけですね。
このとき、確認したいのはmessageresponseがどうなっているかです。
この時点で文字化けないし何かおかしなことになっている場合は
そもそもindex.htmlからの受け渡しに失敗している可能性があります。

今回は該当しなかったので
renderer.jsおよびindex.htmlは問題なさそうとひとまず判断。

main.js
// ~その他の記述

// Renderer.jsからデータを受け取って、Pythonサーバーに送信するコード
ipcMain.handle('send-data', async (event, message) => {
    const encodedMessage = encodeURIComponent(message);
    const response = await fetch(`http://127.0.0.1:8000/receive-data?message=${encodedMessage}`);
    const data = await response.json();
    console.log(`Response: ${data.response}`);
    return data.response;
});

続いてmain.jsです。
こちらでまずsend-dataから受け取ったmessage
果たして問題ないのか確認したいところですね。

…すると今回はまずここで文字化けしていることがわかりました。
ここから長らく沼にはまるのですが、
Pythonサーバーにはこの後のencodedMessageをもって処理を行うので
Pyhtonの問題でもないだろうと考えました。
(というかそもそもターミナルをnpmで立ち上げているのでPythonからのログは直接出ない)

エンコードやデコードをrenderer.jsmain.jsにかませて
確認してみるも効果なし…。

ここまでで、ipcMainでの文字列の受け渡しがなんかうまいこといっていないのだろう。
つまり問題はmain.jsにあると考えていました。

ところが文字化けしているはずのencodedMessageですが、
Pythonサーバーを経由したのちにrenderer.jsによって
responseFieldに表示されているのに文字化けしていない…。

念のためPythonサーバーからrenderer.jsへ返される前に
tikinterを立ち上げてラベルとして送られてきた文字列を表示させてみると
やはり文字化けしていない…!

ということでいよいよコンソール上でのみ
文字化けが発生しているという判断に至ったわけですが、ここからも長かった。

これも色々やりましたがほぼ全てが徒労に終わりましたので
一瞬希望が見えた方法だけ1つ残しておきます。

ターミナル上(cmdでもPowerShellでも)にて
chcp 65001を実行するという方法ですね。
詳しいことはよくわかりませんが
コンソールのエンコーディングを65001(utf-8)にするというコマンドです。
実は上記はまだmain.jsが問題だと思っていた時に試してダメだったので
「やっぱりmain.jsに問題があるんだ」
という執着心が高まり解決に時間がかかったような気がします。

皆さんがこの記事をどういう経緯で見ているのかわかりませんが、
もしかすると上記で直る方もいるかもしれないですね。

そして解決へ…

長々と戦ってきたこの問題もいよいよ終着点です。
まだこの問題に悩んでいるそこのあなた、
とりあえず下記をターミナルで実行してください。

[Console]::OutputEncoding

上記を実行すると、こんな感じの内容が出力されるはずです。

BodyName          : utf-8
EncodingName      : Unicode (UTF-8)
HeaderName        : utf-8
WebName           : utf-8
WindowsCodePage   : 1200
IsBrowserDisplay  : True
IsBrowserSave     : True
IsMailNewsDisplay : True
IsMailNewsSave    : True
IsSingleByte      : False
EncoderFallback   : System.Text.EncoderReplacementFallback
DecoderFallback   : System.Text.DecoderReplacementFallback
IsReadOnly        : False
CodePage          : 65001

上記はすでに設定済みのものですが、
ここでutf-8以外のものが表示された場合
以下を実行してください。

[Console]::OutputEncoding = [System.Text.Encoding]::UTF8

実行したら、ターミナルを再起動して再度文字化けしないかを確認してください。
私はここまででひとまず解決しました。

ただ上記では暫定対応になってしまうので、
恒久的に設定を適応する場合は

echo '[Console]::OutputEncoding = [System.Text.Encoding]::UTF8' >> $PROFILE

上記を実行してPROFILEに直接設定を追加します。
同じくVSCodeの再起動を行い、[Console]::OutputEncodingで再度
エンコードがutf-8になっているかを確認して下さい。

もしもうまくいかない場合はecho $PROFILEを実行して、
$PROFILEファイルの位置を確認します。
ない場合はMicrosoft.PowerShell_profile.ps1を、
C:\Users\YourName\Documents\PowerShell\の直下に作成した上で
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8を記述し
PowerShellを再起動することで解消される可能性があります。

補足

上記を行うにあたりファイルの実行ができないなどのエラーが出た場合は
ポリシーが関係している場合があります。

Get-ExecutionPolicy

ターミナルで上記を実行してステータスがRestrictedになっている場合は
スクリプトの実行が制限されていますので、
ローカル上のスクリプトを実行可能にするため管理者権限でPowerShellを開き、

Set-ExecutionPolicy RemoteSigned -Scope CurrentUser

上記を実行することでポリシーの変更ができます。
その後再度ターミナルを再起動して[Console]::OutputEncodingにて
エンコーディングがutf-8になっていれば成功です。

説明するまでもないとは思いますが、
今回変更したポリシーの説明は割愛させていただきますので
詳細を知りたい方は以下MicroSoftが公開している
実行ポリシーについての記事をご覧ください。

以上、お疲れさまでした!

0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?