macOSでMatplotlibのエンコーディングエラーを解決する方法

## はじめに

Pythonでデータ可視化やグラフ作成を行う際に欠かせないライブラリであるMatplotlibですが、macOSで使用していると以下のようなエンコーディングエラーに遭遇することがあります。

```
Cannot decode configuration file ... as utf-8.
'utf-8' codec can't decode byte 0xb0 in position 37: invalid start byte
```

この記事では、この問題の原因と解決方法について説明します。実際にワードクラウド生成ツールの開発中に出くわした事例をもとに、具体的な対処法を紹介します。

## 問題の発生状況

### エラーメッセージ

典型的なエラーメッセージは以下のようなものです：

```python
Cannot decode configuration file PosixPath('/path/to/matplotlib/mpl-data/stylelib/.__classic_test_patch.mplstyle') as utf-8.
'utf-8' codec can't decode byte 0xb0 in position 37: invalid start byte
```

このエラーは、`wordcloud`のような、内部的にMatplotlibに依存するライブラリを使用しているときにも発生します。

### 実際のエラー出力例

実際のテスト実行時には、以下のようなエラーが表示されます：

```
シンプルなワードクラウドのテスト開始...
テキスト長: 291 文字
テキストを処理中...
単語数: 28
  テスト: 8
  ワードクラウド: 6
  画像: 6
  生成: 5
  Python: 3
  単語: 3
  テキスト: 2
  サンプル: 1
  使っ: 1
  日本語: 1
ワードクラウド生成中...
Cannot decode configuration file PosixPath('/path/to/matplotlib/mpl-data/stylelib/._seaborn-v0_8-notebook.mplstyle') as utf-8.
ワードクラウド画像生成中にエラーが発生しました: 'utf-8' codec can't decode byte 0xb0 in position 37: invalid start byte
```

### どんなコードで発生するか

以下のような単純なワードクラウド生成コードでも問題が発生することがあります：

```python
from wordcloud import WordCloud
import matplotlib.pyplot as plt

# テキストデータ
text = "Python データ分析 可視化 matplotlib エラー 解決 macOS エンコーディング 問題 対策"

# ワードクラウドを生成
wordcloud = WordCloud(width=800, height=400, background_color='white').generate(text)

# 表示
plt.figure(figsize=(10, 5))
plt.imshow(wordcloud, interpolation='bilinear')
plt.axis('off')
plt.show()
```

## 原因

この問題は主に以下の原因で発生します：

1. **macOSのリソースフォーク**: macOSはファイルにメタデータを格納するために「リソースフォーク」と呼ばれる仕組みを使用しており、これが「._」や「.__」で始まる隠しファイルとして現れます

2. **非UTF-8エンコーディング**: これらの隠しファイルは通常UTF-8以外のエンコーディング（MacRomanなど）を使用していますが、Matplotlibはファイルの読み込み時にUTF-8を想定しています

3. **stylelib内の隠しファイル**: Matplotlibはスタイル設定を`mpl-data/stylelib`ディレクトリから読み込みますが、このディレクトリに存在する「._」で始まるファイルがエラーの原因となります

## 解決方法

### 方法1: 問題のスタイルファイルを修正する

問題を解決する最も直接的な方法は、エラーの原因となっている隠しファイルを修正または削除することです。

```bash
find . -name "._*" -delete  
```

このコマンドを実行すると、問題のあるファイルを検出して修正します。

### 方法2: matplotlibを再インストールする

特定のバージョンのMatplotlibを指定して再インストールすることでも問題が解決する場合があります：

```bash
pip install --force-reinstall matplotlib==3.5.3
```

### 方法3: システムレベルの対応

macOSの設定で「._」ファイルの作成を抑制することもできます：

```bash
# ._ ファイルの作成を抑制
defaults write com.apple.desktopservices DSDontWriteNetworkStores true
```

## 実践例: ワードクラウド生成での対応

実際のプロジェクトでは、matplotlibに依存しない方法でワードクラウドを生成することで問題を回避することも可能です：

```python
from wordcloud import WordCloud
from janome.tokenizer import Tokenizer

def create_wordcloud_without_matplotlib(text, output_path, width=1920, height=1080):
    """matplotlibに依存せずにワードクラウドを生成する"""
    # テキストを処理
    t = Tokenizer()
    tokens = t.tokenize(text)
    
    # 単語の頻度をカウント
    word_frequencies = {}
    valid_pos = ['名詞', '動詞', '形容詞']
    
    for token in tokens:
        pos = token.part_of_speech.split(',')[0]
        if pos in valid_pos and len(token.surface) > 1:
            word = token.surface
            word_frequencies[word] = word_frequencies.get(word, 0) + 1
    
    # ワードクラウドを生成
    wc = WordCloud(
        width=width, 
        height=height,
        background_color="white",
        prefer_horizontal=0.9,
        regexp=r"[\w\p{Han}\p{Hiragana}\p{Katakana}]+",
        max_words=200
    )
    
    # 頻度から生成
    wc.generate_from_frequencies(word_frequencies)
    
    # 画像を直接ファイルに保存（matplotlibを使わない）
    wc.to_file(output_path)
    return True
```

このコードはmatplotlibの`plt.figure()`や`plt.imshow()`を使用せず、`WordCloud.to_file()`メソッドを直接呼び出すことでワードクラウド画像を生成します。

### 修正後の実行結果例

```
シンプルなワードクラウドのテスト開始...
テキスト長: 291 文字
テキストを処理中...
単語数: 28
  テスト: 8
  ワードクラウド: 6
  画像: 6
  生成: 5
  Python: 3
  単語: 3
  テキスト: 2
  サンプル: 1
  使っ: 1
  日本語: 1
ワードクラウド生成中...
ワードクラウド画像が 20250322_simple_wordcloud.png に保存されました。
ファイルサイズ: 19529 バイト
```

## 生成されるワードクラウドの例

修正が成功すると、以下のようなワードクラウド画像が生成されます。

![20250322_wordcloud_aD6LVN3EN4o.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/512829/72b1a24f-fb89-451a-aa30-e0a28ed0de71.png)


## まとめ

Mac OSだと ._ で始まる隠しファイルによってしばしば問題が発生します。適宜ファイル削除すれば問題解決可能ですが、ちょっと気が付きづらい。。。

## 参考リンク

- [Matplotlib公式ドキュメント](https://matplotlib.org/)
- [WordCloud公式リポジトリ](https://github.com/amueller/word_cloud)
- [macOSのリソースフォークについて](https://en.wikipedia.org/wiki/Resource_fork)