Python library for ESC/POS thermal and impact printers
Project description
escpos-thermal
A powerful Python library for ESC/POS thermal receipt printers.
Features
- Full ESC/POS Support - Text, formatting, barcodes, QR codes, images, and more
- Multiple Connections - Network (TCP/IP), USB, Serial, File, CUPS, and Windows printing
- Async Support - AsyncNetworkConnector for non-blocking I/O
- Image Dithering - Floyd-Steinberg, Atkinson, and ordered dithering algorithms
- Printer Status - Read paper status, online state, and error conditions
- Cash Drawer Control - Open drawers and check open/closed status
- Context Manager - Clean resource management with
withstatement - Logging - Built-in debug logging support
- 294 Tests - Comprehensive test coverage
Installation
pip install escpos-thermal
Optional Dependencies
# USB printer support
pip install pyusb
# Serial printer support
pip install pyserial
# QR code generation fallback
pip install qrcode
# Barcode generation fallback
pip install python-barcode
Quick Start
from escpos_thermal import Printer
from escpos_thermal.connectors import NetworkConnector
# Using context manager (recommended)
with Printer(NetworkConnector("192.168.1.100", 9100)) as printer:
printer.text("Hello, World!\n")
printer.barcode("123456789012", Printer.BARCODE_UPCA)
printer.qr_code("https://example.com")
printer.cut()
Connection Types
Network Printer (TCP/IP)
from escpos_thermal import Printer
from escpos_thermal.connectors import NetworkConnector
with Printer(NetworkConnector("192.168.1.100", 9100)) as printer:
printer.text("Network printing!\n")
printer.cut()
Async Network Printer
import asyncio
from escpos_thermal.connectors import AsyncNetworkConnector
async def print_async():
async with AsyncNetworkConnector("192.168.1.100", 9100) as conn:
await conn.write(b"\x1b@") # Initialize
await conn.write(b"Async printing!\n")
await conn.write(b"\x1dVA\x03") # Cut
asyncio.run(print_async())
USB Printer
from escpos_thermal import Printer
from escpos_thermal.connectors import USBConnector
# Find vendor/product ID with: lsusb
with Printer(USBConnector(0x04b8, 0x0202)) as printer:
printer.text("USB printing!\n")
printer.cut()
Serial Printer
from escpos_thermal import Printer
from escpos_thermal.connectors import SerialConnector
with Printer(SerialConnector("/dev/ttyUSB0", 9600)) as printer:
printer.text("Serial printing!\n")
printer.cut()
Text Formatting
with Printer(connector) as printer:
# Text sizes (1-8)
printer.set_text_size(2, 2)
printer.text("BIG TEXT\n")
printer.set_text_size(1, 1)
# Styles
printer.set_emphasis(True)
printer.text("Bold\n")
printer.set_emphasis(False)
printer.set_underline(Printer.UNDERLINE_SINGLE)
printer.text("Underlined\n")
printer.set_underline(Printer.UNDERLINE_NONE)
# Alignment
printer.set_justification(Printer.JUSTIFY_CENTER)
printer.text("Centered\n")
printer.set_justification(Printer.JUSTIFY_LEFT)
# Fonts
printer.set_font(Printer.FONT_B)
printer.text("Smaller font\n")
printer.set_font(Printer.FONT_A)
Barcodes
with Printer(connector) as printer:
# Configure barcode appearance
printer.set_barcode_height(80)
printer.set_barcode_width(3)
printer.set_barcode_text_position(Printer.BARCODE_TEXT_BELOW)
# Print various barcode types
printer.barcode("012345678905", Printer.BARCODE_UPCA)
printer.barcode("5901234123457", Printer.BARCODE_JAN13)
printer.barcode("{BHELLO123", Printer.BARCODE_CODE128)
printer.barcode("ABC123", Printer.BARCODE_CODE39)
QR Codes
with Printer(connector) as printer:
# Simple QR code
printer.qr_code("https://example.com")
# With options
printer.qr_code(
"https://example.com",
ec=Printer.QR_ECLEVEL_H, # High error correction
size=8, # Module size
model=Printer.QR_MODEL_2
)
Image Printing with Dithering
from escpos_thermal import Printer, PillowEscposImage, DitherMode
from escpos_thermal.connectors import NetworkConnector
with Printer(NetworkConnector("192.168.1.100")) as printer:
# Simple threshold (default)
img = PillowEscposImage("logo.png")
printer.graphics(img)
# Floyd-Steinberg dithering (best for photos)
img = PillowEscposImage("photo.jpg", dither=DitherMode.FLOYDSTEINBERG)
printer.graphics(img)
# Atkinson dithering (lighter, good for graphics)
img = PillowEscposImage("graphic.png", dither=DitherMode.ATKINSON)
printer.graphics(img)
# Custom threshold
img = PillowEscposImage("logo.png", threshold=100)
printer.graphics(img)
Convert Image to Monochrome
from PIL import Image
from escpos_thermal import PillowEscposImage, DitherMode
# Convert any image to printer-ready monochrome
pil_image = Image.open("photo.jpg")
mono = PillowEscposImage.to_monochrome(pil_image, dither=DitherMode.FLOYDSTEINBERG)
mono.save("preview.png") # Preview what will print
Printer Status
with Printer(connector) as printer:
# Check printer status
if printer.is_online():
print("Printer is online")
if printer.has_paper():
print("Paper is loaded")
else:
print("Paper is low or out!")
if printer.has_error():
print("Printer has an error")
Cash Drawer
with Printer(connector) as printer:
# Open cash drawer
printer.pulse() # Pin 0, default timing
printer.pulse(pin=1, on_ms=200, off_ms=400) # Pin 1, custom timing
# Check drawer status (requires compatible hardware)
if printer.is_drawer_open():
print("Drawer is open!")
Logging
import logging
# Enable debug logging
logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger('escpos')
logger.setLevel(logging.DEBUG)
# Now printer operations will log debug info
with Printer(connector) as printer:
printer.text("Debug logging enabled\n")
Printer Profiles
from escpos_thermal import Printer, CapabilityProfile
from escpos_thermal.connectors import NetworkConnector
# List available profiles
profiles = CapabilityProfile.get_profile_names()
print(profiles)
# Use a specific profile
profile = CapabilityProfile.load("TM-T88IV")
with Printer(NetworkConnector("192.168.1.100"), profile) as printer:
printer.text("Using TM-T88IV profile\n")
API Reference
Printer Constants
| Category | Constants |
|---|---|
| Barcode Types | BARCODE_UPCA, BARCODE_UPCE, BARCODE_JAN13, BARCODE_JAN8, BARCODE_CODE39, BARCODE_ITF, BARCODE_CODABAR, BARCODE_CODE93, BARCODE_CODE128 |
| QR Code | QR_ECLEVEL_L/M/Q/H, QR_MODEL_1/2, QR_MICRO |
| Text | JUSTIFY_LEFT/CENTER/RIGHT, FONT_A/B/C, UNDERLINE_NONE/SINGLE/DOUBLE |
| Cut | CUT_FULL, CUT_PARTIAL |
| Images | IMG_DEFAULT, IMG_DOUBLE_WIDTH, IMG_DOUBLE_HEIGHT |
DitherMode Options
| Mode | Description |
|---|---|
DitherMode.NONE |
Simple threshold (fast, good for logos) |
DitherMode.FLOYDSTEINBERG |
Floyd-Steinberg error diffusion (best for photos) |
DitherMode.ATKINSON |
Atkinson dithering (lighter, good for graphics) |
DitherMode.ORDERED |
Bayer ordered dithering (fast, consistent) |
Connectors
| Connector | Use Case | Requirements |
|---|---|---|
NetworkConnector |
TCP/IP printers | None |
AsyncNetworkConnector |
Async TCP/IP | None |
USBConnector |
USB printers | pyusb |
SerialConnector |
Serial printers | pyserial |
FileConnector |
Device files | None |
CupsConnector |
CUPS (Linux/macOS) | pycups |
WindowsConnector |
Windows API | Windows |
DummyConnector |
Testing | None |
Requirements
- Python 3.8+
- Pillow (for image support)
License
MIT License
Credits
- Author: Yevhen Salitrynskyi
- Based on: escpos-php by Michael Billington
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file escpos_thermal-1.0.0.tar.gz.
File metadata
- Download URL: escpos_thermal-1.0.0.tar.gz
- Upload date:
- Size: 62.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7dcee6ef4cecca9a3a0fe0bca2d0523233234007a142e6c60335f098d17c6729
|
|
| MD5 |
93f4000892101ea2b5f72ddae98aac3b
|
|
| BLAKE2b-256 |
92b6640a61b563f6d05c3be49fbefd772a904731de82ba6169a913f07ca136e4
|
Provenance
The following attestation bundles were made for escpos_thermal-1.0.0.tar.gz:
Publisher:
python-publish.yml on ysalitrynskyi/escpos-thermal
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
escpos_thermal-1.0.0.tar.gz -
Subject digest:
7dcee6ef4cecca9a3a0fe0bca2d0523233234007a142e6c60335f098d17c6729 - Sigstore transparency entry: 713951858
- Sigstore integration time:
-
Permalink:
ysalitrynskyi/escpos-thermal@f57b6051f6c6fe758b7a198bb82c638e57a6ba8f -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/ysalitrynskyi
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-publish.yml@f57b6051f6c6fe758b7a198bb82c638e57a6ba8f -
Trigger Event:
release
-
Statement type:
File details
Details for the file escpos_thermal-1.0.0-py3-none-any.whl.
File metadata
- Download URL: escpos_thermal-1.0.0-py3-none-any.whl
- Upload date:
- Size: 66.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a094fd39a6c87a00ebbef708b0ee7e41d5ad1d9e0d021a264630f2290f91792e
|
|
| MD5 |
f90915466619173942a3102228c2751f
|
|
| BLAKE2b-256 |
16844e73b9c7c04076a736ad1cdd341ff8ba76fa14c91ff00736a357a4c622e1
|
Provenance
The following attestation bundles were made for escpos_thermal-1.0.0-py3-none-any.whl:
Publisher:
python-publish.yml on ysalitrynskyi/escpos-thermal
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
escpos_thermal-1.0.0-py3-none-any.whl -
Subject digest:
a094fd39a6c87a00ebbef708b0ee7e41d5ad1d9e0d021a264630f2290f91792e - Sigstore transparency entry: 713951860
- Sigstore integration time:
-
Permalink:
ysalitrynskyi/escpos-thermal@f57b6051f6c6fe758b7a198bb82c638e57a6ba8f -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/ysalitrynskyi
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-publish.yml@f57b6051f6c6fe758b7a198bb82c638e57a6ba8f -
Trigger Event:
release
-
Statement type: