何が起きたか
Streamlit Community Cloud(SCC)に共起ネットワークを表示するアプリをデプロイしたら、ノードのラベルが □□□ になった。ローカルでは普通に出ていたのに。
なぜ起きるか
SCC の実行環境に日本語フォントが入っていない。matplotlib のデフォルトフォント DejaVu Sans には日本語グリフがないので □ に置き換わる。ローカルだと OS のフォントを使えるから気づかない。
対処
フォントファイルをリポジトリに入れて、コードから直接読む。
フォントを置く
Google Fonts から Noto Sans JP をダウンロードして fonts/ に置く。Regular 1ウェイトで約 9MB。
your-app/
├── fonts/
│ └── NotoSansJP-Regular.ttf
├── pages/
│ └── 共起分析.py
└── requirements.txt
matplotlib + networkx
import pathlib
import matplotlib
from matplotlib import font_manager
import networkx as nx
# フォント登録
_font_path = pathlib.Path(__file__).parent.parent / "fonts" / "NotoSansJP-Regular.ttf"
if _font_path.exists():
font_manager.fontManager.addfont(str(_font_path))
matplotlib.rcParams["font.family"] = (
font_manager.FontProperties(fname=str(_font_path)).get_name()
)
matplotlib.rcParams["axes.unicode_minus"] = False
ここまでで matplotlib の描画は日本語が出るようになる。ただし nx.draw_networkx_labels() はデフォルトで sans-serif を使うので、font_family を明示的に渡す必要がある。
_font_name = matplotlib.rcParams["font.family"]
if isinstance(_font_name, list):
_font_name = _font_name[0]
nx.draw_networkx_labels(G, pos, font_size=9, font_family=_font_name, ax=ax)
rcParams だけ設定して「なんで出ないんだ」としばらく悩んだ。networkx 側にも渡さないといけない。
packages.txt でもできる(参考)
packages.txt に fonts-noto-cjk を書けばシステムフォントとしてインストールされる。ただしパスが Debian バージョンで変わるので、候補を複数持つ必要がある。リポジトリに同梱するほうが確実。
まとめ
| ハマりポイント | 対処 |
|---|---|
| SCC に日本語フォントがない |
fonts/ にフォントを同梱 |
rcParams 設定したのに networkx が文字化け |
draw_networkx_labels に font_family= を渡す |