# Janome: Japanese morphological analysis with no compiled dependency

> Janome is a Japanese morphological analysis engine written in pure Python, using the MeCab-IPADIC dictionary and statistical model, so it installs with pip and runs anywhere Python does. It suits search, keyword extraction and preprocessing work, and it trades raw speed for that portability.

**mocobeta/janome** — Japanese morphological analysis engine written in pure Python

- Repository: https://github.com/mocobeta/janome
- Website: https://janome.mocobeta.dev
- Stars: 917 · Forks: 55
- Language: Python
- License: Apache-2.0
- Published: 2026-10-20 · Updated: 2026-10-20 · Language: en
- Canonical page: https://hysenlabs.com/projects/mocobeta-janome

## Pure Python, and what that buys you

Janome is a Japanese morphological analysis engine written in pure Python. That phrase is the whole design decision, and it determines almost everything else about the library.

A morphological analyzer for Japanese splits running text into words and labels each one with its part of speech and its features. The hard part is the dictionary and the statistical model that decides, among several possible segmentations, which one a human reader would choose. Janome takes both from MeCab, in the form of the MeCab-IPADIC dictionary and statistical model, and re-implements the analysis in Python.

The payoff is deployment. There is no native library to compile, no version to match against the system and no wheel that only works on one platform. A service that tokenises Japanese can add one pure Python dependency and be done, including on a platform where a C++ extension would be a deployment obstacle.

The cost is speed, and it is a real cost, because the dictionary lookup and the Viterbi search over the lattice run in the interpreter. For interactive work, one user request at a time, that is a trade most projects will accept. For a corpus job that walks millions of characters, it is not.

The project maintains a benchmark directory and a profiler directory at the root of the repository, which tells you the performance question is being worked on rather than ignored.

## Installing costs about 500 MB of memory for the build

The install is a single pip command, and the requirement is Python 3.10 or later.

```bash
pip install janome
```

What makes the install step worth reading is the note above it, which says that it consumes about 500 MB memory for building. That is not the runtime footprint of the library, it is the peak memory the build needs, and it is the kind of number that breaks a small CI container or a memory limited build environment.

The reason is in the packaging. The pyproject file builds with hatchling, and the source distribution explicitly includes the dictionary archive.

```toml
[tool.hatch.build.targets.sdist]
include = [
    "src/janome/**",
    "ipadic/sysdic.zip",
]
```

So the dictionary travels with the package rather than being downloaded and compiled separately, which is exactly the behaviour you want from a pure Python library, and it is also why the build step is heavy.

The distribution channels are the usual ones. The README badges point at the PyPI download statistics and at the conda-forge package, and the documentation site is janome.mocobeta.dev with separate English and Japanese versions. The package metadata declares the version dynamically, read from the version file inside the source tree, so the released version and the source file cannot drift apart.

```toml
[tool.hatch.version]
path = "src/janome/version.py"
pattern = "^JANOME_VERSION = '(?P<version>.+)'$"
```

## The tokenizer prints surface form and linguistic features

The usage example in the README is a REPL session, which is a good way to show what a token actually contains.

```python
>>> from janome.tokenizer import Tokenizer
>>> t = Tokenizer()
>>> for token in t.tokenize('すもももももももものうち'):
...     print(token)
...
すもも 名詞,一般,*,*,*,*,すもも,スモモ,スモモ
```

Two tokens are enough to read the format. The first field is the surface form as it appears in the text, and the following fields are the part of speech and the features, separated by commas, with asterisks where a feature does not apply. The last three fields are the readings in katakana and the base form, which is what you need for reading, indexing or converting text.

The sentence used in the example is a well known Japanese tongue twister, and the segmentation it produces is the interesting part: the analyser has to decide where the boundaries fall, and the example shows it handling repeated identical words correctly rather than greedily consuming them.

The API is deliberately small. You construct a tokenizer and you iterate over tokens, and the objects are plain enough to inspect in a debugger.

## User dictionaries, a compiled variant and an analyzer example

The examples directory is where the extension points become visible. It contains usage.py, usage_analyzer.py, usage_compiled_userdic.py and usage_with_zipimport.py, along with two dictionary files, user_ipadic.csv and user_simpledic.csv.

The two dictionary files tell you the vocabulary story. A user dictionary in this format lets you add or override entries for words the bundled dictionary does not know, which matters in any domain with specialised terms, and having both an IPADIC-based and a simplified variant in the repository suggests the two flavours are used for different situations, with the simplified one being easier to hand edit.

The compiled user dictionary example is the performance option. A user dictionary that is compiled ahead of time, rather than parsed on every run, is the obvious way to keep the cost of a large custom vocabulary off the hot path, and the example name points at that being a supported path rather than a workaround.

The analyzer example is separate from the tokenizer example, so the project distinguishes the two roles: one entry point for the token stream and one for the analysis itself.

The zipimport example is the other end of the pure Python story. If the library can be imported from a zip archive, then a deployment can ship a single file with the code and the dictionary inside it, which is the sort of trick that only works because there is no compiled component to extract.

## Packaging, typing and the dictionary that is excluded from checks

The pyproject file is a good place to see how the project is maintained. The build backend is hatchling, with a custom build hook file named hatch_build.py in the repository root, and the wheel target packages only the src/janome directory while the source distribution additionally carries the dictionary archive.

The development toolchain is declared as a dependency group rather than installed ad hoc: autopep8, coverage, flake8, hatchling, mypy and psutil. The presence of psutil points at the memory question being measured rather than guessed, which is consistent with the 500 MB note in the install instructions.

Two configuration details are worth reading closely because they explain the shape of the codebase.

```toml
[tool.coverage.run]
relative_files = true
omit = ["src/janome/sysdic/*", "tests/*"]

[tool.mypy]

[[tool.mypy.overrides]]
module = "janome.sysdic.*"
ignore_errors = true
```

Both coverage and mypy are told to leave the dictionary directory alone. The dictionary is data, not code, and it is generated rather than written by hand, so type errors and uncovered lines there would be noise. If you are reading the source to understand how the analysis works, knowing that the sysdic directory is generated is the first thing to establish.

The project also keeps a CHANGES.txt, a CONTRIBUTING.md, a release-memo.md, a profiler directory and a uv.lock file, which suggests a working practice where dependencies are pinned for development while the package itself stays dependency free.

## Apache 2.0 for the code, separate terms for the dictionary

The licence line is short but it points at two things. Janome is licensed under the Apache License 2.0 and uses the MeCab-IPADIC dictionary and statistical model, with the details in LICENSE.txt and NOTICE.txt.

The distinction matters in practice. The code you install is Apache 2.0, which is permissive and includes the patent grant. The dictionary and the statistical model come from MeCab and are a separate work with its own terms, which is why a NOTICE file exists next to the licence file at all. A team shipping a product that embeds Janome should read both files rather than assuming the code licence covers the data, and that is a description of what the repository contains rather than advice.

The copyright line reads 2015-2025, Tomoko Uchida, and the acknowledgement section names four contributors. The project is classified as Development Status 4 - Beta in the package metadata, with support for Python 3.10 through 3.13.

On maintenance, the recent releases are 0.5.0 from 2023-07-01 and 0.4.2 from 2022-02-23, while the last push was on 2026-06-07. So the code is still moving, and the version numbers have not moved with it for three years. For a library consumed from a package index, that means the released version you install is old and the repository is ahead of it, and it means you should check the changelog before assuming a bug you hit has been fixed.

## Conclusion

Adopt Janome when you need Japanese tokenisation inside a Python service without a system-level dependency, when your workload is search, filtering, keyword extraction or preprocessing rather than bulk text mining, and when a custom user dictionary is enough to tune the results for your domain. Do not adopt it when you process Japanese at a rate where a native engine is required, because the pure Python implementation pays for its portability in throughput. Before the first install, budget the build memory, since the project states that installing consumes about 500 MB, check that the bundled MeCab-IPADIC dictionary matches your domain, since specialised vocabulary will need a user dictionary, and read NOTICE.txt alongside LICENSE.txt, because the dictionary and the statistical model carry their own terms.

## FAQ

### What is Janome and what does it do with Japanese text?

Janome is a Japanese morphological analysis engine written in pure Python. It splits text into words and labels each token with its surface form, part of speech, features and readings, using the MeCab-IPADIC dictionary and statistical model.

### What does it take to install Janome?

Python 3.10 or later and one pip command, pip install janome. The project warns that the install consumes about 500 MB of memory for building, which matters on a small CI container.

### Can I add my own words to the Janome dictionary?

Yes. The examples directory includes user dictionary files in CSV form, user_ipadic.csv and user_simpledic.csv, and an example named usage_compiled_userdic.py for the compiled variant of a user dictionary.

### What licence applies to Janome and its dictionary?

The code is licensed under the Apache License 2.0, and the project states that it uses the MeCab-IPADIC dictionary and statistical model. Both LICENSE.txt and NOTICE.txt are in the repository and cover the licence details for the code and the dictionary separately.

### Is Janome still being updated?

The last push was on 2026-06-07, so the repository is receiving work, but the tagged releases are 0.5.0 from 2023-07-01 and 0.4.2 from 2022-02-23. Users installing from a package index therefore get a version that is several years behind the repository, so the changelog is worth reading.

## Sources

- [License: Apache-2.0](https://github.com/mocobeta/janome/blob/master/LICENSE)
- [mocobeta/janome on GitHub](https://github.com/mocobeta/janome)
- [Project website](https://janome.mocobeta.dev)
- [README](https://github.com/mocobeta/janome/blob/master/README.md)
- [Releases](https://github.com/mocobeta/janome/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/mocobeta-janome
