SamuraiT / mecab-python3

:snake: mecab-python. you can find original version here:http://taku910.github.io/mecab/
https://pypi.python.org/pypi/mecab-python3
Other
539 stars 51 forks source link

ValueError: too many values to unpack (expected 2) について #75

Closed ShutoSato closed 2 years ago

ShutoSato commented 2 years ago

初めまして。 ローカル環境では問題なく動いていたのですが、Herokuにデプロイしたところ、タイトルのようなエラー (エラー1) が出てしまい動かなくなってしまいました。 mecab-python3のバージョンは1.0.3です。 こちらにあったようにバージョンを落とし、0.996.5にすると解決するのですが、その場合別のエラー(エラー2)が出てしまい動きません。 また、test.pyで試してみると、バージョンが1.0.3の場合は問題なく動きますが、0.996.5にすると(エラー3のように)動きません。 何か解決方法はありますでしょうか? mecab-python3==1.0.3のまま、エラー1が解決できると一番いいなと考えています。

ローカルはDocker環境で、mecab-python3==1.0.3で問題なく動いていました。 初心者ですので至らない点等ございましたら申し訳ございません。

エラー1 (mecab-python3==1.0.3) ↓

    negaPosiResults = list(map(analyzer.analyze, TweetsAnalytics))
File "/app/.heroku/python/lib/python3.6/site-packages/oseti/oseti.py", line 109, in analyze
    for sentence in sengiri.tokenize(text):
File "/app/.heroku/python/lib/python3.6/site-packages/sengiri/sengiri.py", line 65, in tokenize
    result += _analyze_by_mecab(line, mecab_args)
File "/app/.heroku/python/lib/python3.6/site-packages/sengiri/sengiri.py", line 21, in _analyze_by_mecab
    (surface, features) = line.split('\t')
ValueError: too many values to unpack (expected 2)

エラー2 (mecab-python3==0.996.5) ↓

Traceback (most recent call last):
File "/app/app/Python/TweetsAnalytics.py", line 26, in <module>
    analyzer = oseti.Analyzer()
File "/app/.heroku/python/lib/python3.6/site-packages/oseti/oseti.py", line 20, in __init__
    self.tagger = MeCab.Tagger(mecab_args)
File "/app/.heroku/python/lib/python3.6/site-packages/MeCab/__init__.py", line 99, in __init__
    super(Tagger, self).__init__(*args)
RuntimeError

test.py ↓

import sys
import MeCab
m = MeCab.Tagger ()
print(m.parse ("すもももももももものうち"))

エラー3 (mecab-python3==0.996.5) ↓

Traceback (most recent call last):
  File "test.py", line 3, in <module>
    m = MeCab.Tagger ()
  File "/app/.heroku/python/lib/python3.6/site-packages/MeCab/__init__.py", line 99, in __init__
    super(Tagger, self).__init__(*args)
RuntimeError

~ $ pip list ↓

Package            Version
------------------ ---------
certifi            2021.10.8
charset-normalizer 2.0.8
emoji              1.6.1
idna               3.3
mecab-python3      1.0.3
neologdn           0.5.1
oauthlib           3.1.1
oseti              0.2
pip                21.3.1
python-dotenv      0.19.2
requests           2.26.0
requests-oauthlib  1.3.0
sengiri            0.2.1
setuptools         57.5.0
tweepy             4.4.0
unidic-lite        1.0.8
urllib3            1.26.7
wheel              0.37.0

Aptfile

locales
git make curl xz-utils file
mecab libmecab-dev mecab-ipadic-utf8 git make curl xz-utils file -y
polm commented 2 years ago

初めまして。

問題の原因は辞書の形式の違いにあります。

v0.966.5 では、ipadic が固定で使われているので、parse の出力はこうなります。

日本語  名詞,一般,*,*,*,*,日本語,ニホンゴ,ニホンゴ
EOS

タブが一つです。おそらくこの形式を想定していますね。

UniDic では形式が異なって、unidic-lite の場合 parse の出力はこうなります。v1.0 以降で、unidic-lite がインストールされている場合、デフォルト辞書として使われます。

日本    ニッポン        ニッポン        日本    名詞-固有名詞-地名-国                   3
語      ゴ      ゴ      語      名詞-普通名詞-一般                      1
EOS

ここでタブが複数ありますので too many values to unpack になってしまいます。

この出力形式は辞書の設定ファイルに記述されているもので、 Tagger を作成するときに別の形式を指定することはできます、詳細については 公式資料 をご参照ください。

RuntimeError について、以上の情報だけでは原因がよく分かりません。Tagger()のところを Model()にすると詳しいエラーが出ると思いますが、その場合はどうなりますか?

因みに、v0.996.1 から、MeCab や辞書を mecab-python3 と別にインストールする必要はありません。MeCab のバイナリは mecab-python3 に含まれていますので、pip install だけでインストールできます。また、parseの出力を処理しようとしているようですが、その場合 fugashi がおすすめです。中身は同じ MeCab ですが、辞書の情報を nametuple として提供するなど便利な機能が色々あります。チュートリアル ノートブックもありますので、ぜひ試してみてください。

polm commented 2 years ago

あ、すみません、ここで直接処理しているのではなくて、oseti/sengiriの内部処理の問題ですね。sengiriはipadic前提でできているので、MeCabの引数を渡す必要があります。osetiを使っているなら、最新版の mecab-python3 で、こうすれば動くと思います。

まずPython用のipadic をインストールします。

pip install ipadic

MeCabの引数を指定します。

import oseti
import ipadic

analyzer = oseti.Analyzer(mecab_args=ipadic.MECAB_ARGS)
analyzer.analyze('天国で待ってる。')

それで動かなかったら教えてください。

ShutoSato commented 2 years ago

ご回答ありがとうございます。問題の原因等よくわかりました。 そこで試してみたのですが、またいくつかうまくいかないことが出てきたので教えていただきたいです。

まず試したこととして、下記のコードを消し、

pip install unidic-lite

その後言われた通りに下記のコードを実行したところ、当初問題だったValueError: too many values to unpackは消すことができました。

pip install ipadic
import oseti
import ipadic

analyzer = oseti.Analyzer(mecab_args=ipadic.MECAB_ARGS)
analyzer.analyze('天国で待ってる。')

しかし、新たに以下のエラーが出るようになってしまいました。

------------------- ERROR DETAILS ------------------------
arguments: 
error message: [ifs] no such file or directory: ./dicrc
----------------------------------------------------------
Traceback (most recent call last):
  File "app/Python/test.py", line 5, in <module>
    analyzer.analyze('天国で待ってる。')
  File "/app/.heroku/python/lib/python3.6/site-packages/oseti/oseti.py", line 109, in analyze
    for sentence in sengiri.tokenize(text):
  File "/app/.heroku/python/lib/python3.6/site-packages/sengiri/sengiri.py", line 65, in tokenize
    result += _analyze_by_mecab(line, mecab_args)
  File "/app/.heroku/python/lib/python3.6/site-packages/sengiri/sengiri.py", line 13, in _analyze_by_mecab
    tagger = MeCab.Tagger(mecab_args)
  File "/app/.heroku/python/lib/python3.6/site-packages/MeCab/__init__.py", line 124, in __init__
    super(Tagger, self).__init__(args)
RuntimeError

mecabrcは環境変数で以下のように設定しています。

MECABRC == /app/.heroku/python/lib/python3.6/site-packages/ipadic/dicdir/mecabrc

他に以下のmecabrcも試してみましたが結果は同じでした。

MECABRC == /app/.heroku/python/lib/python3.6/site-packages/ipadic/dicdir
MECABRC == /app/.heroku/python/lib/python3.6/site-packages/ipadic/dicdir/dicrc

unidic-liteの際は上記のように設定することでこの問題は解決できていました。 そこでもう一度下記のようにunidic-liteをインストールしてみました、が、

pip install unidic-lite

再びValueError: too many values to unpackが出るようになってしまいました。

Traceback (most recent call last):
  File "app/Python/test.py", line 5, in <module>
    analyzer.analyze('天国で待ってる。')
  File "/app/.heroku/python/lib/python3.6/site-packages/oseti/oseti.py", line 109, in analyze
    for sentence in sengiri.tokenize(text):
  File "/app/.heroku/python/lib/python3.6/site-packages/sengiri/sengiri.py", line 65, in tokenize
    result += _analyze_by_mecab(line, mecab_args)
  File "/app/.heroku/python/lib/python3.6/site-packages/sengiri/sengiri.py", line 21, in _analyze_by_mecab
    (surface, features) = line.split('\t')
ValueError: too many values to unpack (expected 2)

どのように対処したら良いでしょうか?

polm commented 2 years ago

osetiのバグみたいです。ERROR DETAILSを見ると、arguments (引数)になにもないということは、ipadicに関する引数は使われていないということです。osetiの方では修正されたものの、修正版はまだPyPIに上がっていないようです。

https://github.com/ikegami-yukino/oseti/pull/3

osetiをソースからインストールすると動くと思います。

ShutoSato commented 2 years ago
git+https://github.com/ikegami-yukino/oseti.git

上記でosetiをソースからインストールしようとしたのですが、デプロイに失敗してしまいます。 Collecting mecab のところで失敗しているのですが、pip install oseti の時と何か違いがあるのでしょうか?

Collecting mecab
  Downloading mecab-0.996.3.tar.gz (62 kB)
  Preparing metadata (setup.py): started
  Preparing metadata (setup.py): finished with status 'error'
  ERROR: Command errored out with exit status 1:
  command: /app/.heroku/python/bin/python -c 'import io, os, sys, setuptools, tokenize; sys.argv[0] = '"'"'/tmp/pip-install-alvjch2t/mecab_817d524eeee94a23b53f43a3c304cec3/setup.py'"'"'; __file__='"'"'/tmp/pip-install-alvjch2t/mecab_817d524eeee94a23b53f43a3c304cec3/setup.py'"'"';f = getattr(tokenize, '"'"'open'"'"', open)(__file__) if os.path.exists(__file__) else io.StringIO('"'"'from setuptools import setup; setup()'"'"');code = f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' egg_info --egg-base /tmp/pip-pip-egg-info-9urtup19
            cwd: /tmp/pip-install-alvjch2t/mecab_817d524eeee94a23b53f43a3c304cec3/
  Complete output (10 lines):
  /bin/sh: 1: mecab-config: not found
  Traceback (most recent call last):
   File "<string>", line 1, in <module>
   File "/tmp/pip-install-alvjch2t/mecab_817d524eeee94a23b53f43a3c304cec3/setup.py", line 53, in <module>
     include_dirs=cmd2("mecab-config --inc-dir"),
   File "/tmp/pip-install-alvjch2t/mecab_817d524eeee94a23b53f43a3c304cec3/setup.py", line 19, in cmd2
     return cmd1(strings).split()
   File "/tmp/pip-install-alvjch2t/mecab_817d524eeee94a23b53f43a3c304cec3/setup.py", line 15, in cmd1
     return os.popen(strings).readlines()[0].rstrip()
  IndexError: list index out of range
  ----------------------------------------
ERROR: Could not find a version that satisfies the requirement mecab (from oseti) (from versions: 0.996, 0.996.2, 0.996.3)
ERROR: No matching distribution found for mecab
polm commented 2 years ago

これは少し分かりづらいですね…PyPIのmecabmecab-python3とは別のもので、osetiの作者が管理しているプロジェクトです。確かに以前mecab-python-windowsとして特にWindowsで使いやすいように作られましたが、いつからか他のOSでも動くようになってmecabと改名しました。ただしmecab-python3と違って、Linux用のwheelを提供していないため、ビルドするためにはMeCab本体が必要で、またmecab-configがPATHにないと以上のようにインストールできないようです。

それで、なぜmecabがインストールされるかというと、osetiのsetup.pyにはこのように定義されています。

https://github.com/ikegami-yukino/oseti/blob/facf14baea54a35400573456c949b797d0606826/setup.py#L8

install_requires = [] if pkgutil.find_loader('MeCab') else ['mecab']

これは少し特徴的な指定方法で、MeCabとしてインポートできるパッケージがない場合のみmecabはインストールされます。なので事前にmecab-python3をインストールすればmecabはインストールされません。(こちらで最初に試したときにmecabがインストールされることはなかったので困惑していました。)

少し長くなってしまいましたが、要するにosetiをpip installする前にpip install mecab-python3を実行すると直ると思います。

pip install oseti の時と何か違いがあるのでしょうか?

pip install git+https://github.com/ikegami-yukino/oseti.git

以上のコマンドとpip install osetiの違いは、pip install osetiだとPyPIから公開されている最新版(アルファ版などを除く)がインストールされます。逆にgitのURLを使う場合、gitに上がっているコードをそのまま使います。

osetiのPyPIでのリリース状態については下記で確認できます。最新のリリースは2019年10月のv0.2です。

https://pypi.org/project/oseti/#history

ShutoSato commented 2 years ago

なるほど...そういうことなんですね... よく分かりました。ありがとうございます。

少し長くなってしまいましたが、要するにosetiをpip installする前にpip install mecab-python3を実行すると直ると思います。

ただここがHerokuの仕様上?なのか、requirements.txtでの記述順を変えてみても同じエラーで上手くいかず... そのため、Herokuへのデプロイ方法からもう一度見直して色々試してみたいと思います。

丁寧に回答くださり本当に助かりました。ありがとうございました。

ShutoSato commented 2 years ago

当たり前だとは思いますが、pip installを使わずosetiのソースを直接自分のコードに入れてデプロイすることでとりあえずは動くようになりました。 ありがとうございました。