Practical Example: Accepts Host, Port, and Timeout

๐Ÿท๏ธ Python Scripting Best Practices / Command-Line Arguments via Argparse


๐Ÿง  Context Introduction

When building network tools or automation scripts, you'll often need to accept connection details like a host, port, and timeout value. Hardcoding these values inside your script is inflexible and forces you to edit the code every time you need to test a different server. Instead, using argparse allows you to pass these values dynamically when running your script from the terminal. This practical example walks through building a simple connectivity checker that accepts all three parameters cleanly.


โš™๏ธ What We're Building

We'll create a script that: - Accepts a hostname or IP address (required) - Accepts a port number (required) - Accepts a timeout in seconds (optional, with a default value) - Attempts to connect to the specified host and port - Reports whether the connection succeeded or failed


๐Ÿ› ๏ธ Step-by-Step Breakdown

๐Ÿ“ฆ Importing Required Modules

The script needs two standard Python libraries: - argparse โ€“ for parsing command-line arguments - socket โ€“ for making the actual network connection attempt

Both are built into Python, so no additional installation is needed.


๐Ÿงฉ Defining the Arguments

We define three arguments using argparse:

  • host โ€“ Positional argument (required). This is the target server address.
  • port โ€“ Positional argument (required). This is the target port number.
  • --timeout โ€“ Optional flag argument. If not provided, a default value of 5 seconds is used.

Using positional arguments for host and port makes the script intuitive to use. The timeout is optional because a sensible default (5 seconds) works for most cases.


๐Ÿ” Argument Type Validation

For the port argument, we add a type check to ensure only valid port numbers (1โ€“65535) are accepted. This prevents common mistakes like typos or invalid values. If someone passes a port outside this range, argparse automatically shows a helpful error message.

For the timeout argument, we use a float type so users can pass values like 2.5 for half-second precision.


๐Ÿ—๏ธ Building the Connection Logic

The core logic follows these steps:

  1. Create a new TCP socket using the socket module
  2. Set the socket's timeout to the value provided (or the default)
  3. Attempt to connect to the specified host and port
  4. If the connection succeeds, print a success message and close the socket
  5. If the connection fails (timeout, connection refused, or unreachable host), print a descriptive error message

The socket's timeout is critical โ€“ without it, the script could hang indefinitely waiting for an unresponsive host.


๐Ÿงช Handling Errors Gracefully

The script catches two specific exceptions:

  • socket.timeout โ€“ Raised when the connection takes longer than the specified timeout
  • socket.error โ€“ A broader exception that covers connection refused, host unreachable, and other network errors

Each exception prints a clear, user-friendly message so the engineer knows exactly what went wrong.


๐Ÿ“Š Comparison: Hardcoded vs. Argparse Approach

Feature Hardcoded Values Argparse Approach
Flexibility Must edit code to change values Change values at runtime via command line
Reusability One-time use per script Share with team without code changes
Error handling Manual validation needed Automatic type checking and validation
Documentation No built-in help Auto-generated -h or --help output
Default values Hard to manage Easy to set and override

๐Ÿ•ต๏ธ How to Run the Script

Once the script is saved (for example, as check_connection.py), you run it from the terminal like this:

Basic usage with required arguments:
python check_connection.py google.com 80

With a custom timeout:
python check_connection.py google.com 80 --timeout 10

With a shorter timeout:
python check_connection.py 192.168.1.1 22 --timeout 2.5

Viewing the built-in help:
python check_connection.py --help

The help output automatically shows all arguments, their types, and whether they are required or optional.


โœ… Expected Behavior Examples

Successful connection:
If the host and port are reachable, the script prints a message like:
Connection to google.com on port 80 succeeded

Connection timeout:
If the host is unreachable or the timeout expires, the script prints:
Connection to 10.0.0.99 on port 8080 timed out after 3 seconds

Connection refused:
If the host is reachable but the port is closed, the script prints:
Connection to localhost on port 9999 failed: Connection refused

Invalid port number:
If someone passes a port like 70000, argparse automatically shows:
error: argument port: invalid int value: '70000'


๐Ÿงน Best Practices Demonstrated

  • Separation of concerns โ€“ Argument parsing is handled separately from the connection logic
  • Sensible defaults โ€“ Timeout defaults to 5 seconds, reducing required typing
  • Clear error messages โ€“ Each failure mode has a distinct, descriptive message
  • Input validation โ€“ Port range checking prevents invalid values early
  • Self-documenting code โ€“ The --help flag provides instant documentation

๐Ÿš€ Next Steps

Once you're comfortable with this pattern, you can extend the script to: - Accept multiple ports and scan them in sequence - Add a --verbose flag for detailed output - Save results to a file using a --output argument - Support both TCP and UDP connections via a --protocol argument

This foundational pattern โ€“ accepting host, port, and timeout โ€“ appears in countless real-world tools like port scanners, health checkers, and deployment scripts. Mastering it gives you a reusable template for any network-related automation task.


This example shows how to accept host, port, and timeout values from the command line using Python's argparse module.


๐ŸŸข Example 1: Basic host, port, and timeout arguments

This example demonstrates the simplest way to accept three command-line arguments.

import argparse

parser = argparse.ArgumentParser()
parser.add_argument("--host")
parser.add_argument("--port")
parser.add_argument("--timeout")
args = parser.parse_args()

print(args.host)
print(args.port)
print(args.timeout)

๐Ÿ“ค Output: None (if no arguments provided)


๐ŸŸก Example 2: Adding default values for all arguments

This example shows how to set default values when no arguments are provided.

import argparse

parser = argparse.ArgumentParser()
parser.add_argument("--host", default="localhost")
parser.add_argument("--port", default=8080)
parser.add_argument("--timeout", default=30)
args = parser.parse_args()

print(args.host)
print(args.port)
print(args.timeout)

๐Ÿ“ค Output: localhost 8080 30


๐ŸŸ  Example 3: Making host a required argument

This example shows how to make the host argument mandatory while keeping port and timeout optional.

import argparse

parser = argparse.ArgumentParser()
parser.add_argument("--host", required=True)
parser.add_argument("--port", default=8080)
parser.add_argument("--timeout", default=30)
args = parser.parse_args()

print("Connecting to", args.host)
print("Using port", args.port)
print("Timeout set to", args.timeout, "seconds")

๐Ÿ“ค Output: Connecting to 192.168.1.100 Using port 8080 Timeout set to 30 seconds


๐Ÿ”ต Example 4: Adding help text for each argument

This example shows how to add descriptive help text that appears when users run with --help.

import argparse

parser = argparse.ArgumentParser()
parser.add_argument("--host", required=True, help="Target hostname or IP address")
parser.add_argument("--port", type=int, default=8080, help="Port number to connect to")
parser.add_argument("--timeout", type=int, default=30, help="Connection timeout in seconds")
args = parser.parse_args()

print("Connecting to", args.host)
print("Using port", args.port)
print("Timeout set to", args.timeout, "seconds")

๐Ÿ“ค Output: Connecting to example.com Using port 443 Timeout set to 60 seconds


๐ŸŸฃ Example 5: Validating port and timeout ranges

This example shows how to validate that port and timeout values fall within acceptable ranges.

import argparse

parser = argparse.ArgumentParser()
parser.add_argument("--host", required=True, help="Target hostname or IP address")
parser.add_argument("--port", type=int, default=8080, help="Port number (1-65535)")
parser.add_argument("--timeout", type=int, default=30, help="Timeout in seconds (1-300)")
args = parser.parse_args()

if args.port < 1 or args.port > 65535:
    print("Error: Port must be between 1 and 65535")
    exit(1)

if args.timeout < 1 or args.timeout > 300:
    print("Error: Timeout must be between 1 and 300 seconds")
    exit(1)

print("Connecting to", args.host)
print("Using port", args.port)
print("Timeout set to", args.timeout, "seconds")

๐Ÿ“ค Output: Connecting to 10.0.0.1 Using port 22 Timeout set to 10 seconds


Comparison Table

Feature Example 1 Example 2 Example 3 Example 4 Example 5
Default values No Yes Partial Partial Partial
Required host No No Yes Yes Yes
Help text No No No Yes Yes
Type validation No No No Yes Yes
Range checking No No No No Yes

๐Ÿง  Context Introduction

When building network tools or automation scripts, you'll often need to accept connection details like a host, port, and timeout value. Hardcoding these values inside your script is inflexible and forces you to edit the code every time you need to test a different server. Instead, using argparse allows you to pass these values dynamically when running your script from the terminal. This practical example walks through building a simple connectivity checker that accepts all three parameters cleanly.


โš™๏ธ What We're Building

We'll create a script that: - Accepts a hostname or IP address (required) - Accepts a port number (required) - Accepts a timeout in seconds (optional, with a default value) - Attempts to connect to the specified host and port - Reports whether the connection succeeded or failed


๐Ÿ› ๏ธ Step-by-Step Breakdown

๐Ÿ“ฆ Importing Required Modules

The script needs two standard Python libraries: - argparse โ€“ for parsing command-line arguments - socket โ€“ for making the actual network connection attempt

Both are built into Python, so no additional installation is needed.


๐Ÿงฉ Defining the Arguments

We define three arguments using argparse:

  • host โ€“ Positional argument (required). This is the target server address.
  • port โ€“ Positional argument (required). This is the target port number.
  • --timeout โ€“ Optional flag argument. If not provided, a default value of 5 seconds is used.

Using positional arguments for host and port makes the script intuitive to use. The timeout is optional because a sensible default (5 seconds) works for most cases.


๐Ÿ” Argument Type Validation

For the port argument, we add a type check to ensure only valid port numbers (1โ€“65535) are accepted. This prevents common mistakes like typos or invalid values. If someone passes a port outside this range, argparse automatically shows a helpful error message.

For the timeout argument, we use a float type so users can pass values like 2.5 for half-second precision.


๐Ÿ—๏ธ Building the Connection Logic

The core logic follows these steps:

  1. Create a new TCP socket using the socket module
  2. Set the socket's timeout to the value provided (or the default)
  3. Attempt to connect to the specified host and port
  4. If the connection succeeds, print a success message and close the socket
  5. If the connection fails (timeout, connection refused, or unreachable host), print a descriptive error message

The socket's timeout is critical โ€“ without it, the script could hang indefinitely waiting for an unresponsive host.


๐Ÿงช Handling Errors Gracefully

The script catches two specific exceptions:

  • socket.timeout โ€“ Raised when the connection takes longer than the specified timeout
  • socket.error โ€“ A broader exception that covers connection refused, host unreachable, and other network errors

Each exception prints a clear, user-friendly message so the engineer knows exactly what went wrong.


๐Ÿ“Š Comparison: Hardcoded vs. Argparse Approach

Feature Hardcoded Values Argparse Approach
Flexibility Must edit code to change values Change values at runtime via command line
Reusability One-time use per script Share with team without code changes
Error handling Manual validation needed Automatic type checking and validation
Documentation No built-in help Auto-generated -h or --help output
Default values Hard to manage Easy to set and override

๐Ÿ•ต๏ธ How to Run the Script

Once the script is saved (for example, as check_connection.py), you run it from the terminal like this:

Basic usage with required arguments:
python check_connection.py google.com 80

With a custom timeout:
python check_connection.py google.com 80 --timeout 10

With a shorter timeout:
python check_connection.py 192.168.1.1 22 --timeout 2.5

Viewing the built-in help:
python check_connection.py --help

The help output automatically shows all arguments, their types, and whether they are required or optional.


โœ… Expected Behavior Examples

Successful connection:
If the host and port are reachable, the script prints a message like:
Connection to google.com on port 80 succeeded

Connection timeout:
If the host is unreachable or the timeout expires, the script prints:
Connection to 10.0.0.99 on port 8080 timed out after 3 seconds

Connection refused:
If the host is reachable but the port is closed, the script prints:
Connection to localhost on port 9999 failed: Connection refused

Invalid port number:
If someone passes a port like 70000, argparse automatically shows:
error: argument port: invalid int value: '70000'


๐Ÿงน Best Practices Demonstrated

  • Separation of concerns โ€“ Argument parsing is handled separately from the connection logic
  • Sensible defaults โ€“ Timeout defaults to 5 seconds, reducing required typing
  • Clear error messages โ€“ Each failure mode has a distinct, descriptive message
  • Input validation โ€“ Port range checking prevents invalid values early
  • Self-documenting code โ€“ The --help flag provides instant documentation

๐Ÿš€ Next Steps

Once you're comfortable with this pattern, you can extend the script to: - Accept multiple ports and scan them in sequence - Add a --verbose flag for detailed output - Save results to a file using a --output argument - Support both TCP and UDP connections via a --protocol argument

This foundational pattern โ€“ accepting host, port, and timeout โ€“ appears in countless real-world tools like port scanners, health checkers, and deployment scripts. Mastering it gives you a reusable template for any network-related automation task.

Interactive Views

You are currently in ๐Ÿ“š All-in-One mode. Use the tabs at the top to switch to ๐Ÿ“– Theory Only or ๐Ÿ’ป Code Only views.

This example shows how to accept host, port, and timeout values from the command line using Python's argparse module.


๐ŸŸข Example 1: Basic host, port, and timeout arguments

This example demonstrates the simplest way to accept three command-line arguments.

import argparse

parser = argparse.ArgumentParser()
parser.add_argument("--host")
parser.add_argument("--port")
parser.add_argument("--timeout")
args = parser.parse_args()

print(args.host)
print(args.port)
print(args.timeout)

๐Ÿ“ค Output: None (if no arguments provided)


๐ŸŸก Example 2: Adding default values for all arguments

This example shows how to set default values when no arguments are provided.

import argparse

parser = argparse.ArgumentParser()
parser.add_argument("--host", default="localhost")
parser.add_argument("--port", default=8080)
parser.add_argument("--timeout", default=30)
args = parser.parse_args()

print(args.host)
print(args.port)
print(args.timeout)

๐Ÿ“ค Output: localhost 8080 30


๐ŸŸ  Example 3: Making host a required argument

This example shows how to make the host argument mandatory while keeping port and timeout optional.

import argparse

parser = argparse.ArgumentParser()
parser.add_argument("--host", required=True)
parser.add_argument("--port", default=8080)
parser.add_argument("--timeout", default=30)
args = parser.parse_args()

print("Connecting to", args.host)
print("Using port", args.port)
print("Timeout set to", args.timeout, "seconds")

๐Ÿ“ค Output: Connecting to 192.168.1.100 Using port 8080 Timeout set to 30 seconds


๐Ÿ”ต Example 4: Adding help text for each argument

This example shows how to add descriptive help text that appears when users run with --help.

import argparse

parser = argparse.ArgumentParser()
parser.add_argument("--host", required=True, help="Target hostname or IP address")
parser.add_argument("--port", type=int, default=8080, help="Port number to connect to")
parser.add_argument("--timeout", type=int, default=30, help="Connection timeout in seconds")
args = parser.parse_args()

print("Connecting to", args.host)
print("Using port", args.port)
print("Timeout set to", args.timeout, "seconds")

๐Ÿ“ค Output: Connecting to example.com Using port 443 Timeout set to 60 seconds


๐ŸŸฃ Example 5: Validating port and timeout ranges

This example shows how to validate that port and timeout values fall within acceptable ranges.

import argparse

parser = argparse.ArgumentParser()
parser.add_argument("--host", required=True, help="Target hostname or IP address")
parser.add_argument("--port", type=int, default=8080, help="Port number (1-65535)")
parser.add_argument("--timeout", type=int, default=30, help="Timeout in seconds (1-300)")
args = parser.parse_args()

if args.port < 1 or args.port > 65535:
    print("Error: Port must be between 1 and 65535")
    exit(1)

if args.timeout < 1 or args.timeout > 300:
    print("Error: Timeout must be between 1 and 300 seconds")
    exit(1)

print("Connecting to", args.host)
print("Using port", args.port)
print("Timeout set to", args.timeout, "seconds")

๐Ÿ“ค Output: Connecting to 10.0.0.1 Using port 22 Timeout set to 10 seconds


Comparison Table

Feature Example 1 Example 2 Example 3 Example 4 Example 5
Default values No Yes Partial Partial Partial
Required host No No Yes Yes Yes
Help text No No No Yes Yes
Type validation No No No Yes Yes
Range checking No No No No Yes