Skip to main content

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 with statement
  • 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

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

escpos_thermal-1.0.0.tar.gz (62.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

escpos_thermal-1.0.0-py3-none-any.whl (66.5 kB view details)

Uploaded Python 3

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

Hashes for escpos_thermal-1.0.0.tar.gz
Algorithm Hash digest
SHA256 7dcee6ef4cecca9a3a0fe0bca2d0523233234007a142e6c60335f098d17c6729
MD5 93f4000892101ea2b5f72ddae98aac3b
BLAKE2b-256 92b6640a61b563f6d05c3be49fbefd772a904731de82ba6169a913f07ca136e4

See more details on using hashes here.

Provenance

The following attestation bundles were made for escpos_thermal-1.0.0.tar.gz:

Publisher: python-publish.yml on ysalitrynskyi/escpos-thermal

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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

Hashes for escpos_thermal-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 a094fd39a6c87a00ebbef708b0ee7e41d5ad1d9e0d021a264630f2290f91792e
MD5 f90915466619173942a3102228c2751f
BLAKE2b-256 16844e73b9c7c04076a736ad1cdd341ff8ba76fa14c91ff00736a357a4c622e1

See more details on using hashes here.

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

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page