WindowsでUnicodeDecodeError: 'cp932' codec can't decode byte... が出たときの対処方法

## Case1. 自分で作ったところで発生した場合

1. 自分でopen関数などを書いた場合は対象のファイルがShift_JISであるかどうか確認します。
[chardet](https://pypi.org/project/chardet/)で確認することができます

```python
import chardet
with open(file, "rb") as f:
  result = chardet.detect(f.read())
```

  1-1. ファイルがShift_JISでないならShift_JISに変換します。
```python
with codecs.open(file, "r", "utf-8") as file:
    row_data = []
    for row in file:
       row_data.append(row)

with codecs.open(file, "w", "shift_jis") as file:
    for row in row_data:
        file.write(row)
```

  1-2. ファイルをUTF-8で開きたい場合はencodingを付け足します。

```python
f = open(file, encoding="utf-8")
```

そのうえでライブラリがopen関数などを読んでいる場合はシステムがどのエンコードを使っているかを確認します。

## Case2. 依存しているライブラリから発生している場合

pythonで使っているデフォルトのエンコーディングがShift_JIS(CP932)になっており、基本のエンコーディングのUTF-8を読み込めなくなっている可能性があります。

以下のスクリプトを実行してみてください。

```python
import os
import sys
import locale
print(os.environ.get("PYTHONIOENCODING"))
print(sys.getdefaultencoding())
print(sys.getfilesystemencoding())
print(sys.stdout.encoding)
print(locale.getpreferredencoding())
```

一つでも *cp932* があるとそれが原因でファイルを読み込めない場合があります。

それぞれのケースで対処方法を見ていきます。

### os.environ.get("PYTHONIOENCODING")でcp932が出た場合
### sys.getdefaultencoding()でcp932が出た場合

以下で修正できます。
```python
os.environ["PYTHONIOENCODING"] = "utf-8"
```

### sys.getfilesystemencoding()でcp932が出た場合

あまりないと思いますが以下で直せます。

```python
import sys
sys.getfilesystemencoding = lambda: 'UTF-8'
```

### sys.stdout.encodingでcp932が出た場合

以下で修正できます。
```python
sys.stdout.reconfigure(encoding='utf-8')
```

### locale.getpreferredencoding()でcp932が出た場合

おそらく最もありえると思われるパターンです。
Windowsでのロケールを変更します。
以下が参考になります。

https://qiita.com/nanbuwks/items/8ed83d48263e2f143125

コントロールパネルより「地域」→「管理」から

![img1](https://camo.qiitausercontent.com/51eac0771b193f3cb120ceeda26f7816554b3715/68747470733a2f2f71696974612d696d6167652d73746f72652e73332e61702d6e6f727468656173742d312e616d617a6f6e6177732e636f6d2f302f3133393532342f65363664303433382d333165652d393038372d323532652d3030623666383563386134652e706e67)

「システムロケールの変更」を選んでください。

![img2](
https://camo.qiitausercontent.com/3e94736679fb536fabd7ab7f2a5ce0c30fdf5669/68747470733a2f2f71696974612d696d6167652d73746f72652e73332e61702d6e6f727468656173742d312e616d617a6f6e6177732e636f6d2f302f3133393532342f63363531333762362d643735322d396436392d343235652d3130623832666633393932322e706e67)

「ベータ：ワールドワイド言語サポートでUnicode UTF-8を使用」にチェックを入れます。

![img3](https://camo.qiitausercontent.com/66d61737f8ba42e0940b0d4f585a2f248901d826/68747470733a2f2f71696974612d696d6167652d73746f72652e73332e61702d6e6f727468656173742d312e616d617a6f6e6177732e636f6d2f302f3133393532342f35336461666238662d636263662d303665632d323566652d3939626566666161363733392e706e67)

これで使われるロケールのエンコーディングがUTF-8になります。


### 別の対処法

Powershellで設定もできます。

```powershell
New-ItemProperty -LiteralPath 'HKLM:\SYSTEM\CurrentControlSet\Control\Nls\CodePage' -Name 'ACP' -Value '65001' -PropertyType String -Force;
New-ItemProperty -LiteralPath 'HKLM:\SYSTEM\CurrentControlSet\Control\Nls\CodePage' -Name 'OEMCP' -Value '65001' -PropertyType String -Force;
New-ItemProperty -LiteralPath 'HKLM:\SYSTEM\CurrentControlSet\Control\Nls\CodePage' -Name 'MACCP' -Value '65001' -PropertyType String -Force;
```

戻すときは以下です。

```powershell
New-ItemProperty -LiteralPath 'HKLM:\SYSTEM\CurrentControlSet\Control\Nls\CodePage' -Name 'ACP' -Value '932' -PropertyType String -Force;
New-ItemProperty -LiteralPath 'HKLM:\SYSTEM\CurrentControlSet\Control\Nls\CodePage' -Name 'OEMCP' -Value '932' -PropertyType String -Force;
New-ItemProperty -LiteralPath 'HKLM:\SYSTEM\CurrentControlSet\Control\Nls\CodePage' -Name 'MACCP' -Value '932' -PropertyType String -Force;
```


### 注釈:cp65001とは？

UTF-8の別名みたいです。

pythonでは以下のように出力されます。

```python
import codecs
codecs.lookup('cp65001')
```
```
<codecs.CodecInfo object for encoding utf-8 at 0x1a62631cbe0>
```