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:
- Create a new TCP socket using the socket module
- Set the socket's timeout to the value provided (or the default)
- Attempt to connect to the specified host and port
- If the connection succeeds, print a success message and close the socket
- 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:
- Create a new TCP socket using the socket module
- Set the socket's timeout to the value provided (or the default)
- Attempt to connect to the specified host and port
- If the connection succeeds, print a success message and close the socket
- 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 |