Coder Social home page Coder Social logo

pyknp's Introduction

pyknp: Python Module for JUMAN++/KNP

形態素解析器JUMAN++(JUMAN)と構文解析器KNPのPythonバインディング (Python2系と3系の両方に対応)。

Requirements

  • Python
    • Verified Versions: 2.7.15, 3.7.11
  • 形態素解析器 JUMAN++ [EN] (or JUMAN[EN])
    • JUMAN++ はJUMANの後継にあたる形態素解析器
  • 構文解析器 KNP [EN]

Installation

$ pip install pyknp

Documents

https://pyknp.readthedocs.io/en/latest/

Authors/Contact

京都大学 黒橋・河原研究室 ([email protected])

  • John Richardson, Tomohide Shibata, Yuta Hayashibe, Tomohiro Sakaguchi

pyknp's People

Contributors

blyoa avatar dependabot[bot] avatar eggplants avatar eiennohito avatar gackel avatar ha1f avatar haruo31 avatar hkiyomaru avatar kaisugi avatar kzinmr avatar murawaki avatar nobu-g avatar pnnc205j avatar shirayu avatar tamuhey avatar trickytoforget avatar tsuchm avatar warashi avatar yudaik avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

pyknp's Issues

JumanとJuman++での挙動

knpに形態素解析結果を出力する解析器としてJuman++を使った場合いくつかの文で

;; Invalid morpheme ID: kata(25) kei(37)

といったIDが違うというエラーを発生させます。Pyknpはエラー行を発見した際に例外を発生させていますが、KNPは解析を続け結果の出力まで行っています。

このエラーは無視できるものなのでしょうか。

エラーを起こす文のサンプル

  • この吉本くんは大変千葉さんのファンでしてね。
  • 平野という人の出生にからまる問題でしてね。

原因としてはJumanとJuma++に同梱されるJUMAN.katuyouが異なることかと考えたりもしていますが……

複数スレッド間で `Juman` インスタンスを共有し analysis を実行すると確率的に処理が止まってしまう

複数スレッド間で Juman インスタンスを共有し analysis を実行すると確率的に処理が止まってしまう事象を観測したので報告します。
私はマルチスレッドで web サーバを起動していたときにこの事象に遭遇しました。

再現コード

from concurrent.futures import ThreadPoolExecutor
from pyknp import Juman


def main():
    jumanpp = Juman()

    # これは動く
    # for _ in range(10):
    #     print([m.midasi for m in jumanpp.analysis("こんにちは!").mrph_list()])

    # 途中で止まる
    with ThreadPoolExecutor(max_workers=10) as executor:
        futures = []
        for _ in range(10):
            futures.append(
                executor.submit(jumanpp.analysis, "こんにちは!")
            )

        for f in futures:
            print([m.midasi for m in f.result()])


if __name__ == "__main__":
    main()
foo@bar:/home# python reproduce.py
['こんにちは', '!']
['こんにちは', '!']
['こんにちは', '!'] ← ここで出力が止まってしまう


^C^CTraceback (most recent call last): ← Ctrl+C で中断しないとずっと何も返さない
  File "reproduce.py", line 60, in main
    print([m.midasi for m in f.result()])
  File "/usr/local/lib/python3.7/concurrent/futures/_base.py", line 430, in result
    self._condition.wait(timeout)
  File "/usr/local/lib/python3.7/threading.py", line 296, in wait
    waiter.acquire()
KeyboardInterrupt

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "reproduce.py", line 64, in <module>
    main()
  File "reproduce.py", line 60, in main
    print([m.midasi for m in f.result()])
  File "/usr/local/lib/python3.7/concurrent/futures/_base.py", line 623, in __exit__
    self.shutdown(wait=True)
  File "/usr/local/lib/python3.7/concurrent/futures/thread.py", line 216, in shutdown
    t.join()
  File "/usr/local/lib/python3.7/threading.py", line 1044, in join
    self._wait_for_tstate_lock()
  File "/usr/local/lib/python3.7/threading.py", line 1060, in _wait_for_tstate_lock
    elif lock.acquire(block, timeout):
^CKeyboardInterrupt
^CError in atexit._run_exitfuncs:
Traceback (most recent call last):
  File "/usr/local/lib/python3.7/concurrent/futures/thread.py", line 40, in _python_exit
    t.join()
  File "/usr/local/lib/python3.7/threading.py", line 1044, in join
    self._wait_for_tstate_lock()
  File "/usr/local/lib/python3.7/threading.py", line 1060, in _wait_for_tstate_lock
    elif lock.acquire(block, timeout):
KeyboardInterrupt

考えられる原因

内部で実行している jumanpp コマンドの標準入力、標準出力の取り扱いで競合が発生し dead lock のような状態になっている。

考えられる解決策

  1. 利用者が Juman インスタンスをスレッド間で共有せず、スレッドごとで Juman インスタンスを利用する
  2. Juman#analysis を thread safe な実装に変更する
    2-1. 別スレッドからの参照時は subprocess を作り直す実装に変更する
    2-2. そもそも jumanpp を使い回さず Juman#analysis の実行毎に jumanpp コマンドを実行する related #28

jumanの出力が止まったとき無限ループに入る

while True:

EOSを検知してループから抜ける処理だと思われるんですがjumanが長い文章の場合たまに\n\n\nを無限に出力して抜けれなくなる場合がある
ループ回数を入力の文字数などで上限を決めるか同じ文字列が一定数連続したらbreakするなどの処理がないと例外すら出ず止まってしまう

AttributeError: 'NoneType' object has no attribute 'group'

Minimal reproduce code

knp = KNP()
knp.parse(" ")
Traceback (most recent call last):
  File "hoge.py", line 79, in <module>
    knp.parse(" ")
  File "/root/.local/share/virtualenvs/app-4PlAip0Q/lib/python3.8/site-packages/pyknp/knp/knp.py", line 70, in parse
    return self.parse_juman_result(juman_str, juman_format)
  File "/root/.local/share/virtualenvs/app-4PlAip0Q/lib/python3.8/site-packages/pyknp/knp/knp.py", line 97, in parse_juman_result
    return BList(knp_lines, self.pattern, juman_format)
  File "/root/.local/share/virtualenvs/app-4PlAip0Q/lib/python3.8/site-packages/pyknp/knp/blist.py", line 42, in __init__
    self._set_pas(self.juman_format)
  File "/root/.local/share/virtualenvs/app-4PlAip0Q/lib/python3.8/site-packages/pyknp/knp/blist.py", line 78, in _set_pas
    tag.pas = Pas(tag.tag_id, self)
  File "/root/.local/share/virtualenvs/app-4PlAip0Q/lib/python3.8/site-packages/pyknp/knp/pas.py", line 94, in __init__
    self.__set_args(tag_predicate.features.get("格解析結果"), CaseInfoFormat.CASE)
  File "/root/.local/share/virtualenvs/app-4PlAip0Q/lib/python3.8/site-packages/pyknp/knp/pas.py", line 206, in __set_args
    for items in self.__parse_case_analysis_items(analysis_result, case_info_format):
  File "/root/.local/share/virtualenvs/app-4PlAip0Q/lib/python3.8/site-packages/pyknp/knp/pas.py", line 184, in __parse_case_analysis_items
    self.cfid = match.group(1) + ':' + match.group(2)
AttributeError: 'NoneType' object has no attribute 'group'

KNPの出力

$ echo " " | jumanpp | knp -tab
# S-ID:1 KNP:5.0-165d699 DATE:2020/09/11 SCORE:-23.04048
* -1D <文頭><文末><受けNONE><用言:判><体言止><レベル:C><区切:5-5><ID:(文末)><提題受:30><主節><状態述語><正規化代表表記:><主辞代表表記:>
+ -1D <文頭><文末><受けNONE><用言:判><体言止><レベル:C><区切:5-5><ID:(文末)><提題受:30><主節><状態述語><判定詞句><正規化代表表記:><主辞代表表記:><用言代表表記:><CF_NOT_FOUND><節-区切><節-主辞><時制:非過去><格解析結果::判0><標準用言代表表記:>
\ \ \ 特殊 1 空白 6 * 0 * 0 "代表表記: / " <代表表記:></><正規化代表表記:><記英数カ><英記号><記号><文頭><文末><自立><内容語><タグ単位始><文節始><文節主辞><用言表記先頭><用言表記末尾><用言意味表記末尾>
EOS

More cases

knp.parse("末尾に半角スペースはエラー ") # AttributeError: 'NoneType' object has no attribute 'group'
knp.parse(" 文先頭に半角スペースはエラーなし")
knp.parse("文中に半角スペース エラーなし")
knp.parse(" !") # AttributeError: 'NoneType' object has no attribute 'group'
knp.parse("! !") # AttributeError: 'NoneType' object has no attribute 'group'

JUMAN++ 1.02
KNP masterブランチの最新版 ku-nlp/knp@165d699
pyknp 0.4.5
Python 3.8.5
OS Ubuntu 20.04

Maximum byte size of input string

What is the maximum byte size for input string for Morpheme class? I am getting the following error:

Traceback (most recent call last):
  File "generate_vectors.py", line 207, in <module>
    tokenize_text(JA_WIKI_TEXT_FILENAME, JA_WIKI_TEXT_TOKENS_FILENAME)
  File "generate_vectors.py", line 139, in tokenize_text
    tokenized_text = ' '.join(get_words(text, juman_pp=True))
  File "generate_vectors.py", line 114, in get_words
    result = jumanpp.analysis(text)
  File "/media/nicoindia/Ubuntu/miniconda3/envs/gfoot/lib/python3.7/site-packages/pyknp/juman/juman.py", line 91, in analysis
    return self.juman(input_str, juman_format)
  File "/media/nicoindia/Ubuntu/miniconda3/envs/gfoot/lib/python3.7/site-packages/pyknp/juman/juman.py", line 78, in juman
    result = MList(self.juman_lines(input_str), juman_format)
  File "/media/nicoindia/Ubuntu/miniconda3/envs/gfoot/lib/python3.7/site-packages/pyknp/juman/mlist.py", line 29, in __init__
    mrph = Morpheme(line, mid, juman_format)
  File "/media/nicoindia/Ubuntu/miniconda3/envs/gfoot/lib/python3.7/site-packages/pyknp/juman/morpheme.py", line 80, in __init__
    self._parse_spec(spec.strip("\n"))
  File "/media/nicoindia/Ubuntu/miniconda3/envs/gfoot/lib/python3.7/site-packages/pyknp/juman/morpheme.py", line 143, in _parse_spec
    self.hinsi_id = int(parts[4])
ValueError: invalid literal for int() with base 10: 'input'

I have found out that this error is caused because the input string length is greater than maximum length allowed. In morpheme.py, in _parse_spec, if I use print(spec) then I get the following string

'InvalidParameter byte size of input string (12797) is greater than maximum allowed (4096)'

Is there a way to change the maximum length allowed?

Unable to tokenize sentences that start with at mark

Tokenization fails when a sentence starts with "@".
This doesn't seem to be an issue when jumanpp is called through subprocess or rhoknp.

To reproduce:

import subprocess
from pyknp import Juman
import rhoknp


def subprocess_tokenize(ja_sent):
    command = f"echo {ja_sent} | jumanpp --segment"
    return subprocess.run(command, shell=True, capture_output=True, text=True).stdout.strip()


def pyknp_tokenize(ja_sent):
    jumanpp = Juman()
    return " ".join([mrph.midasi for mrph in jumanpp.analysis(ja_sent).mrph_list()])


def rhoknp_tokenize(ja_sent):
    jumanpp = rhoknp.Jumanpp()
    return " ".join([str(morph) for morph in jumanpp.apply(ja_sent).morphemes])


def main():
    ja_sent = "@@抄録@@移動アドホックネットワークのための適応経路チューニングスキーム「OR2」を提案した。"
    ja_sent = "@ECOVISIONの導入効果は以下の通りである。"

    ja_sent = pyknp_tokenize(ja_sent)
    print(ja_sent)


if __name__ == "__main__":
    main()

Standard error:

Traceback (most recent call last):
  File "error.py", line 30, in <module>
    main()
  File "error.py", line 25, in main
    ja_sent = pyknp_tokenize(ja_sent)
  File "error.py", line 13, in pyknp_tokenize
    return " ".join([mrph.midasi for mrph in jumanpp.analysis(ja_sent).mrph_list()])
  File "/path_to_venv/lib/python3.8/site-packages/pyknp/juman/juman.py", line 98, in analysis
    return self.juman(input_str, juman_format)
  File "/path_to_venv/venv/lib/python3.8/site-packages/pyknp/juman/juman.py", line 85, in juman
    result = MList(self.juman_lines(input_str), juman_format)
  File "/path_to_venv/venv/lib/python3.8/site-packages/pyknp/juman/mlist.py", line 26, in __init__
    self._mrph[-1].push_doukei(Morpheme(line[2:], mid, juman_format))
IndexError: list index out of range

UnicodeDecodeError: 'cp932'

Hi,
I am just trying this py interface to analyze Japanese text semantics, but got the following issue while trying to install with pip.

Environment: Windows, VS code, python 3.8.5, pip working properly.

pip install pyknp
Collecting pyknp
Using cached pyknp-0.4.5.zip (43 kB)
ERROR: Command errored out with exit status 1:
command: 'e:\program files\python38\python.exe' -c 'import sys, setuptools, tokenize; sys.argv[0] = '"'"'C:\Users\XXX\AppData\Local\Temp\pip-install-7i0yz2y7\pyknp\setup.py'"'"'; file='"'"'C:\Users\XXX\AppData\Local\Temp\pip-install-7i0yz2y7\pyknp\setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(file);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, file, '"'"'exec'"'"'))' egg_info --egg-base 'C:\Users\XXX\AppData\Local\Temp\pip-pip-egg-info-mimk6u5_'
cwd: C:\Users\XXX\AppData\Local\Temp\pip-install-7i0yz2y7\pyknp
Complete output (5 lines):
Traceback (most recent call last):
File "", line 1, in
File "C:\Users\XXX\AppData\Local\Temp\pip-install-7i0yz2y7\pyknp\setup.py", line 16, in
long_description = f.read()
UnicodeDecodeError: 'cp932' codec can't decode byte 0x87 in position 115: illegal multibyte sequence
----------------------------------------
ERROR: Command errored out with exit status 1: python setup.py egg_info Check the logs for full command output.

New pypi package release?

It's been more than one year since the last pypi package release.
Do you have any plan to release new version?

ValueError: invalid literal for int() with base 10: '!!'

Minimal reproduce code

knp = KNP()
knp.parse("!!")
Traceback (most recent call last):
  File "hoge.py", line 99, in <module>
    knp.parse("!!")
  File "/root/.local/share/virtualenvs/app-4PlAip0Q/lib/python3.8/site-packages/pyknp/knp/knp.py", line 70, in parse
    return self.parse_juman_result(juman_str, juman_format)
  File "/root/.local/share/virtualenvs/app-4PlAip0Q/lib/python3.8/site-packages/pyknp/knp/knp.py", line 97, in parse_juman_result
    return BList(knp_lines, self.pattern, juman_format)
  File "/root/.local/share/virtualenvs/app-4PlAip0Q/lib/python3.8/site-packages/pyknp/knp/blist.py", line 39, in __init__
    self.parse(spec)
  File "/root/.local/share/virtualenvs/app-4PlAip0Q/lib/python3.8/site-packages/pyknp/knp/blist.py", line 116, in parse
    synnodes = SynNodes(string)
  File "/root/.local/share/virtualenvs/app-4PlAip0Q/lib/python3.8/site-packages/pyknp/knp/syngraph.py", line 21, in __init__
    self.tagids = [int(n) for n in tagid.split(',')]
  File "/root/.local/share/virtualenvs/app-4PlAip0Q/lib/python3.8/site-packages/pyknp/knp/syngraph.py", line 21, in <listcomp>
    self.tagids = [int(n) for n in tagid.split(',')]
ValueError: invalid literal for int() with base 10: '!!'

KNP output

$ echo '!!' | jumanpp | knp -tab
# S-ID:1 KNP:5.0-165d699 DATE:2020/09/23 SCORE:-23.04048
* -1D <文頭><文末><体言><用言:判><体言止><レベル:C><区切:5-5><ID:(文末)><裸名詞><提題受:30><主節><状態述語><正規化代表表記:!!/!!><主辞代表表記:!!/!!>
+ -1D <文頭><文末><体言><用言:判><体言止><レベル:C><区切:5-5><ID:(文末)><裸名詞><提題受:30><主節><状態述語><判定詞句><名詞項候補><先行詞候補><正規化代表表記:!!/!!><主辞代表表記:!!/!!><用言代表表記:!!/!!><CF_NOT_FOUND><節-区切><節-主辞><時制:非過去><格解析結果:!!/!!:判0><標準用言代表表記:!!/!!>
!! !! !! 名詞 6 普通名詞 1 * 0 * 0 "品詞推定:名詞 疑似代表表記 代表表記:!!/!! 品詞変更:!!-!!-!!-15-1-0-0" <品詞推定:名詞><疑似代表表記><代表表記:!!/!!><正規化代表表記:!!/!!><品詞変更:!!-!!-!!-15-1-0-0-"品詞推定:名詞 疑似代表表記 代表表記:!!/!!"><品曖-その他><未知語><記英数カ><英記号><記号><名詞相当語><文頭><文末><表現文末><自立><内容語><タグ単位始><文節始><文節主辞><用言表記先頭><用言表記末尾><用言意味表記末尾>
EOS

JUMAN++ 1.02
KNP current HEAD of master ku-nlp/knp@165d699
pyknp current HEAD of master 6ba00ea
Python 3.8.5
OS Ubuntu 20.04

Unbalanced/hanging double quotes allows weird midasi

from pyknp import Juman
juman = Juman(jumanpp=False)

result = juman.analysis('"test').mrph_list()
print(" :: ".join(r.midasi for r in result)) # --> '"test "test'

result = juman.analysis('"test "').mrph_list()
print(" :: ".join(r.midasi for r in result)) # --> '"test "test' :: '\\ ' :: '"'

Something like

if sum(1 for c in input_str if c == '"') % 2 != 0:
    input_str = "".join(
        reversed("".join(reversed(input_str)).replace('"', "", 1))
    )

could be used to clean strings with unpaired quotes before calling Juman.analyze(), but I don't find it satisfactory. It may just be an example of "garbage in, garbage out".

The problem is in morpheme.py: Morpheme._parse_spec() where quotes are handled in these nested if-statements (starting line 125):

                # If "\"" proceeds " ", it would be not inside_quotes, but "\"".
                if inside_quotes and char == " " and part == '"':
                    inside_quotes = False

                if part != "" and char == " " and not inside_quotes:
                    if part.startswith('"') and part.endswith('"') and len(part) > 1:
                        print(f"APPENDING PART0 {part}")
                        parts.append(part[1:-1])
                    else:
                        print(f"APPENDING PART1 {part}")
                        parts.append(part)
                    part = ""
                else:
                    print(f"ADDING CHAR TO PART {part} + {char}")
                    part += char

The expected behaviour (according only to me), should be '"test' and '"test' :: '\\ ' :: '"'.

述語項構造にNEの情報が付与されている場合,パースに失敗する

これはエラーとなります.

$ echo '1,000円とお得な値段です。' |  jumanpp|knp -tab -ne-crf -anaphora | knp-drawtree
Traceback (most recent call last):
  File "/home/username/.local/bin/knp-drawtree", line 91, in <module>
    main()
  File "/home/username/.local/bin/knp-drawtree", line 87, in main
    draw_trees(inf, outf, opts.lattice_format)
  File "/home/username/.local/bin/knp-drawtree", line 65, in draw_trees
    bl = pyknp.BList(u"".join(lines), juman_format=juman_format)
  File "/home/username/.local/lib/python3.7/site-packages/pyknp/knp/blist.py", line 42, in __init__
    self._set_pas(self.juman_format)
  File "/home/username/.local/lib/python3.7/site-packages/pyknp/knp/blist.py", line 78, in _set_pas
    tag.pas = Pas(tag.tag_id, self)
  File "/home/username/.local/lib/python3.7/site-packages/pyknp/knp/pas.py", line 91, in __init__
    self.__set_args(tag_predicate.features.get("述語項構造"), CaseInfoFormat.PASv42)
  File "/home/username/.local/lib/python3.7/site-packages/pyknp/knp/pas.py", line 205, in __set_args
    for items in self.__parse_case_analysis_items(analysis_result, case_info_format):
  File "/home/username/.local/lib/python3.7/site-packages/pyknp/knp/pas.py", line 201, in __parse_case_analysis_items
    yield self.__parse_case_info_format(items, case_info_format)
  File "/home/username/.local/lib/python3.7/site-packages/pyknp/knp/pas.py", line 160, in __parse_case_info_format
    sdist = int(items[3])
ValueError: invalid literal for int() with base 10: '5;ニ'
$ echo '1,000円とお得な値段です。' |  jumanpp|knp -tab -anaphora | knp-drawtree

ではエラーになりません.

-ne-crf をつけると以下のように, MON:が付与されるのが原因です.

+ 2D <BGH:得だ/とくだ><連体修飾><用言:形><係:連格><レベル:B-><区切:0-5><ID:(形判連体)><連体節><状態述語><正規化代表表記:得だ/とくだ><主辞代表表記:得だ/とくだ><用言
代表表記:得だ/とくだ><時制:非過去><格関係2:ガ:値段><標準用言代表表記:得だ/とくだ><EID:6><述語項構造:得だ/とくだ:形2:ガ2/E/著者/2/-1/0;ガ/N/値段/0/2/7;ガ/N/MON:1,000円/0/0/5;ニ/E/不特定-その他/2/-1/3;ト/-/-/-/-/-;デ/-/-/-/-/-;カラ/-/-/-/-/-;ヨリ/-/-/-/-/-;マデ/-/-/-/-/-;時間/-/-/-/-/-;外の関係/-/-/-/-/-;修飾/-/-/-/-/-;ニムケ
ル/-/-/-/-/-;ニクラベル/-/-/-/-/-><省略解析信頼度:0.000><ガ格省略解析信頼度:0.000>

pas.pyの以下の正規表現を修正する必要があります.

arg_pat = re.compile(r';(.+?/[CNODEU]/.+?(?:/(?:-?\d*)){3})'

修正方法までは調べきれていませんが,ひとまず報告させていただきます.

Test knp,Exception: Error: ;; Too many mrph ( ...)!

I use this code to test knp on Linux:

#!/usr/bin/env python3
from pyknp import KNP
import csv

knp = KNP()  
result = knp.parse("<br>今回のTOP報告では、「R検定」「R検定によってもたらされる効果」を中心にして解説をしていきます。<br><br>1.R検定とは<br>まず、「R検定」とは何であるかを説明します。「R検定」とは、「AIの知識」と「マネジメントの知識」を問いながら、それらの知識を、どのように実践の戦略に活かしていくのかの能力を検定する資格試験の事です。ちなみに、試験の内容としては、AIの基礎的な知識だけでなく、流通や小売に関するマネジメント知識の問題も出題していきます。具体的な流通・小売のマネジメント知識としては、サプライチューンマネジメント、カテゴリーマネジメント、ショッパーマーケティングですが、R検定ではこれらのマネジメント手法が、AIと融合していく事で、どのような効果が得られるのかも問題として出題していこうと考えています。")
title = [['キーワード','原形','品詞','品詞細分類']]
top_list=[]
every_row = result.mrph_list()
for i in every_row:
    top_list.append([i.midasi,i.genkei,i.hinsi,i.bunrui])
    # print(i.midasi,i.genkei,i.hinsi, i.bunrui,sep='\t')
with open(r'/opt/knp.csv', 'w', newline='', encoding='utf-8') as f:
    writer = csv.writer(f)
    writer.writerows(title)
    writer.writerows(top_list)

The error message is:

Exception: Error: ;; Too many mrph ( ...)!

All the wrong information is like this:

File "/root/anaconda3/lib/python3.6/site-packages/pyknp/knp/knp.py", line 79, in parse return BList(knp_lines, self.pattern) File "/root/anaconda3/lib/python3.6/site-packages/pyknp/knp/blist.py", line 40, in __init__ self.parse(spec) File "/root/anaconda3/lib/python3.6/site-packages/pyknp/knp/blist.py", line 106, in parse raise Exception("Error: %s" % string) Exception: Error: ;; Too many mrph ( ...)!

Where is wrong?

How to cite pyknp?

How should we cite the programme pyknp in academic articles, books, and presentations? I would be really grateful if you would provide the citation info with a BibTeX format for us.

PASにおける「不特定:人」問題

照応解析で照応先が「不特定:人」の場合、下記のガ格のような出力を読み込むため、Argument.tid=-1となる。

<述語項構造:使う/つかう:動24:ガ/E/不特定:人/-1/-1/2;ヲ/C/両手/0/1/4;ニ/U/-/-/-/-;ガ2/U/-/-/-/-;時間/U/-/-/-/->

すると、 rep = self.tag_list[tid].repname で文末の基本句を選択してしまう。

照応解析(anaphora)オプションを付けると前の入力を読み続ける

knp本体の問題な気もしてますがanaphoraオプションを付けると複数文の結果を見ようとするのか前の入力内容をflushしないで延々と関係を見に行くケースがある
そのため同じ単語を多く含む文章郡を何度か投入するとEntity "%s" mentiond too many times!で落ちる

pas.cfidがNoneになることがある

以下の入力を与えるとpas.cfidNoneになってしまいます

$  knp -v
knp 5.0 (Revision.165d699a on 2020-04-27)

$  echo '束の間ですがゲームします。' | jumanpp | knp -tab -anaphora | knp-drawtree
# S-ID: 1
 束の間nですcがp┐       /Traceback (most recent call last):
  File "/home/username/.local/bin/knp-drawtree", line 7, in <module>
    exec(compile(f.read(), __file__, 'exec'))
  File "/home/username/workspace/3rd/pyknp/pyknp/scripts/knp-drawtree", line 91, in <module>
    main()
  File "/home/username/workspace/3rd/pyknp/pyknp/scripts/knp-drawtree", line 87, in main
    draw_trees(inf, outf, opts.lattice_format)
  File "/home/username/workspace/3rd/pyknp/pyknp/scripts/knp-drawtree", line 66, in draw_trees
    draw_tree(bl, outf)
  File "/home/username/workspace/3rd/pyknp/pyknp/scripts/knp-drawtree", line 33, in draw_tree
    outf.write(pas.cfid)
TypeError: write() argument must be str, not None

UnicodeDecodeError: 'utf-8' codec can't decode byte 0x82 in position 7: invalid start byte

I use this code to test pyknp.

from pyknp import Juman
jumanpp = Juman()  # default is JUMAN++: Juman(jumanpp=True). if you use JUMAN, use Juman(jumanpp=False)
result = jumanpp.analysis("お疲れさまです。今週のトップ報告を行います")
for mrph in result.mrph_list(): # 各形態素にアクセス
    print("見出し:%s, 読み:%s, 原形:%s, 品詞:%s, 品詞細分類:%s, 活用型:%s, 活用形:%s, 意味情報:%s, 代表表記:%s" \
            % (mrph.midasi, mrph.yomi, mrph.genkei, mrph.hinsi, mrph.bunrui, mrph.katuyou1, mrph.katuyou2, mrph.imis, mrph.repname))

The error message is:

UnicodeDecodeError: 'utf-8' codec can't decode byte 0x82 in position 7: invalid start byte

jumanpp 2.0.0-rc3でpyknp/juman/juman.pyのテストに失敗する

jumanpp 2.0.0-rc3pyknp/juman/juman.pyのテストに失敗します

$ jumanpp -v
Juman++ Version: 2.0.0-rc3 / Dictionary: 20190731-356e143 / LM: K:20190430-7d143fb L:20181122-b409be68 F:20171214-9d125

$  python3 ./pyknp/juman/juman.py
.F.F.....F
======================================================================
FAIL: test_dquo (__main__.JumanTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "./pyknp/juman/juman.py", line 148, in test_dquo
    self.assertEqual(''.join(mrph.midasi for mrph in result), test_str)
AssertionError: '”最高”の気分' != '"最高"の気分'
- ”最高”の気分
? ^  ^
+ "最高"の気分
? ^  ^


======================================================================
FAIL: test_eos2 (__main__.JumanTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "./pyknp/juman/juman.py", line 143, in test_eos2
    self.assertEqual(''.join(mrph.midasi for mrph in result), test_str.replace(" ", "\ "))
AssertionError: 'Canon\u3000EOS\u300080D買った' != 'Canon\\ EOS\\ 80D買った'
- Canon EOS 80D買った
?      ^   ^
+ Canon\ EOS\ 80D買った
?      ^^   ^^


======================================================================
FAIL: test_whitespace_jumanpp (__main__.JumanTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "./pyknp/juman/juman.py", line 132, in test_whitespace_jumanpp
    self.assertEqual(''.join(mrph.midasi for mrph in result), test_str.replace(" ", "\ "))
AssertionError: '半角\u3000スペース' != '半角\\ スペース'
- 半角 スペース
?   ^
+ 半角\ スペース
?   ^^


----------------------------------------------------------------------
Ran 10 tests in 0.177s

FAILED (failures=3)

Cannot get result of knp.parse()

Python version 3.6
OS: windows10 or macos 10.14.1
Problem.
run the sample code like
from pyknp import KNP knp = KNP() # Default is JUMAN++. If you use JUMAN, use KNP(jumanpp=False) result = knp.parse("下鴨神社の参道は暗かった。"
and the program idle at the function of parse() forever.
no error and no crash.

consideration of parse process

問題

以下のような入力ケースで、顔文字の中にスペースが存在するため、パースができない不具合がある (jumanpp 2.0.0-rc3)

こんにちは(^ ^)
こんにちは こんにちは こんにちは 感動詞 12 * 0 * 0 * 0 "代表表記:こんにちは/こんにちは"
(^ ^) (^ ^) (^ ^) 特殊 1 記号 5 * 0 * 0 "代表表記:顔文字/顔文字 顔文字"
EOS

解決策1

  • \t の入力を想定せず簡易な実装に留める場合はjumanppのプロセスを呼び出す際に -s 1 オプションを付与する。

解決策2

  • protobuf出力でjumanppがビルドされているとき、protobuf経由でパースする、

An utility function to read files in KNP format

To read files in KNP format, users should implement this kind of codes by themselves.

from pyknp import KNP

knp = KNP()
filename = 'result.knp'

blists = []
with open(filename) as f:
    chunk = ''
    for line in f:
        chunk += line
        if line.strip() == 'EOS':
            blists.append(knp.result(chunk))
            chunk = ''

My suggestion is to provide a function to perform this process.

from pyknp import KNP
from pyknp.utils import read_knp_file  # the proposed function

knp = KNP()
filename = 'result.knp'

blists = []
with open(filename) as f:
    for chunk in read_knp_file(f):
        blists.append(knp.result(chunk))

KNP seems to ignore the `timeout` option

KNP module seems to ignore the timeout option. In the following example, I set the timeout period to 0 for a time-consuming process (option='-tab -anaphora -semantic-head') with a long sentence. Although I gave no time for the parser to process that sentence, the parse is done and it takes 2--3 seconds.

#!/usr/bin/env python3.6
# coding: utf-8

from pyknp import KNP
import time

# Default is JUMAN++. If you use JUMAN, use KNP(jumanpp=False)
knp = KNP(option='-tab -anaphora -semantic-head', timeout=0)

start = time.time()

"""
Source of the to-be-parsed sentence:
https://ja.uncyclopedia.info/wiki/%E8%AA%AD%E3%81%BF%E3%81%AB%E3%81%8F%E3%81%84%E6%96%87%E7%AB%A0/%E6%96%87%E3%81%AE%E6%A7%8B%E9%80%A0%E3%81%8C%E5%8E%9F%E5%9B%A0%E3%81%A7%E8%AA%AD%E3%81%BF%E3%81%AB%E3%81%8F%E3%81%84%E6%96%87%E7%AB%A0#.E5.8F.A5.E8.AA.AD.E7.82.B9.E3.81.8C.E5.B0.91.E3.81.AA.E3.81.99.E3.81.8E.E3.82.8B.E6.96.87.E7.AB.A0
"""

result = knp.parse(
    "このような句読点が少ない文章は文章の流れをつかみにくく読みづらいという欠点を持つが書く人はこの方が早く書けることもあるので「句読点が多い文章」よりは出現しやすくさらにパソコンやワープロなどで書き印刷する場合は紙のスペースの節約になり省資源にも多少は貢献すると思われるのみならず最近の女子高生が携帯電話からブログに書いた文章においては句読点がないのが普通だったりするんだけれども読みやすさ第一を心がける場合においては句読点をつけすぎなさすぎないことはやめましょう。")

elapsed_time = time.time() - start

print("文節")
for bnst in result.bnst_list():  # 各文節へのアクセス
    print("\tID:%d, 見出し:%s, 係り受けタイプ:%s, 親文節ID:%d, 素性:%s"
          % (bnst.bnst_id, "".join(mrph.midasi for mrph in bnst.mrph_list()), bnst.dpndtype, bnst.parent_id, bnst.fstring))

print("基本句")
for tag in result.tag_list():  # 各基本句へのアクセス
    print("\tID:%d, 見出し:%s, 係り受けタイプ:%s, 親基本句ID:%d, 素性:%s"
          % (tag.tag_id, "".join(mrph.midasi for mrph in tag.mrph_list()), tag.dpndtype, tag.parent_id, tag.fstring))

print("形態素")
for mrph in result.mrph_list():  # 各形態素へのアクセス
    print("\tID:%d, 見出し:%s, 読み:%s, 原形:%s, 品詞:%s, 品詞細分類:%s, 活用型:%s, 活用形:%s, 意味情報:%s, 代表表記:%s"
          % (mrph.mrph_id, mrph.midasi, mrph.yomi, mrph.genkei, mrph.hinsi, mrph.bunrui, mrph.katuyou1, mrph.katuyou2, mrph.imis, mrph.repname))

print(round(elapsed_time, 2))

The option appears to be merely initialised in the definition but no function seems to take timeout as its argument. Would you mind rechecking here?

IndexError caused

When I parse 「こんにちは、世界」を、表示する; with KNP using pyknp, I get the following error:

$ cat main_.py 
from pyknp import KNP

knp = KNP()
knp.parse('「こんにちは、世界」を、表示する;')
$ python main_.py
Traceback (most recent call last):
  File "main_.py", line 4, in <module>
    knp.parse('「こんにちは、世界」を、表示する;')
  File "path/to/pyknp/knp/knp.py", line 83, in parse
    return BList(knp_lines, self.pattern, juman_format)
  File "path/to/pyknp/knp/blist.py", line 43, in __init__
    self._setPAS(juman_format)
  File "path/to/pyknp/knp/blist.py", line 79, in _setPAS
    tag.pas = Pas(tag.tag_id, self)
  File "path/to/pyknp/knp/pas.py", line 93, in __init__
    self.__set_args(tag_predicate.features.get("格解析結果"), CaseInfoFormat.CASE)
  File "path/to/pyknp/knp/pas.py", line 186, in __set_args
    for items in self.__parse_case_analysis_items(analysis_result, case_info_format):
  File "path/to/pyknp/knp/pas.py", line 181, in __parse_case_analysis_items
    yield self.__parse_case_info_format(items, case_info_format)
  File "path/to/pyknp/knp/pas.py", line 137, in __parse_case_info_format
    tid = int(items[3])
IndexError: list index out of range

Cause

When I parse 「こんにちは、世界」を、表示する; with KNP using CLI, I get the following output:

$ echo "「こんにちは、世界」を、表示する;" | jumanpp|knp -tab
# S-ID:1 KNP:4.20-CF1.1 DATE:2020/05/02 SCORE:-1064.74912
* 1D <文頭><読点><括弧始><引用内文頭><感動詞><修飾><係:連用><区切:0-4><連用要素><連用節><正規化代表表記:こんにちは/こんにちは><主辞代表表記:こんにちは/こんにちは>
+ 1D <文頭><読点><括弧始><引用内文頭><感動詞><修飾><係:連用><区切:0-4><連用要素><連用節><正規化代表表記:こんにちは/こんにちは>
「 「 「 特殊 1 括弧始 3 * 0 * 0 NIL <文頭><記英数カ><英記号><記号><括弧始><括弧><接頭><非独立接頭辞><タグ単位始><文節始>
こんにちは こんにちは こんにちは 感動詞 12 * 0 * 0 * 0 "代表表記:こんにちは/こんにちは" <代表表記:こんにちは/こんにちは><正規化代表表記:こんにちは/こんにちは><かな漢字><ひらがな><自立><内容語><文節主辞>
、 、 、 特殊 1 読点 2 * 0 * 0 NIL <英記号><記号><述語区切><付属>
* 2D <ヲ><読点><括弧終><助詞><引用内文末><体言><係:ヲ格><並キ:名:&ST:4.0&&ヲ><区切:0-4><読点並キ><並列タイプ:?><提題受:30><格要素><連用要素><正規化代表表記:世界/せかい><主辞代表表記:世界/せかい><並列類似度:-100.000>
+ 2D <ヲ><読点><括弧終><助詞><引用内文末><体言><係:ヲ格><並キ:名:&ST:4.0&&ヲ><区切:0-4><読点並キ><並列タイプ:?><提題受:30><格要素><連用要素><名詞項候補><先行詞候補><正規化代表表記:世界/せかい><解析格:ヲ>
世界 せかい 世界 名詞 6 普通名詞 1 * 0 * 0 "代表表記:世界/せかい カテゴリ:場所-その他" <代表表記:世界/せかい><カテゴリ:場所-その他><正規化代表表記:世界/せかい><漢字><かな漢字><名詞相当語><自立><内容語><タグ単位始><文節始><文節主辞>
」 」 」 特殊 1 括弧終 4 * 0 * 0 NIL <記英数カ><英記号><記号><括弧終><括弧><述語区切><付属>
を を を 助詞 9 格助詞 1 * 0 * 0 NIL <かな漢字><ひらがな><付属>
、 、 、 特殊 1 読点 2 * 0 * 0 NIL <英記号><記号><述語区切><付属>
* 3D <サ変><サ変動詞><連体修飾><用言:動><係:連格><レベル:B><区切:0-5><ID:(動詞連体)><連体節><動態述語><正規化代表表記:表示/ひょうじ><主辞代表表記:表示/ひょうじ>
+ 3D <サ変動詞><連体修飾><用言:動><係:連格><レベル:B><区切:0-5><ID:(動詞連体)><連体節><動態述語><サ変><正規化代表表記:表示/ひょうじ><用言代表表記:表示/ひょうじ><時制-未来><格関係1:ヲ:世界><格関係3:ガ:;><格解析結果:表示/ひょうじ:動2:ガ/N/;/3/0/1;ヲ/C/世/-/-/-;時間/U/-/-/-/-;外の関係/U/-/-/-/-;ノ/U/-/-/-/-;修飾/U/-/-/-/-;ニヨル/U/-/-/-/-;トスル/U/-/-/-/-;ニツク/U/-/-/-/-;ニモトヅク/U/-/-/-/-;ニアワセル/U/-/-/-/-;ニタイスル/U/-/-/-/-;ニオク/U/-/-/-/->
表示 ひょうじ 表示 名詞 6 サ変名詞 2 * 0 * 0 "代表表記:表示/ひょうじ カテゴリ:抽象物" <代表表記:表示/ひょうじ><カテゴリ:抽象物><正規化代表表記:表示/ひょうじ><漢字><かな漢字><名詞相当語><サ変><サ変動詞><自立><内容語><タグ単位始><文節始><文節主辞>
する する する 動詞 2 * 0 サ変動詞 16 基本形 2 "代表表記:する/する 付属動詞候補(基本) 自他動詞:自:成る/なる" <代表表記:する/する><付属動詞候補(基本)><自他動詞:自:成る/なる><正規化代表表記:する/する><とタ系連用テ形複合辞><かな漢字><ひらがな><活用語><付属>
* -1D <文末><体言><用言:判><体言止><レベル:C><区切:5-5><ID:(文末)><裸名詞><提題受:30><主節><状態述語><正規化代表表記:;/;><主辞代表表記:;/;>
+ -1D <文末><体言><用言:判><体言止><レベル:C><区切:5-5><ID:(文末)><裸名詞><提題受:30><主節><状態述語><判定詞><名詞項候補><先行詞候補><正規化代表表記:;/;><用言代表表記:;/;><時制-無時制><解析連格:ガ><格解析結果:;/;:判0:ガ/U/-/-/-/->
; ; ; 名詞 6 普通名詞 1 * 0 * 0 "品詞推定:名詞 疑似代表表記 代表表記:;/; 品詞変更:;-;-;-15-1-0-0" <品詞推定:名詞><疑似代表表記><代表表記:;/;><正規化代表表記:;/;><文末><表現文末><品詞変更:;-;-;-15-1-0-0-"品詞推定:名詞 疑似代表表記 代表表記:;/;"><品曖-その他><未知語><記英数カ><英記号><記号><名詞相当語><自立><内容語><タグ単位始><文節始><文節主辞>
EOS

It seems that ガ/N/; in + 3D ...<格解析結果:表示/ひょうじ:動2:ガ/N/;...> is not parsed well in the following place:

pyknp/pyknp/knp/pas.py

Lines 133 to 140 in ab2dfbe

if case_info_format == CaseInfoFormat.CASE:
mycase = items[0]
caseflag = items[1]
midasi = items[2]
tid = int(items[3])
sdist = int(items[4])
sid = items[5]
eid = None

Environment

$ cat /etc/os-release
NAME="Ubuntu"
VERSION="18.04.4 LTS (Bionic Beaver)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 18.04.4 LTS"
VERSION_ID="18.04"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=bionic
UBUNTU_CODENAME=bionic
$ python --version
Python 3.6.9
$ pip show pyknp
Name: pyknp
Version: 0.4.1
Summary: Python module for JUMAN/KNP.
Home-page: https://github.com/ku-nlp/pyknp
Author: Kurohashi-Kawahara Lab, Kyoto Univ.
Author-email: [email protected]
License: See COPYING
Location: ***
Requires: six
Required-by:
$ jumanpp -v
JUMAN++ 1.02 
$ knp -v
knp 4.20

複数文にまたがる照応解析への対応

エンティティが文外にある場合に eid -> tid を正確に対応付けるには、 eid が含まれる sid を辿って該当する tid を取得しなければならず、Blist 同士の対応関係が必要となる。

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.