Анализатор¶
Analyzer(path=None)
Морфологический анализатор: для словоформы находит по словарю OpenCorpora все варианты разбора - начальную форму, часть речи и признаки Universal Dependencies - и упорядочивает их по вероятности. Словарь загружается при создании первого анализатора: анализаторы с тем же файлом словаря в процессе делят его, поэтому новый анализатор создается мгновенно. Последний загруженный словарь остается в процессе и без анализаторов, поэтому задачи пула процессов и анализатор, созданный на один вызов, не загружают словарь заново.
Исключения:
FileNotFoundError- нет файла словаря;OSError- файл словаря не читается: нет доступа, путь указывает на каталог;ValueError- файл не словарь ruMorph или поврежден;TypeError- путь, который не строка и неPathLike.
from rumorph import Analyzer
morph = Analyzer()
morph.analyze("стали")[0]
Analysis(word='стали', lemma='стать', pos='VERB', feats='Aspect=Perf|Mood=Ind|Number=Plur|Tense=Past|VerbForm=Fin|Voice=Mid', labels='intr', prob=0.9753459013836056, source='dictionary')
Параметры¶
| Параметр | Тип | По умолчанию | Описание |
|---|---|---|---|
path |
str / PathLike |
None |
Путь к файлу словаря; по умолчанию - словарь из пакета |
Объект хранит путь к словарю в path типа Path, только для чтения. Файл словаря отображается в память: процессы с одним файлом делят его память, поэтому каждый следующий процесс с анализатором занимает около 1,4 МБ. Пока анализатор существует, файл нельзя перезаписывать на месте, а заменить новым файлом можно; в Windows открытый файл не заменяется и не удаляется. Последний загруженный словарь остается открытым и после удаления анализаторов - до загрузки словаря из другого файла или выхода из процесса. Словарь - доверенные данные, как код: загрузка отвергает поврежденный файл, но не любой специально подделанный, поэтому словари из ненадежных источников загружать не стоит.
Методы¶
Разборы словоформы¶
analyze(word)
Разборы словоформы по убыванию вероятности; сумма вероятностей равна 1. Регистр не важен, а буква «е» может обозначать «ё»: analyze("ЕЖ") возвращает разборы словоформы «ёж». Токен, которого нет в словаре, - число, знак, слово латиницей, сокращение - разбирается по правилам, а разборы незнакомого слова кириллицей угадываются по окончанию и по частям. Токен без пробелов и невидимых символов получает хотя бы один разбор: если ничего не подошло - X без признаков.
| Параметр | Тип | По умолчанию | Описание |
|---|---|---|---|
word |
str |
- | Словоформа |
Исключения:
TypeError- слово, которое не строка.
[(a.lemma, a.pos, a.feats.get("Case"), round(a.prob, 3)) for a in morph.analyze("стали")]
[(a.lemma, a.source) for a in morph.analyze("чатботу")][:2]
[('стать', 'VERB', None, 0.975),
('сталь', 'NOUN', 'Gen', 0.011),
('сталь', 'NOUN', 'Nom', 0.005),
('сталь', 'NOUN', 'Dat', 0.003),
('сталь', 'NOUN', 'Loc', 0.003),
('сталь', 'NOUN', 'Acc', 0.003)]
[('чатбот', 'guess'), ('чатбота', 'guess')]
Разборы списка словоформ¶
analyze_many(words)
Разборы каждой словоформы, как у analyze; на списке метод быстрее, чем analyze в цикле.
| Параметр | Тип | По умолчанию | Описание |
|---|---|---|---|
words |
Iterable[str] |
- | Словоформы: список, кортеж, генератор |
Исключения:
TypeError- строка вместо набора слов, слово, которое не строка.
[len(analyses) for analyses in morph.analyze_many(["мама", "мыла", "раму"])]
[1, 4, 2]
Лемматизация¶
lemmatize(words)
Леммы самых вероятных разборов словоформ; токен без разборов возвращается в нижнем регистре.
| Параметр | Тип | По умолчанию | Описание |
|---|---|---|---|
words |
Iterable[str] |
- | Словоформы: список, кортеж, генератор |
Исключения:
TypeError- строка вместо набора слов, слово, которое не строка.
morph.lemmatize("Мы стали друзьями в ковиде".split())
['мы', 'стать', 'друг', 'в', 'ковид']
Словоформа в словаре¶
is_known(word)
Есть ли словоформа в словаре; регистр и «е» вместо «ё», как у analyze, не важны. Слова, разобранные по правилам или угаданные, в словаре не числятся.
| Параметр | Тип | По умолчанию | Описание |
|---|---|---|---|
word |
str |
- | Словоформа |
Исключения:
TypeError- слово, которое не строка.
morph.is_known("Ежи"), morph.is_known("вайб")
(True, False)
Словарь¶
Словарь пакета собран из словаря OpenCorpora: около 3,1 млн словоформ. Вероятности разборов взяты из корпуса OpenCorpora: у слова, написанного через «е» вместо «ё», - частоты написания с «ё», у словоформ, которых в корпусе нет, разборы равновероятны. Словарь распространяется по лицензии CC BY-SA 3.0.
Потоки и процессы¶
Один анализатор можно использовать из нескольких потоков: analyze_many и lemmatize отпускают GIL и разбирают списки параллельно, а в Python 3.14t без GIL параллельно работают и analyze, is_known, inflect и agree. Общий анализатор не медленнее отдельного на каждый поток, поэтому заводить анализатор на поток не нужно. Без GIL потоки упираются в удаление объектов разборов: forms в потоках почти не ускоряется, а analyze_many на длинных списках - слабо, поэтому такие списки лучше разбирать кусками по тысяче-другой слов. Анализатор и разборы сохраняются через pickle, поэтому работают с multiprocessing и joblib: процессы делят отображенный в память словарь, сколько бы разборов они ни получили. Передача разборов между процессами дороже самого разбора, поэтому в процессах лучше получать леммы и поля разборов, а разборы - в потоках.
from concurrent.futures import ThreadPoolExecutor
texts = [["мама", "мыла", "раму"], ["кошки", "ловят", "мышей"]]
with ThreadPoolExecutor(2) as pool:
lemmas = list(pool.map(morph.lemmatize, texts))
lemmas
[['мама', 'мыло', 'рама'], ['кошка', 'ловить', 'мышь']]