2月ぐらいに構築したポケモン耐久調整ツールですが、なぜか4月28日ぐらいから使用できない状態となっていました。
んで、気づいたのが1週間前ぐらいだったのですが、なかなか修正に取り組む時間もなく放置してしまっておりましたが、ようやくまとまった時間が取れたので本腰を入れる。
まずはなんでおかしくなっているのかを確認しました。
原因
まずは原因調査。
APIサービスを再起動してみてログに何が出てるか確認する。
BrokenFilesystemWarning: Detected a misconfigured UNIX filesystem: Will use UTF-8 as filesystem encoding instead of 'ascii'
単純に翻訳すると、
「asciiが使えないからutf-8を使うよ」
っていうエラーに見えます。
そもそもasciiを使用するような設定はしてなかったと思うのですが、なんでこんなエラーがいきなり表示されるんや?
と思い、以下のファイルを覗いてみる。
less /usr/local/lib/python3.6/site-packages/werkzeug/filesystem.py
# -*- coding: utf-8 -*-
"""
werkzeug.filesystem
~~~~~~~~~~~~~~~~~~~
Various utilities for the local filesystem.
:copyright: 2007 Pallets
:license: BSD-3-Clause
"""
import codecs
import sys
import warnings
# We do not trust traditional unixes.
has_likely_buggy_unicode_filesystem = (
sys.platform.startswith("linux") or "bsd" in sys.platform
)
def _is_ascii_encoding(encoding):
"""Given an encoding this figures out if the encoding is actually ASCII (which
is something we don't actually want in most cases). This is necessary
because ASCII comes under many names such as ANSI_X3.4-1968.
"""
if encoding is None:
return False
try:
return codecs.lookup(encoding).name == "ascii"
except LookupError:
return False
class BrokenFilesystemWarning(RuntimeWarning, UnicodeWarning):
"""The warning used by Werkzeug to signal a broken filesystem. Will only be
used once per runtime."""
_warned_about_filesystem_encoding = False
def get_filesystem_encoding():
"""Returns the filesystem encoding that should be used. Note that this is
different from the Python understanding of the filesystem encoding which
might be deeply flawed. Do not use this value against Python's unicode APIs
because it might be different. See :ref:`filesystem-encoding` for the exact
behavior.
The concept of a filesystem encoding in generally is not something you
should rely on. As such if you ever need to use this function except for
writing wrapper code reconsider.
"""
global _warned_about_filesystem_encoding
rv = sys.getfilesystemencoding()
if has_likely_buggy_unicode_filesystem and not rv or _is_ascii_encoding(rv):
if not _warned_about_filesystem_encoding:
warnings.warn(
"Detected a misconfigured UNIX filesystem: Will use"
" UTF-8 as filesystem encoding instead of {0!r}".format(rv),
BrokenFilesystemWarning,
)
_warned_about_filesystem_encoding = True
return "utf-8"
return rv
たぶん、
rv = sys.getfilesystemencoding()
if has_likely_buggy_unicode_filesystem and not rv or _is_ascii_encoding(rv):
if not _warned_about_filesystem_encoding:
warnings.warn(
"Detected a misconfigured UNIX filesystem: Will use"
" UTF-8 as filesystem encoding instead of {0!r}".format(rv),
BrokenFilesystemWarning,
)
_warned_about_filesystem_encoding = True
return "utf-8"
この辺でasciiからutf-8に変換する処理をやってそうだなあと考えました。
簡単に読んでみると、rvという変数にデフォルト言語を格納している?みたいな感じ。
このrvがasciiになっているからおかしなことになっている・・・のかな?
というわけで
rv = sys.getfilesystemencoding()
print(rv) # 追記
if has_likely_buggy_unicode_filesystem and not rv or _is_ascii_encoding(rv):
if not _warned_about_filesystem_encoding:
warnings.warn(
"Detected a misconfigured UNIX filesystem: Will use"
" UTF-8 as filesystem encoding instead of {0!r}".format(rv),
BrokenFilesystemWarning,
)
_warned_about_filesystem_encoding = True
return "utf-8"
ってやって無理やりrvの中身を表示させてみる。
ascii
あーやっぱりなーーー
原因はPython3のデフォルト言語がUTF-8ではなくasciiになっており、うまくエンコードできなかったのでその部分でエラーを吐いていたようです。
解決方法
では、どやってUTF-8に直すのかというと、こちらの記事が非常に参考になりました。
単純に環境変数にUTF-8を設定して解決させる方法です。
上記の記事ではC.UTF-8を設定しておりましたが、私の場合は以下コマンドにてJPを設定。
export LANG="ja_JP.UTF-8
APIサービスを再起動すると、発生していたエラーは無くなりました。
よかったよかった・・・
まとめ
- Python3で日本語エンコード辺りでエラーを吐いている場合は環境変数等を見直しましょう。
何故突然こんなことになったのか謎ですが、今後も発生しうると思われますので備忘録として残しておきます。
使用してくれている方々には大変ご迷惑をおかけいたしました・・・。
コメント