Embedding into Custom Scripts
esptool can be easily integrated into Python applications or called from other Python scripts.
Using Esptool as a Python Module
The esptool module provides a comprehensive Python API for interacting with ESP chips programmatically. By leveraging the API, developers can automate tasks such as flashing firmware, reading device information, managing flash memory, or preparing and analyzing binary images. The API supports both high-level abstractions and low-level control.
Using the Command-Line Interface
The most straightforward and basic integration option is to pass arguments to esptool.main(). This workaround allows you to pass exactly the same arguments as you would on the CLI:
import esptool
command = ['--baud', '460800', 'read-flash', '0', '0x200000', 'flash_contents.bin']
print("Using command ", " ".join(command))
esptool.main(command)
Public API Reference
For more control and custom integration, esptool exposes a public API - a set of high-level functions that encapsulate common operations and simplify the interaction with the ESP chip. These functions are designed to be user-friendly and provide an intuitive way to work with the chip. The public API is the recommended way to interact with the chip programmatically.
Basic Workflow:
Detect and Connect: Use
connect_esp()for a single call that mirrors the CLI - auto-discover the serial port, auto-detect the chip, and retry failed connections. Alternatively, manually create and instantiate a specificESPLoaderobject (e.g.ESP32ROM) and establish a connection in two steps.Run Stub Flasher (Optional): Upload and execute the stub flasher which provides enhanced functionality and speed.
Perform Operations: Utilize the chip object’s methods or public API command functions to interact with the device.
Reset and Cleanup: Ensure proper reset and resource cleanup using context managers.
This example demonstrates writing two binary files using high-level commands:
from esptool.cmds import connect_esp, attach_flash, reset_chip, run_stub, write_flash
BOOTLOADER = "bootloader.bin"
FIRMWARE = "firmware.bin"
with connect_esp() as esp: # Auto-discover the port and detect the chip
esp = run_stub(esp) # Skip this line to avoid running the stub flasher
attach_flash(esp) # Attach the flash memory chip, required for flash operations
with open(BOOTLOADER, "rb") as bl_file, open(FIRMWARE, "rb") as fw_file:
write_flash(esp, [(0, bl_file), (0x1000, fw_file)]) # Write the binary files
reset_chip(esp, "hard-reset") # Reset the chip
The
espobject has to be replaced with the stub flasher object returned byrun_stub(esp)when the stub flasher is activated. This step can be skipped if the stub flasher is not needed.Running
attach_flash(esp)is required for any flash-memory-related operations to work.Using the
espobject in a context manager ensures the port gets closed properly after the block is executed.connect_esp()auto-discovers the serial port and detects the chip; passport="/dev/ttyACM0"to target a specific port. It accepts the same connection options as the CLI (before,port_filter,connect_attempts, etc.), and you can callesp.change_baud()on the returned object to raise the transfer speed.
The following example demonstrates running a series of flash memory operations in one go:
from esptool.cmds import (
erase_flash,
attach_flash,
flash_id,
read_flash,
reset_chip,
run_stub,
verify_flash,
write_flash,
)
from esptool.targets import ESP32ROM # Import the target class, e.g. ESP8266ROM, ESP32S3ROM, etc.
PORT = "/dev/ttyACM0"
BOOTLOADER = "bootloader.bin"
FIRMWARE = "firmware.bin"
with ESP32ROM(PORT) as esp:
esp.connect() # Connect to the ESP chip, needed when ESP32ROM is instantiated directly
esp = run_stub(esp) # Run the stub loader (optional)
attach_flash(esp) # Attach the flash memory chip, required for flash operations
flash_id(esp) # Print information about the flash chip
erase_flash(esp) # Erase the flash memory first
with open(BOOTLOADER, "rb") as bl_file, open(FIRMWARE, "rb") as fw_file:
write_flash(esp, [(0, bl_file), (0x1000, fw_file)]) # Write the binary files
verify_flash(esp, [(0, bl_file), (0x1000, fw_file)]) # Verify the written data
read_flash(esp, 0x0, 0x2400, "output.bin") # Read the flash memory into a file
reset_chip(esp, "hard-reset") # Reset the chip
This example doesn’t use
connect_esp(), but instantiates aESP32ROMclass directly. This is useful when you know the target chip in advance. In this scenarioesp.connect()is required to establish a connection with the device.Multiple operations can be chained together in a single context manager block.
The Public API implements a custom ImageSource input type, which expands to str | bytes | IO[bytes] - a path to the firmware image file, an opened file-like object, or the image data as bytes.
As output, the API returns a bytes object representing the binary image or writes the image to a file if the output parameter is provided.
The following example converts an ELF file to a flashable binary, prints the image information, and flashes the image. The example demonstrates three different ways to achieve the same result, showcasing the flexibility of the API:
ELF = "firmware.elf"
# var 1 - Loading ELF from a file, not writing binary to a file
bin_file = elf2image(ELF, "esp32c3")
image_info(bin_file)
with connect_esp() as esp:
attach_flash(esp)
write_flash(esp, [(0, bin_file)])
# var 2 - Loading ELF from an opened file object, not writing binary to a file
with open(ELF, "rb") as elf_file, connect_esp() as esp:
bin_file = elf2image(elf_file, "esp32c3")
image_info(bin_file)
attach_flash(esp)
write_flash(esp, [(0, bin_file)])
# var 3 - Loading ELF from a file, writing binary to a file
elf2image(ELF, "esp32c3", "image.bin")
image_info("image.bin")
with connect_esp() as esp:
attach_flash(esp)
write_flash(esp, [(0, "image.bin")])
The following section provides a detailed reference for the public API functions.
Chip Control Operations
- esptool.cmds.connect_esp(port: str | None = None, chip: str = 'auto', initial_baud: int = 115200, port_filter: list[str] | None = None, before: str = 'default-reset', trace: bool = False, connect_attempts: int = 7, open_port_attempts: int = 1) ESPLoader
Connect to an Espressif device, mirroring how the esptool CLI establishes a connection: auto-discover serial ports, auto-detect the chip, and retry failed connections.
This is the recommended single-call entry point for scripts that want the full CLI connection behavior (port discovery, chip detection, and reset/sync retries) without reimplementing it around
detect_chip().- Parameters:
port – Specific serial port device to use (e.g.
"/dev/ttyACM0"), orNoneto auto-discover ports viaport_filter.chip – Target chip name (e.g.
"esp32","esp32s3"), or"auto"to detect.initial_baud – The baud rate the port is opened at for the initial sync, not an operational rate. ROM bootloaders typically require 115200 (the default);
connect_esp()does not upgrade to a faster rate on its own — callesp.change_baud()on the returned object afterward if you need a faster transfer speed.port_filter – Filters applied when auto-discovering ports (ignored when
portis given), each entry of the form"vid=NUMBER","pid=NUMBER","name=SUBSTRING"or"serial=SUBSTRING".before – The chip reset method to perform when connecting (
"default-reset","usb-reset","no-reset","no-reset-no-sync").trace – Enables or disables tracing for debugging purposes.
connect_attempts – Number of sync attempts per candidate port before moving on (or giving up if
portwas set).open_port_attempts – Number of times to retry opening
portif it fails to open.1(default) means try once; only meaningful when bothportand a concretechipare specified.
- Returns:
A connected
ESPLoaderinstance for the detected or requested chip.- Raises:
FatalError – If no Espressif device could be reached on any of the candidate serial ports.
Example
from esptool.cmds import connect_esp, attach_flash, run_stub # Auto-discover the port and auto-detect the chip with connect_esp() as esp: esp = run_stub(esp) # Optional: upload the stub flasher esp.change_baud(921600) # Upgrade to a faster operational rate attach_flash(esp) ...
- esptool.cmds.connect_with_retries(port: str, initial_baud: int, chip: str, max_retries: int, trace: bool = False, before: str = 'default-reset') ESPLoader
Repeatedly attempt to open a single, known port and sync with the chip, retrying on failure.
connect_esp()is the recommended entry point; use this lower-level helper when driving the retry loop directly.- Parameters:
port – The serial port to open.
initial_baud – The baud rate used when opening the port for the initial sync (ROM bootloaders typically require 115200).
chip – Target chip name (e.g.
"esp32","esp32s3"). Must be a concrete chip, not"auto".max_retries – Number of attempts before giving up.
0retries forever until successful.trace – Enables or disables tracing for debugging purposes.
before – The chip reset method to perform before each attempt (
"default-reset","usb-reset","no-reset","no-reset-no-sync").
- Returns:
A connected ESPLoader instance for the requested chip.
- esptool.cmds.connect_first_available(serial_list: list[str], port: str | None, connect_attempts: int, initial_baud: int, chip: str = 'auto', trace: bool = False, before: str = 'default-reset') ESPLoader | None
Iterate
serial_listand return the first port that connects successfully.connect_esp()is the recommended entry point; use this lower-level helper when driving port iteration directly.- Parameters:
serial_list – Candidate serial port devices to try.
port – Original user-supplied port, or
Noneif auto-discovering. When set, the first connection error is re-raised instead of being swallowed to move on to the next candidate.connect_attempts – Number of sync attempts per candidate port.
initial_baud – The baud rate used when opening each port for the initial sync (ROM bootloaders typically require 115200).
chip – Target chip name, or
"auto"to detect.trace – Enables or disables tracing for debugging purposes.
before – The chip reset method to perform when connecting (
"default-reset","usb-reset","no-reset","no-reset-no-sync").
- Returns:
A connected ESPLoader instance for the first reachable port, or
Noneif no candidate could be connected.
- esptool.cmds.detect_chip(port: str = '/dev/ttyUSB0', baud: int = 115200, connect_mode: str = 'default-reset', trace_enabled: bool = False, connect_attempts: int = 7) ESPLoader
Detect the type of ESP device connected via serial, connect to it, and return an active ESPLoader object.
- Parameters:
port – The serial port to use for communication.
baud – The baud rate for serial communication.
connect_mode – The chip reset method to perform when connecting to the ESP device (
"default-reset","usb-reset","no-reset","no-reset-no-sync")trace_enabled – Enables or disables tracing for debugging purposes.
connect_attempts – Number of connection attempts before failing.
- Returns:
An initialized instance of the detected chip class ready for use.
- esptool.cmds.run_stub(esp: ESPLoader, plugins: list[str] | None = None) ESPLoader
Load and execute the stub loader on the ESP device. If stub loading is not supported or is explicitly disabled, warnings are logged.
- Parameters:
esp – Initiated esp object connected to a real device.
plugins – Optional list of plugin names to load (e.g. [“nand”]).
- Returns:
The esp instance, either as a stub child class in a state where the stub has been executed, or in its original state if the stub loader is disabled or unsupported.
- esptool.cmds.load_ram(esp: ESPLoader, input: str | bytes | IO[bytes]) None
Load a firmware image into RAM and execute it on the ESP device.
- Parameters:
esp – Initiated esp object connected to a real device.
input – Path to the firmware image file, opened file-like object, or the image data as bytes.
- esptool.cmds.run(esp: ESPLoader) None
Execute the firmware loaded on the ESP device.
- Parameters:
esp – Initiated esp object connected to a real device.
- esptool.cmds.reset_chip(esp: ESPLoader, reset_mode: str = 'hard-reset') None
Reset the ESP device.
- Parameters:
esp – Initiated esp object connected to a real device.
reset_mode – Reset mode to use (
"hard-reset": perform a hard reset using the RTS control line,"soft-reset": perform a soft reset,"no-reset": stay in bootloader,"no-reset-stub": stay in flasher stub,"watchdog-reset": perform a hard reset utilizing a software watchdog. )
Chip Information Operations
- esptool.cmds.chip_id(esp: ESPLoader) None
Read and display the Chip ID of the ESP device if available, otherwise fall back to displaying the MAC address.
- Parameters:
esp – Initiated esp object connected to a real device.
- esptool.cmds.get_security_info(esp: ESPLoader) None
Read and display security-related information about the ESP device.
- Parameters:
esp – Initiated esp object connected to a real device.
- esptool.cmds.read_mac(esp: ESPLoader) None
Read and display the MAC address of the ESP device.
- Parameters:
esp – Initiated esp object connected to a real device.
Flash Memory Manipulation Operations
- esptool.cmds.attach_flash(esp: ESPLoader, spi_connection: tuple[int, int, int, int, int] | str | None = None, flash_type: str = 'nor') None
Configure and attach a SPI flash memory chip to the ESP device, verify the connection. All following flash operations will be performed on the attached flash chip.
- Parameters:
esp – Initiated esp object connected to a real device.
spi_connection – Custom SPI connection configuration. This can either be a tuple containing five pin numbers
(CLK, Q, D, HD, CS)for manual configuration or a string ("SPI"or"HSPI") representing a pre-defined config. If not provided, the default flash connection is used.flash_type – Type of flash - “nor” (default) or “nand”.
- esptool.cmds.flash_id(esp: ESPLoader) None
Read and display the SPI flash memory chip identification and configuration details, such as the manufacturer ID, device ID, detected flash size, type, and voltage.
- Parameters:
esp – Initiated esp object connected to a real device.
- esptool.cmds.read_flash(esp: ESPLoader, address: int, size: int, output: str | None = None, flash_size: str = 'keep', no_progress: bool = False, flash_type: str = 'nor', nand_end_address: int | None = None) bytes | None
Read a specified region of SPI flash memory of an ESP device and optionally save it to a file.
- Parameters:
esp – Initiated esp object connected to a real device.
address – The starting address in flash memory to read from.
size – The number of bytes to read.
output – The name of the file to save the read data. If None, the function returns the data.
flash_size – Flash size setting, needs to be set only when the stub flasher is disabled. Options:
"detect": auto-detect flash size with fallback to 4MB,"keep": auto-detect but skip setting parameters in SDM, Explicit size: use the specified flash size.no_progress – Disable printing progress.
flash_type – Type of flash - “nor” (default) or “nand”.
- Returns:
The read flash data as bytes if output is None; otherwise, returns None after writing to file.
- esptool.cmds.write_flash(esp: ESPLoader, addr_data: list[tuple[int, str | bytes | IO[bytes]]], flash_freq: str = 'keep', flash_mode: str = 'keep', flash_size: str = 'keep', flash_type: str = 'nor', **kwargs) None
Write firmware or data to the SPI flash memory of an ESP device.
- Parameters:
esp – Initiated esp object connected to a real device.
addr_data – List of (address, data) tuples specifying where to write each file or data in flash memory. The data can be a file path (str), bytes, or a file-like object.
flash_freq – Flash frequency to set in the bootloader image header (
"keep"to retain current).flash_mode – Flash mode to set in the bootloader image header (
"keep"to retain current).flash_size – Flash size to set in the bootloader image header (
"keep"to retain current).flash_type – Flash type - “nor” (default) or “nand”.
- Keyword Arguments:
erase_all (bool) – Erase the entire flash before writing.
encrypt (bool) – Encrypt all files during flashing.
encrypt_files (list[tuple[int, ImageSource]] | None) – List of (address, data) tuples for files to encrypt individually.
compress (bool) – Compress data before flashing.
no_compress (bool) – Don’t compress data before flashing.
force (bool) – Ignore safety and content checks (e.g., overwriting bootloader, flash size, whether binary is already in flash).
ignore_flash_enc_efuse (bool) – Ignore flash encryption eFuse settings.
no_progress (bool) – Disable progress updates.
diff_with – list[ImageSource | None]: Previously flashed image(s) to compare with for fast reflashing. Will be zipped with addr_data.
no_diff_verify – bool: Skip post-flash verification of unchanged files when using diff_with to save time (trust the state of the flash contents). Only unchanged files are skipped without an MD5 check, written data is still verified after write and the whole file is reflashed if verification fails. Use only when flash has not been modified since the last flash. Requires diff_with. Mutually exclusive with skip_flashed.
skip_flashed – bool: Skip flashing if the new binary is already in flash. Only for use when diff_with is not specified (mutually exclusive).
- esptool.cmds.erase_flash(esp: ESPLoader, force: bool = False, flash_type: str = 'nor') None
Erase the SPI flash memory of the ESP device.
- Parameters:
esp – Initiated esp object connected to a real device.
force – Bypass the security checks for flash encryption and secure boot.
flash_type – “nor” or “nand”.
- esptool.cmds.erase_region(esp: ESPLoader, address: int, size: int, force: bool = False, flash_type: str = 'nor') None
Erase a specific region of the SPI flash memory of the ESP device.
- Parameters:
esp – Initiated esp object connected to a real device.
address – The starting address from which to begin erasing.
size – The total number of bytes to erase.
force – Bypass the security checks for flash encryption and secure boot.
flash_type – “nor” or “nand”.
- esptool.cmds.verify_flash(esp: ESPLoader, addr_data: list[tuple[int, str | bytes | IO[bytes]]], flash_freq: str = 'keep', flash_mode: str = 'keep', flash_size: str = 'keep', diff: bool = False, flash_type: str = 'nor') None
Verify the contents of the SPI flash memory against the provided binary files or byte data.
- Parameters:
esp – Initiated esp object connected to a real device.
addr_data – List of (address, data) tuples specifying what parts of flash memory to verify. The data can be a file path (str), bytes, or a file-like object.
flash_freq – Flash frequency setting (
"keep"to retain current).flash_mode – Flash mode setting (
"keep"to retain current).flash_size – Flash size setting (
"keep"to retain current).diff – If True, perform a byte-by-byte comparison on failure.
flash_type – “nor” or “nand”.
- esptool.cmds.read_flash_status(esp: ESPLoader, bytes: int = 2) None
Read and print the status register value of the SPI flash memory.
- Parameters:
esp – Initiated esp object connected to a real device.
bytes – Number of bytes to read.
- esptool.cmds.write_flash_status(esp: ESPLoader, value: int, bytes: int = 2, non_volatile: bool = False) None
Write a new value to the SPI flash memory status register and verify the update.
- Parameters:
esp – Initiated esp object connected to a real device.
value – The new status register value to write.
bytes – Number of bytes to write.
non_volatile – If True, allows non-volatile status register bits to be written.
- esptool.cmds.read_flash_sfdp(esp: ESPLoader, address: int, bytes: int = 1) None
Read and display the Serial Flash Discoverable Parameters (SFDP) from the flash memory.
- Parameters:
esp – Initiated esp object connected to a real device.
address – Starting address in the SFDP region to read from.
bytes – Number of bytes to read (1-4).
Memory Operations
- esptool.cmds.read_mem(esp: ESPLoader, address: int) None
Read and display a 32-bit value from a memory address on the ESP device.
- Parameters:
esp – Initiated esp object connected to a real device.
address – Memory address to read from (32-bit aligned).
- esptool.cmds.write_mem(esp: ESPLoader, address: int, value: int, mask: int = 4294967295) None
Write a 32-bit value to a memory address on the ESP device with optional bitmask.
- Parameters:
esp – Initiated esp object connected to a real device.
address – Memory address to write to (32-bit aligned).
value – 32-bit value to write.
mask – Bitmask specifying which bits to modify (default: all bits).
- esptool.cmds.dump_mem(esp: ESPLoader, address: int, size: int, output: str | None = None) bytes | None
Dump a block of memory from the ESP device.
- Parameters:
esp – Initiated esp object connected to a real device.
address – Starting memory address to dump from.
size – Number of bytes to dump.
output – Path to output file for binary data. If None, returns the data.
- Returns:
Memory dump as bytes if output is None; otherwise, returns None after writing to file.
Binary Image Manipulation Operations
The following commands can run without the need for a connected chip:
- esptool.cmds.elf2image(input: str | bytes | IO[bytes], chip: str, output: str | None = None, flash_freq: str | None = None, flash_mode: str = 'qio', flash_size: str = '1MB', **kwargs) bytes | tuple[bytes | None, bytes] | None
Convert ELF data into a firmware image suitable for flashing onto an ESP device.
- Parameters:
input – Path to the ELF file to convert, opened file-like object, or the ELF data as bytes.
chip – Target ESP device type.
output – Path to save the generated firmware image. If “auto”, a default pre-defined path is used. If None, the image is not written to a file, but returned as bytes.
flash_freq – Flash frequency to set in the image header.
flash_mode – Flash mode to set in the image header.
flash_size – Flash size to set in the image header.
- Keyword Arguments:
version (int) – ESP8266-only, firmware image version.
min_rev (int) – Minimum chip revision required in legacy format.
min_rev_full (int) – Minimum chip revision required in extended format.
max_rev_full (int) – Maximum chip revision allowed in extended format.
secure_pad (bool) – ESP32-only, enable secure padding.
secure_pad_v2 (bool) – Enable version 2 secure padding.
elf_sha256_offset (int) – Offset for storing the ELF file’s SHA-256 hash.
append_digest (bool) – Whether to append a digest to the firmware image.
use_segments (bool) – Use ELF segments instead of sections.
flash_mmu_page_size (str) – MMU page size for flash mapping.
pad_to_size (str) – Pad the final image to a specific flash size.
ram_only_header (bool) – Include only RAM segments and no SHA-256 hash.
- Returns:
The firmware image as bytes if output is None; otherwise, returns None after writing to file. When ESP8266 V1 image is generated, returns a tuple of bytes of IROM data and the rest if output is None; otherwise, returns None after writing to two files.
- esptool.cmds.merge_bin(addr_data: list[tuple[int, str | bytes | IO[bytes]]], chip: str, output: str | None = None, flash_freq: str = 'keep', flash_mode: str = 'keep', flash_size: str = 'keep', format: str = 'raw', **kwargs) bytes | None
Merge multiple binary files into a single output file for flashing to an ESP device.
Take multiple binary files along with their flash addresses and merge them into a unified binary in either raw, UF2, or Intel HEX format. Also apply necessary flash parameters and ensure correct alignment for flashing.
- Parameters:
addr_data – List of (address, data) tuples specifying where to write each file or data in flash memory. The data can be a file path (str), bytes, or a file-like object.
chip – Target ESP device type (e.g.,
"esp32").output – Path to the output file where the merged binary will be written. If None, the merged binary will be returned as bytes.
flash_freq – Flash frequency to set in the image header (
"keep"to retain current).flash_mode – Flash mode to set in the image header (
"keep"to retain current).flash_size – Flash size to set in the image header (
"keep"to retain current).format – Output format (
"raw","uf2", or"hex").
- Keyword Arguments:
target_offset (int) – Starting offset for the merged output.
pad_to_size (str | None) – If specified, pad the output to a specific flash size.
chunk_size (int | None) – Chunk size for UF2 format.
md5_disable (bool) – If True, disable MD5 checks in UF2 format.
- Returns:
The merged binary data as bytes if output is None; otherwise, returns None after writing to file.
- esptool.cmds.image_info(input: str | bytes | IO[bytes] | list[tuple[int, str | bytes | IO[bytes]]], chip: str | None = None) None
Display detailed information about an ESP firmware image.
- Parameters:
input – Path to the firmware image file, opened file-like object, or the image data as bytes. If a list of tuples is provided, each tuple contains an offset and an image data as bytes. Used for merged binary images.
chip – Target ESP device type (e.g.,
"esp32"). If None, the chip type will be automatically detected from the image header.
Utility Functions
- esptool.cmds.version() None
Print the current esptool version.
For more information, refer to the command implementations in esptool/cmds.py.
Low-Level API Reference
Warning
The low-level API provides more control but requires a deeper understanding of the ESP chip, the esptool internals, and the serial protocol. It is recommended to use the public API functions for most use cases.
Also, the low-level internals are not a part of the public API, so they may change in between releases.
Please submit a feature request if you are missing something from the officially supported API.
For granular control and more configuration freedom, you can directly access the low-level methods and attributes of the ESPLoader object and create your own routines. The following is an example of a custom routine to flash the ESP32:
Note
This example code is a very basic implementation of esptool -p /dev/ttyACM0 write-flash 0x10000 firmware.bin
from esptool.cmds import connect_esp
# The port of the connected ESP
PORT = "/dev/ttyACM0"
# The binary file
BIN_FILE = "./firmware.bin"
# Flash offset to flash the binary to
FLASH_ADDRESS = 0x10000
def progress_callback(percent):
print(f"Wrote: {int(percent)}%")
with connect_esp(port=PORT) as esp:
description = esp.get_chip_description()
features = esp.get_chip_features()
print(f"Detected ESP on port {PORT}: {description}")
print("Features:", ", ".join(features))
esp = esp.run_stub()
with open(BIN_FILE, 'rb') as binary:
# Load the binary
binary_data = binary.read()
total_size = len(binary_data)
print(f"Binary size: {total_size} bytes")
# Write binary blocks
esp.flash_begin(total_size, FLASH_ADDRESS)
for i in range(0, total_size, esp.FLASH_WRITE_SIZE):
block = binary_data[i:i + esp.FLASH_WRITE_SIZE]
# Pad the last block
block = block + bytes([0xFF]) * (esp.FLASH_WRITE_SIZE - len(block))
esp.flash_block(block, i + FLASH_ADDRESS)
progress_callback(i / total_size * 100)
esp.flash_finish()
# Reset the chip out of bootloader mode
esp.hard_reset()
For more information, refer to the methods of the ESPLoader class in esptool/loader.py.
Redirecting Output with a Custom Logger
Esptool allows redirecting output by implementing a custom logger class. This can be useful when integrating esptool with graphical user interfaces or other systems where the default console output is not appropriate. When running esptool from a terminal, colors are disabled automatically if the NO_COLOR environment variable is set; see Disabling Color Output for details.
Below is an example demonstrating how to create and use a custom logger:
from esptool.logger import log, TemplateLogger
import sys
class CustomLogger(TemplateLogger):
log_to_file = True
log_file = "esptool.log"
def print(self, message="", *args, **kwargs):
# Print to console
print(f"[CustomLogger]: {message}", *args, **kwargs)
# Optionally log to a file
if self.log_to_file:
with open(self.log_file, "a") as log:
log.write(f"{message}\n")
def note(self, message):
self.print(f"NOTE: {message}")
def warning(self, message):
self.print(f"WARNING: {message}")
def error(self, message):
self.print(message, file=sys.stderr)
def stage(self, finish=False):
# Collapsible stages not needed in this example
pass
def progress_bar(
self,
cur_iter,
total_iters,
prefix = "",
suffix = "",
bar_length: int = 30,
):
# Progress bars replaced with simple percentage output in this example
percent = f"{100 * (cur_iter / float(total_iters)):.1f}"
self.print(f"Finished: {percent}%")
def set_verbosity(self, verbosity):
# Set verbosity level not needed in this example
pass
# Replace the default logger with the custom logger
log.set_logger(CustomLogger())
# From now on, all esptool output will be redirected through the custom logger
# Your code here ...
In this example, the CustomLogger class provides additional functionality such as logging messages to a file, which the original EsptoolLogger (imported from esptool.logger as an initiated object log) doesn’t. The EsptoolLogger.set_logger() method is used to replace the default logger with the custom logger.
To ensure compatibility with esptool, the custom logger should re-implement (or inherit) the following methods from the original EsptoolLogger class (see the reference implementation here), this is enforced by the TemplateLogger abstract class:
print: Handles plain message logging.note: Logs informational messages.warning: Logs warning messages.error: Logs error messages.stage: Starts or ends a collapsible output stage.progress_bar: Displays a progress bar.set_verbosity: Sets the verbosity level for logging.
- class esptool.logger.EsptoolLogger(*args, **kwargs)
Esptool’s default logger.
Subclasses esp_pylib.logger.EspLog so Rich rendering, IDE WebSocket forwarding, collapsible stages, and
--silentgating are shared with the rest of the Espressif tools, while keeping esptool-specific behaviour:_stage_can_collapse honours
_smart_features:autodefers to esp-pylib’s TTY detection,compactforces collapsing on, and--traceforces it off.print keeps historical builtin-
printsemantics (flush,soft_wrap, lazysys.stdout).warn / err are inherited from EspLog (canonical).
warning / error forward to them for backward compatibility.
- print(*args, **kwargs) None
Plain output with esptool’s historical
printsemantics.soft_wrap=Trueis the default so Rich does not break long lines at the console width. Aflush=Truekwarg some callers pass is stripped here: Rich’sConsole.printalready flushes the underlying stream once per call (the consoles are never used in a buffering context) and rejects an explicitflushargument.Following a reassigned
sys.stdout(e.g.redirect_stdout) and stage newline accounting are both handled by EspLog.print.
- note(*args: Any) None
Informational note (blue) with ‘NOTE: ‘ prefix.
Goes to stdout by default; redirected by set_info_stream.
- warning(message: str, suggestion: str | None = None) None
Backward-compatible alias for warn.
- error(message: str, suggestion: str | None = None) None
Backward-compatible alias for err.
- stage(finish: bool = False) None
Start or finish a collapsible output stage.
While a stage is active, ordinary print output on stdout is discarded when the stage finishes successfully (TTY + normal verbosity). note and warn are buffered and re-printed after collapse. In verbose mode, or on non-interactive stdout, stages are inert markers (output is never removed). Matches esptool’s
log.stage()behaviour.
- progress_bar(cur_iter: int, total_iters: int, prefix: str = '', suffix: str = '', bar_length: int = 30) None
Print progress using Rich ProgressBar.
When the active console can’t render a dim background bar (
no_coloror nocolor_system), the bar is rendered as a fixed-width plain string so the suffix stays in the same column across redraws. Glyph selection uses the same Richascii_only/legacy_windowsrules as ProgressBar (=/>vs━/╸). When color is available, Rich’s ProgressBar handles encoding and legacy Windows rendering.
- set_verbosity(verbosity)
Accept esptool’s CLI verbosity strings + esp-pylib levels.
Historical values (
auto,verbose,silent,compact) map onto Verbosity.verboseisVerbosity.VERBOSEso it enables debug and full progress-bar lines like other esp-pylib tools.compact/autoonly adjust stage collapsing (_smart_features);silentisVerbosity.SILENT.
These methods are essential for maintaining proper integration and behavior with esptool. Additionally, all output printing should be made using log.print() (or the respective method, such as log.note() or log.warn()) instead of the standard print() function to ensure the output is routed through the custom logger. This ensures consistency and allows the custom logger to handle all output appropriately. You can further customize this logger to fit your application’s needs, such as integrating with GUI components or advanced logging frameworks.