Registry / serialization / parsy
library2.2pypypi✓ verified 23d ago

Parsy is an easy-to-use parser combinator library for building parsers in pure Python. It provides a straightforward and Pythonic solution for parsing text without external dependencies, focusing on combining small parsers into complex ones. The library is highly mature and stable, with its current version being 2.2. Releases are active, often aligning with Python version lifecycle updates.

pip install parsy
INSTALL
IMPORT
SIG · PARSY
P
parsy
serializationpythonv2.2
Install
1.6s avg
Import
37ms
Disk
16MB
Pass rate
10/ 10
Env Coverage10 / 10
glibc
3.93.13
musl
3.93.13
Install & Compatibility
Where this runs
tested against v2.2 · pip install
no network on importno background threads
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
musl
py 3.103.95 runs
installs and imports cleanly · install 0.0s · import 0.038s · 17.8MB
glibc
py 3.103.95 runs
installs and imports cleanly · install 1.6s · import 0.036s · 18MB
16MB installed
● package 16MB
Code
Verified usage

Verified import paths — ran on the pinned version, not inferred.

string
from parsy import string
regex
from parsy import regex
generate
from parsy import generate
ParseError
from parsy import ParseError

This quickstart demonstrates basic parser creation using `string` and `regex` primitives, chaining with `then`, and transforming results with `map`. It also showcases the powerful `@generate` decorator for building parsers that yield intermediate results and return a structured object, which is crucial for complex grammars. Error handling with `ParseError` is also illustrated.

from parsy import string, regex, generate, ParseError from datetime import date # Example 1: Simple date parsing using combinators year = regex(r"[0-9]{4}").map(int) month = regex(r"[0-9]{2}").map(int) day = regex(r"[0-9]{2}").map(int) dash = string('-') iso_date_parser = year.then(dash).then(month).then(dash).then(day) try: parsed_date_list = iso_date_parser.parse("2023-10-26") # The default behavior of .then() chain is to return the value of the *last* parser. # To combine results, .map() or @generate is often used. print(f"Simple parse result (last element): {parsed_date_list}") except ParseError as e: print(f"Parse Error: {e}") # Example 2: More complex date parsing using the @generate decorator # This allows you to combine parsed values into a structured result. @generate def full_date_parser(): y = yield year << dash m = yield month << dash d = yield day return date(y, m, d) try: parsed_date_obj = full_date_parser.parse("2023-10-26") print(f"Structured parse result (date object): {parsed_date_obj}") assert parsed_date_obj == date(2023, 10, 26) # Example of a failure full_date_parser.parse("2023/10/26") except ParseError as e: print(f"Parse Error for '2023/10/26': {e}") # Example 3: Using .map to transform simple results weekday_parser = string('Mon') | string('Tue') | string('Wed') # ...and so on weekday_mapping = {'Mon': 'Monday', 'Tue': 'Tuesday', 'Wed': 'Wednesday'} mapped_weekday_parser = weekday_parser.map(lambda s: weekday_mapping.get(s, s)) try: print(f"Mapped weekday: {mapped_weekday_parser.parse('Tue')}") except ParseError as e: print(f"Parse Error: {e}")
Debug
Known issues
breakingParsy version 2.2 (released 2025-09-12) dropped support for Python 3.7 and 3.8, which have reached their End-of-Life (EOL). Users on these Python versions must upgrade to Python 3.9+ or stick to an older `parsy` version (e.g., 2.1 or earlier).
fix
Upgrade Python to 3.9 or newer, or pin `parsy<2.2` in your project dependencies.
affects: >=2.2
gotchaWhile `parsy` provides good basic error messages, for highly detailed, end-user-facing error reporting in complex custom languages (e.g., for a programming language's compiler), significant extra effort might be required to customize the error output, or a more heavyweight parser generator might be a better fit.
fix
For basic parsing, default error messages are often sufficient. For advanced error reporting, consider using `desc()` on parsers to provide more context, or implement custom error processing logic around `ParseError`.
affects: All
gotchaParsy excels at quickly writing clear, declarative parsers for relatively small to medium-sized languages. However, for applications with extremely demanding performance requirements or exceptionally large and complex grammars, other parser generators that use different parsing algorithms (e.g., LALR, PEG) might offer better performance characteristics.
fix
Evaluate `parsy`'s performance for your specific use case. If profiling reveals parsing as a bottleneck in high-performance scenarios, explore alternative parser generation libraries like Lark or PLY.
affects: All
Errors
Common errors & fixes
ModuleNotFoundError: No module named 'parsy'
The 'parsy' library is not installed in your Python environment.
fix
Install the library using pip: `pip install parsy`
parsy.ParseError: expected '...' at X:Y
The input string does not match the grammar defined by the parser at the specified position. The 'expected' message indicates what the parser was looking for.
fix
Review the input string and the parser definition to ensure they align, or handle the ParseError exception with a `try...except` block if non-conforming input is expected.
TypeError: unsupported type for ...: str (e.g., TypeError: unsupported type for timedelta days component: str)
This typically occurs when a parser's output (often a string from `regex` or `string`) is passed to a `.map()` function that expects a different type (e.g., an integer), leading to a type mismatch in the mapping function.
fix
Ensure that the parser output type matches the expected input type of the function provided to `.map()`. Often, an intermediate `.map(int)` or `.map(float)` is needed. For example, `P.regex(r'\d+').map(int).map(lambda x: datetime.timedelta(days=x))`.
NameError: name '...' is not defined (e.g., NameError: name 'expr' is not defined)
This error arises when defining recursive parsers where one part of the grammar refers to a parser (like `expr`) that has not yet been fully defined at that point in the code.
fix
Use `parsy.forward_declaration()` to create a placeholder for the parser before its full definition, then assign the complete parser to it later. Example: `expr = forward_declaration(); simple = regex('[0-9]+').map(int); group = string('(') >> expr.sep_by(string(' ')) << string(')'); expr.become(simple | group)`
TypeError: op() missing X required positional argument: 'Y' (when using @generate)
The `@parsy.generate` decorator expects the decorated function to be a generator that takes no arguments. If you define the generator function with parameters, `parsy` will try to call it without arguments, leading to this `TypeError`.
fix
If you need parameterized parsers, define a factory function that takes the parameters and returns a *new*, argument-less generator function decorated with `@generate`. Example: `def opP(symbol, f): @generate def op(): a = yield numberP; yield lex(pr.string(symbol)); b = yield numberP; return f(a,b); return op`
Upgrade
Version history
2.2latest on PyPI · released Sep 12, 2025
Audit
Dependencies

No dependency data recorded yet.

Agent activity
5 hits · last 30 days
node
4
Resources
parsy — pip install parsy · libregistry