python-wordpress-xmlrpcで記事一覧取得時にエラー

`python-wordpress-xmlrpc`でWordPressから記事一覧を取得しようとして躓いた時の話。

# 環境

```:環境情報
OS: Windows 11
Python環境: Anacondaで仮想環境を構築
Pythonバージョン: 3.10.4

module:
 - python-wordpress-xmlrpc バージョン: 2.3
```

# エラーメッセージ
以下のドキュメントを参考に記事一覧の取得を試みるが、`collections`の処理中にエラーが出る。

- [python-wordpress-xmlrpc ドキュメント](https://python-wordpress-xmlrpc.readthedocs.io/en/latest/examples/posts.html#result-paging)

```python:GetListPosts.py
# 必要なモジュールを持ってくる
from wordpress_xmlrpc import Client, methods
from wordpress_xmlrpc.methods.posts import GetPosts

# client情報
url = 'https://hogehoge.com/xmlrpc.php' # トップページのアドレス末尾に/xmlrpc.phpを付ける
user = 'hoge' # WordPressのユーザ名
password = 'hogehoge' # WordPressのパスワード
 
client = Client(url, user, password)

# 記事一覧の取得。出力はリスト型。
posts = client.call(GetPosts())
```
```python:エラーメッセージ
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
Input In [6], in <cell line: 1>()
----> 1 posts = client.call(GetPosts())

File ~\anaconda3\envs\py310\lib\site-packages\wordpress_xmlrpc\base.py:46, in Client.call(self, method)
     44     else:
     45         raise
---> 46 return method.process_result(raw_result)

File ~\anaconda3\envs\py310\lib\site-packages\wordpress_xmlrpc\base.py:128, in XmlrpcMethod.process_result(self, raw_result)
    126     if isinstance(raw_result, dict_type):
    127         return self.results_class(raw_result)
--> 128     elif isinstance(raw_result, collections.Iterable):
    129         return [self.results_class(result) for result in raw_result]
    131 return raw_result

AttributeError: module 'collections' has no attribute 'Iterable'
```

# 原因と対策
## エラー原因
pythonのバージョン違いで、モジュールの `collections` が `collections.abc`に置き換わっているのが原因。
python3.8以上からこの問題が起こる模様。

## エラー対策
2022/9現在、`python-wordpress-xmlrpc`はバージョン2.3から暫く更新されておらず、当該バグも修正されていない。
ここでは、`python-wordpress-xmlrpc`内でエラーが起こっている`XmlrpcMethod.process_result`の関数を、修正した自作の関数に置き換えて処理を進める。

# 修正後のコード
```python:GetListPosts_ver2.py
# 修正するモジュールをインポート
from wordpress_xmlrpc.base import XmlrpcMethod

# 修正するにあたり、必要な関連モジュールをインポート
from wordpress_xmlrpc.compat import xmlrpc_client, dict_type
import collections.abc

# 元の関数をコピペして、自作関数を作成
def my_process_result(self, raw_result):
    if self.results_class and raw_result:
        if isinstance(raw_result, dict_type): # dict_type は wordpress_xmlrpc.compat からインポートしている
            return self.results_class(raw_result)
        elif isinstance(raw_result, collections.abc.Iterable): # collections => collections.abc に書き換え
            return [self.results_class(result) for result in raw_result]

    return raw_result

# 自作関数に置き換える。
XmlrpcMethod.process_result = my_process_result


###############################
### 以下、記事一覧取得のコード ###
###############################
from wordpress_xmlrpc import Client, methods
from wordpress_xmlrpc.methods.posts import GetPosts

# client情報
url = 'https://hogehoge.com/xmlrpc.php' # トップページのアドレス末尾に/xmlrpc.phpを付ける
user = 'hoge' # WordPressのユーザ名
password = 'hogehoge' # WordPressのパスワード
 
client = Client(url, user, password)

# 記事一覧の取得。出力はリスト型。
posts = client.call(GetPosts())
````

# 参考
- Qiita記事
    - [PythonでWordPressに投稿、一覧取得 - Qiita](https://qiita.com/wktq/items/65c00d93c3e08100abc9)
    - [Pythonでライブラリの処理を上書きする - Qiita](https://qiita.com/Asayu123/items/8d8da9911dd0c3296a81)
- GitHub
    - [GitHub - maxcutler/python-wordpress-xmlrpc: Python library for WordPress XML-RPC integration](https://github.com/maxcutler/python-wordpress-xmlrpc)
    - [fix import for py3.10 compat: collections.Iterable -> collections.abc… by foormea · Pull Request #148 · maxcutler/](https://github.com/maxcutler/python-wordpress-xmlrpc/pull/148)
- collections.abc について
    - [collections.abc --- コレクションの抽象基底クラス — Python 3.10.6 ドキュメント](https://docs.python.org/ja/3/library/collections.abc.html#module-collections.abc)


# 奮闘ログ
詳細はブログに記載。

- [【python】WordPressの記事一覧を取得しようとして躓いた話。 - あれこれふける](https://arefukeblog.com/python-wordpress-xmlrpc/)