A pure python3 version of ICMP ping implementation using raw socket.
npx @tessl/cli install tessl/pypi-ping3@5.1.0A pure Python 3 implementation of ICMP ping functionality using raw sockets. ping3 enables network connectivity testing and monitoring through both programmatic and command-line interfaces, supporting IPv4 and IPv6 protocols with comprehensive error handling and configurable options.
pip install ping3Basic ping functionality:
from ping3 import ping, verbose_pingModule configuration:
import ping3
ping3.DEBUG = True # Enable debug output (default False)
ping3.EXCEPTIONS = True # Raise exceptions instead of returning None/False (default False)Exception handling:
from ping3.errors import (
PingError, Timeout, HostUnknown,
DestinationUnreachable, DestinationHostUnreachable,
TimeToLiveExpired, TimeExceeded,
AddressUnreachable, PortUnreachable
)ICMP constants (advanced usage):
from ping3.enums import (
ICMP_DEFAULT_CODE,
IcmpV4Type, IcmpV6Type,
IcmpV4DestinationUnreachableCode, IcmpV6DestinationUnreachableCode,
IcmpTimeExceededCode
)from ping3 import ping, verbose_ping
# Simple ping - returns delay in seconds
delay = ping('example.com')
if delay is None:
print("Timeout")
elif delay is False:
print("Error (host unreachable or unknown)")
else:
print(f"Ping successful: {delay:.3f}s")
# Ping with custom timeout and get result in milliseconds
delay = ping('8.8.8.8', timeout=2, unit='ms')
if delay:
print(f"Google DNS: {delay:.1f}ms")
# IPv6 ping
delay = ping('2001:4860:4860::8888', version=6)
# Ping with custom options
delay = ping('example.com',
timeout=10, # 10 second timeout
ttl=64, # Time-to-live
size=128, # Payload size in bytes
src_addr='192.168.1.100', # Source IP (multi-interface)
interface='eth0', # Linux only - network interface
seq=5) # ICMP sequence number
# Verbose ping (like command line ping)
verbose_ping('example.com', count=4, interval=1)
# Output:
# ping 'example.com' ... 215ms
# ping 'example.com' ... 216ms
# ping 'example.com' ... 219ms
# ping 'example.com' ... 217msping3 implements ICMP ping functionality through a clean, socket-based architecture:
SOCK_RAW for full control over ICMP packet creation and parsingSOCK_DGRAM on permission errors (Linux), where the kernel handles some ICMP detailsNone/False by default, or raises exceptions when EXCEPTIONS=TrueThis design provides both simplicity for basic use cases and full control for advanced network diagnostics.
Primary ping functionality for sending ICMP packets and measuring network latency.
def ping(dest_addr: str, timeout: int = 4, unit: str = "s", src_addr: str = "",
ttl=None, seq: int = 0, size: int = 56, interface: str = "",
version=None) -> float | None | bool:
"""
Send one ping to destination address with configurable options.
Parameters:
- dest_addr (str): Destination IP address or domain name (e.g., "192.168.1.1", "example.com", "2001:db8::1")
- timeout (int): Response timeout in seconds (default 4)
- unit (str): Return unit "s" for seconds or "ms" for milliseconds (default "s")
- src_addr (str): Source IP address for multi-interface systems (default "")
- ttl (int|None): Time-To-Live value, None uses OS default (default None)
- seq (int): ICMP packet sequence number (default 0)
- size (int): ICMP payload size in bytes (default 56)
- interface (str): Linux only - network interface name like "eth0" (default "")
- version (int|None): IP version 4 or 6, None for auto-detect (default None)
Returns:
float|None|False: Delay in seconds/milliseconds, None on timeout, False on error
Raises:
PingError: Any ping-related error if ping3.EXCEPTIONS is True
"""
def verbose_ping(dest_addr: str, count: int = 4, interval: float = 0,
*args, **kwargs) -> None:
"""
Send multiple pings with formatted output display.
Parameters:
- dest_addr (str): Destination IP address or domain name
- count (int): Number of pings to send, 0 for infinite loop (default 4)
- interval (float): Seconds between pings, 0 for immediate (default 0)
- *args, **kwargs: All ping() arguments except seq
Returns:
None: Prints formatted results to stdout
"""# Module-level configuration constants
DEBUG: bool # Enable debug output (default False)
EXCEPTIONS: bool # Raise exceptions instead of returning None/False (default False)
LOGGER: object # Logger instance for debug output (default None)
__version__: str # Package version string (currently "5.1.5")The package provides a ping3 command-line tool with full argument support:
# Basic usage
ping3 example.com
# With options
ping3 -c 10 -t 2 -i 0.5 -s 64 example.com
# IPv6 ping
ping3 -6 2001:4860:4860::8888
# Help
ping3 --helpclass PingError(Exception):
"""Base exception for all ping-related errors."""
class TimeExceeded(PingError):
"""Base exception for time-related errors."""
class TimeToLiveExpired(TimeExceeded):
"""Exception when TTL expires during routing."""
# Attributes: ip_header, icmp_header, message
class DestinationUnreachable(PingError):
"""Base exception for unreachable destinations."""
# Attributes: ip_header, icmp_header, message
class DestinationHostUnreachable(DestinationUnreachable):
"""Exception for unreachable hosts (IPv4)."""
# Attributes: ip_header, icmp_header, message
class AddressUnreachable(DestinationUnreachable):
"""Exception for unreachable IPv6 addresses."""
# Attributes: ip_header, icmp_header, message
class PortUnreachable(DestinationUnreachable):
"""Exception for unreachable ports."""
# Attributes: ip_header, icmp_header, message
class HostUnknown(PingError):
"""Exception for unresolvable hostnames."""
# Attributes: dest_addr, message
class Timeout(PingError):
"""Exception for ping timeouts."""
# Attributes: timeout, messagefrom ping3 import ping
from ping3.errors import PingError, Timeout, HostUnknown
# Method 1: Check return values (default behavior)
result = ping('example.com')
if result is None:
print("Ping timed out")
elif result is False:
print("Ping failed (host unreachable or unknown)")
else:
print(f"Ping successful: {result:.3f}s")
# Method 2: Exception handling
import ping3
ping3.EXCEPTIONS = True # Enable exception mode
try:
delay = ping('example.com')
print(f"Ping successful: {delay:.3f}s")
except Timeout:
print("Ping timed out")
except HostUnknown:
print("Host could not be resolved")
except PingError as e:
print(f"Ping failed: {e}")ICMP_DEFAULT_CODE = 0 # Default code for ECHO_REPLY and ECHO_REQUEST
class IcmpV4Type(enum.IntEnum):
"""ICMPv4 message type constants."""
ECHO_REPLY = 0
DESTINATION_UNREACHABLE = 3
REDIRECT_MESSAGE = 5
ECHO_REQUEST = 8
ROUTER_ADVERTISEMENT = 9
ROUTER_SOLICITATION = 10
TIME_EXCEEDED = 11
BAD_IP_HEADER = 12
TIMESTAMP = 13
TIMESTAMP_REPLY = 14
class IcmpV6Type(enum.IntEnum):
"""ICMPv6 message type constants."""
DESTINATION_UNREACHABLE = 1
TIME_EXCEEDED = 3
ECHO_REQUEST = 128
ECHO_REPLY = 129
ROUTER_SOLICITATION = 133
ROUTER_ADVERTISEMENT = 134
REDIRECT_MESSAGE = 137class IcmpV4DestinationUnreachableCode(enum.IntEnum):
"""ICMPv4 destination unreachable code constants."""
DESTINATION_NETWORK_UNREACHABLE = 0
DESTINATION_HOST_UNREACHABLE = 1
DESTINATION_PROTOCOL_UNREACHABLE = 2
DESTINATION_PORT_UNREACHABLE = 3
FRAGMENTATION_REQUIRED = 4
SOURCE_ROUTE_FAILED = 5
DESTINATION_NETWORK_UNKNOWN = 6
DESTINATION_HOST_UNKNOWN = 7
SOURCE_HOST_ISOLATED = 8
NETWORK_ADMINISTRATIVELY_PROHIBITED = 9
HOST_ADMINISTRATIVELY_PROHIBITED = 10
NETWORK_UNREACHABLE_FOR_TOS = 11
HOST_UNREACHABLE_FOR_TOS = 12
COMMUNICATION_ADMINISTRATIVELY_PROHIBITED = 13
HOST_PRECEDENCE_VIOLATION = 14
PRECEDENCE_CUTOFF_IN_EFFECT = 15
class IcmpV6DestinationUnreachableCode(enum.IntEnum):
"""ICMPv6 destination unreachable code constants."""
NO_ROUTE_TO_DESTINATION = 0
COMMUNICATION_PROHIBITED = 1
BEYOND_SCOPE = 2
ADDRESS_UNREACHABLE = 3
PORT_UNREACHABLE = 4
SOURCE_ADDRESS_FAILED = 5
REJECT_ROUTE_TO_DESTINATION = 6
ERROR_IN_SOURCE_ROUTING_HEADER = 7
class IcmpTimeExceededCode(enum.IntEnum):
"""ICMP time exceeded code constants for both IPv4 and IPv6."""
TTL_EXPIRED = 0
FRAGMENT_REASSEMBLY_TIME_EXCEEDED = 1ping3 automatically handles socket type selection:
SOCK_RAW first for full controlSOCK_DGRAM on permission errors (Linux)