wcwidth - Simplified wcwidth for MicroPython

January 27, 2026 · View on GitHub

This is a simplified version of wcwidth optimized for MicroPython and embedded systems.

Size Comparison

VersionLines of CodeDisk SizeUnicode Versions
MicroPython wcwidth74688 KB1 version (17.0.0 only)
Original wcwidth7,888672 KB21 versions (4.1.0 - 17.0.0)

Size reduction: ~90% (from 672 KB to 88 KB)

What's Removed

  • Multi-version support (only Unicode 17.0.0 is included)
  • Version selection logic and environment variable handling
  • Standard library functools.lru_cache (replaced with simple dict-based cache)
  • VS15 table (not commonly used)
  • Warnings and detailed error messages
  • lru_cache replace by simplistic cache implementation

What's Kept

  • Full Unicode 17.0.0 character width tables
  • wcwidth() - character width measurement
  • wcswidth() - string width measurement
  • Support for:
    • Wide characters (CJK, emoji, etc.)
    • Zero-width characters (combining marks, ZWJ, etc.)
    • VS16 (Variation Selector 16) for emoji modifiers
    • Control character detection

Installation

Simplest way to install the module on your MicroPython board is via mpremote mip:

mpremote mip install github:josverl/mp_wcwidth

Usage

from wcwidth import wcwidth, wcswidth

# Get width of a single character
print(wcwidth('A'))      # 1 (normal ASCII)
print(wcwidth('你'))     # 2 (wide CJK character)
print(wcwidth('🪲'))     # 2 (wide emoji)
print(wcwidth('\u0301')) # 0 (combining accent)
print(wcwidth('\n'))     # -1 (control character)

# Get width of a string
print(wcswidth('Hello'))         # 5
print(wcswidth('你好'))           # 4
print(wcswidth('print("🪲")'))   # 11

Demo

A simple demo script demo.py is included to showcase the functionality:

# Install the module and demo script to your MicroPython device
mpremote mip install github:josverl/mp_wcwidth
mpremote mip install --target . github:josverl/mp_wcwidth/demo.py

# Run the demo on the device 
mpremote exec "exec(open('demo.py').read())"

Caching

The simplified version includes a minimal cache implementation (simple_cache.py) that replaces Python's functools.lru_cache:

  • Fixed size: Uses a simple dict with size limit (no reallocation)
  • FIFO eviction: When full, clears entire cache (ultra-simple)
  • No external dependencies: Pure Python, MicroPython compatible
  • Minimal overhead: ~90 lines of code
  • Default cache size: 128 entries for wcwidth()

The cache significantly improves performance for repeated character width lookups.

Testing

All basic functionality works identically to the original:

python -c "import wcwidth; print(wcwidth.wcwidth('🪲'))"  # 2

mpremote exec "import wcwidth; print(wcwidth.wcwidth('🪲'))"  # 2

License

Same as original wcwidth (MIT License)

Credits

Based on wcwidth by Jeff Quast, which is based on Markus Kuhn's wcwidth.c implementation.