pycparser
raw JSON → 3.0 verified Tue May 12 auth: no python install: verified quickstart: verified
pycparser is a complete, standards-compliant C99 parser written in pure Python, producing an Abstract Syntax Tree (AST) that can be traversed, modified, and re-emitted as C code. Current version is 3.0, released January 2026, which replaced the bundled PLY (Lex/Yacc) backend with a hand-written lexer and recursive-descent parser—eliminating all external dependencies and improving parse speed by ~30%. Release cadence is irregular; major versions are rare (2.x spanned 2012–2025).
pip install pycparser Common errors
error ModuleNotFoundError: No module named 'pycparser' ↓
cause The `pycparser` package is not installed in the Python environment being used.
fix
Install the package using pip:
pip install pycparser error ModuleNotFoundError: No module named 'pycparser.plyparser' ↓
cause In `pycparser` version 3.0, the internal `plyparser` module was removed as part of replacing the PLY backend with a hand-written parser. Code attempting to import this module will fail.
fix
Update your code to remove any direct imports of
pycparser.plyparser. If a dependency requires it, ensure that dependency is compatible with pycparser 3.0 or downgrade pycparser to a 2.x version if necessary. error pycparser.ParseError: <file>:<line>:<column>: before: <token> ↓
cause `pycparser` encountered C code it could not parse, often due to non-standard C extensions (like GCC built-ins), complex macros, or if the input C code was not fully preprocessed before being passed to `pycparser`.
fix
Ensure the C code is fully preprocessed (e.g., using
gcc -E or clang -E) before parsing with pycparser. If using standard library headers, provide pycparser with its bundled fake_libc_include directory (e.g., parse_file('file.c', parse_headers=True, cpp_args=['-Iutils/fake_libc_include'])). Simplify or remove non-standard C constructs if pycparser doesn't support them. error ImportError: cannot import name 'c_parser' from partially initialized module 'pycparser' ↓
cause This issue typically arises with `pycparser` 3.0, particularly in frozen applications (e.g., those built with `cx_Freeze`), indicating a potential circular import or an initialization problem specific to the packaging process.
fix
Downgrade
pycparser to a version prior to 3.0 (e.g., pip install pycparser<3). Alternatively, check for updates to pycparser or the freezing tool that address this specific compatibility problem. Warnings
breaking v3.0 dropped PLY entirely and rewrote the lexer/parser from scratch. CParser.__init__ kwargs lex_optimize, yacc_optimize, yacc_debug, lextab, yacctab are no longer accepted — passing them raises TypeError. ↓
fix Remove all PLY-related kwargs from CParser() calls. The public AST API is unchanged; only internal constructor arguments differ.
breaking Python 3.8 support was dropped in v3.0. Requires Python >=3.10. ↓
fix Upgrade to Python 3.10+. Pin pycparser<3 if you must support Python 3.8 or 3.9.
gotcha pycparser cannot parse raw C files that contain #include or macros — it requires preprocessed input. Passing unpreprocessed C to parser.parse() will produce parse errors for any non-trivial real-world file. ↓
fix Use parse_file(..., use_cpp=True) which calls cpp/gcc-E automatically, or manually preprocess with subprocess before calling parser.parse().
gotcha fake_libc_include headers are NOT included in the PyPI pip wheel. Code that assumes pycparser.__file__ contains a utils/fake_libc_include directory will fail at runtime. ↓
fix Install the companion package `pip install pycparser-fake-libc` and use `import pycparser_fake_libc; cpp_args='-I' + pycparser_fake_libc.directory`, or vendor the headers from the GitHub source tree.
gotcha The fake_libc_include headers target C11 and will cause errors if the preprocessor is invoked with -std=c99 or older standards. ↓
fix Omit -std=c99 from cpp_args when using fake_libc_include, or use a preprocessor invocation that defaults to C11 or later.
gotcha pycparser supports C99 and a subset of C11, but does NOT support GCC/Clang extensions (__attribute__, __extension__, __builtin_*, etc.) out of the box. Passing GCC-extended code will raise ParseError. ↓
fix Pass cpp_args=['-D__attribute__(x)=', '-D__extension__=', ...] to strip extensions before parsing, as shown in the project FAQ.
gotcha Frozen-app packagers (cx_Freeze, PyInstaller) may fail to import pycparser 3.0 due to internal relative-import restructuring introduced when PLY was removed, raising ImportError on 'c_parser'. ↓
fix Check for updated hooks in your freezer tool. As a workaround, pin pycparser<3 until the packager adds support.
Install
pip install "pycparser<3" Install compatibility verified last tested: 2026-05-12
python os / libc variant status wheel install import disk
3.10 alpine (musl) "pycparser<3" - - 0.04s 18.9M
3.10 alpine (musl) pycparser - - 0.07s 18.1M
3.10 slim (glibc) "pycparser<3" - - 0.02s 19M
3.10 slim (glibc) pycparser - - 0.04s 19M
3.11 alpine (musl) "pycparser<3" - - 0.07s 20.9M
3.11 alpine (musl) pycparser - - 0.15s 20.1M
3.11 slim (glibc) "pycparser<3" - - 0.06s 21M
3.11 slim (glibc) pycparser - - 0.13s 21M
3.12 alpine (musl) "pycparser<3" - - 0.07s 12.7M
3.12 alpine (musl) pycparser - - 0.12s 11.9M
3.12 slim (glibc) "pycparser<3" - - 0.07s 13M
3.12 slim (glibc) pycparser - - 0.12s 12M
3.13 alpine (musl) "pycparser<3" - - 0.06s 12.4M
3.13 alpine (musl) pycparser - - 0.10s 11.6M
3.13 slim (glibc) "pycparser<3" - - 0.06s 13M
3.13 slim (glibc) pycparser - - 0.12s 12M
3.9 alpine (musl) "pycparser<3" - - 0.03s 18.4M
3.9 alpine (musl) pycparser - - 0.04s 18.4M
3.9 slim (glibc) "pycparser<3" - - 0.03s 19M
3.9 slim (glibc) pycparser - - 0.04s 19M
Imports
- CParser wrong
from pycparser import CParsercorrectfrom pycparser import c_parser parser = c_parser.CParser() - parse_file
from pycparser import parse_file - c_generator.CGenerator
from pycparser import c_generator gen = c_generator.CGenerator() - c_ast / NodeVisitor
from pycparser import c_ast class MyVisitor(c_ast.NodeVisitor): ...
Quickstart verified last tested: 2026-04-23
from pycparser import c_parser, c_ast, c_generator
# Direct in-memory parse — only works for preprocessor-free, self-contained C
parser = c_parser.CParser()
src = r"""
int add(int a, int b) {
return a + b;
}
"""
ast = parser.parse(src, filename='<none>')
ast.show(attrnames=True, nodenames=True)
# Regenerate C source from AST
gen = c_generator.CGenerator()
print(gen.visit(ast))
# Visitor pattern: collect all function names
class FuncDefVisitor(c_ast.NodeVisitor):
def visit_FuncDef(self, node):
print('Function:', node.decl.name)
v = FuncDefVisitor()
v.visit(ast)