Python 3
Introduction
The Python 3 Router App provides a full-featured Python 3 environment on Advantech routers. Once installed, Python extends the router's capabilities with a versatile high-level scripting language suitable for:
- Automation of router management tasks.
- Custom data collection and analysis directly at the edge.
- Development of IoT solutions and integrations.
- Enhanced network monitoring and diagnostics.
Compared to the Python 3 Lite Router App, this version includes the full set of development tools:
| Feature | Python 3 | Python 3 Lite |
|---|---|---|
| Python version | 3.x | 3.x |
pip package installer | ✓ | — |
venv virtual environments | ✓ | — |
hashlib | Native (faster) | Pure-Python |
| UNICODE support | Full | Limited |
| Resource usage | Higher | Lower |
The Python 3 Router App is recommended for complex tasks, development workflows, and when router resources (CPU, RAM, storage) are sufficient. For resource-constrained deployments or simple scripting, use the Python 3 Lite Router App instead.
Installation
Prerequisites
Before installing, ensure:
- Sufficient storage space: Python and its libraries can consume significant storage. Check available disk space on the Router Apps page of the router's web interface.
- Internet connectivity (optional): Required if you plan to use
pipto download packages from PyPI. The Router App package itself is obtained separately.
Installation Procedure
To install the Python 3 Router App, follow the instructions in the Configuration Manual, section Customization → Router Apps.
Verifying the Installation
Once installed, verify Python is available and working correctly:
- Access the router's command-line interface (CLI).
- Check the installed Python version:
python3 --versionThis should output the installed version, for example Python 3.x.y.
- Test
pip:
pip3 --version- Test importing a standard module:
python3 -c "import hashlib; print(hashlib)"If these commands execute without error, Python is ready to use.
Using Python
Interactive Python Shell
The Python interactive shell (REPL — Read-Eval-Print Loop) lets you type Python code directly and see immediate results. It is useful for testing code snippets or exploring Python features.
- Log in to the router's CLI.
- Start the Python interpreter:
python3The Python prompt (>>>) appears.
- Enter Python commands:
>>> print("Hello from Advantech Router!")
Hello from Advantech Router!
>>> a = 10
>>> b = 20
>>> print(a + b)
30
>>> import os
>>> os.uname()- To exit, type:
>>> exit()Or press Ctrl-D.
Executing Python Scripts
For more complex tasks, write Python code into .py files and execute them as scripts.
Creating or transferring scripts:
- Using
vi: Create or edit scripts directly on the router. Refer to the BusyBox vi tutorial for guidance. - Transferring via
scp: Write scripts on your development computer and transfer them to the router:
scp myscript.py admin@ROUTER_IP_ADDRESS:/tmp/Note that /tmp is a RAM disk — its contents are cleared on reboot.
Running a script:
- Add a shebang line at the top of the script:
#!/usr/bin/python3
print("This is my Python script.")- Make the script executable:
chmod +x /path/to/your/myscript.py- Run the script:
python3 /path/to/your/myscript.pyPassing Command-Line Arguments
Command-line arguments are accessible within the script via the sys.argv list. Example myscript_args.py:
#!/usr/bin/python3
import sys
print(f"Script name: {sys.argv[0]}")
if len(sys.argv) > 1:
print(f"First argument: {sys.argv[1]}")
if len(sys.argv) > 2:
print(f"Second argument: {sys.argv[2]}")Run with arguments:
python3 myscript_args.py arg1 "another argument"Output:
Script name: myscript_args.py
First argument: arg1
Second argument: another argumentStandard Library Modules
The following standard library modules are particularly useful for router scripting:
| Module | Description |
|---|---|
os | Operating system interaction: file system operations, environment variables, os.system(). |
subprocess | Running external shell commands with full control over input/output streams. Recommended over os.system(). |
sys | System parameters and functions: command-line arguments (sys.argv), exit codes (sys.exit()). |
re | Regular expressions for text pattern matching and manipulation, useful for parsing log files. |
datetime | Date and time handling, for example timestamping log entries. |
socket | Low-level network operations. |
json | Parsing and generating JSON data, common in APIs and configurations. |
Additional third-party modules can be installed using pip3. See Using pip.
Advanced Features
The following tools are available in the Python 3 Router App only and are not included in the Python 3 Lite Router App.
Using pip to Install Third-Party Libraries
pip3 is the Python package installer, allowing you to download and install packages from the Python Package Index (PyPI).
Basic commands:
| Command | Description |
|---|---|
pip3 install package_name | Install a package. |
pip3 install package_name==1.2.3 | Install a specific version. |
pip3 install --upgrade package_name | Upgrade an installed package. |
pip3 list | List all installed packages. |
pip3 show package_name | Show information about a package. |
pip3 uninstall package_name | Uninstall a package. |
Example — installing the requests library:
pip3 install requestsConsiderations:
- Storage space: Third-party libraries can consume significant storage. Install only what is necessary.
- Internet connectivity: The router needs internet access to download packages from PyPI.
- Compilation: Some packages require compilation of C/C++ extensions. The router environment may lack the necessary compilers or development headers. Prefer pure-Python packages or pre-compiled ARM Linux wheels (
.whlfiles). - Permissions: Root or administrative privileges are typically required to install packages globally.
Using venv for Isolated Virtual Environments
venv creates isolated Python virtual environments, each with its own independent set of installed packages.
Benefits:
- Prevents version conflicts between projects that require different library versions.
- Keeps the global Python environment clean.
- Makes a project's environment easier to replicate.
Basic usage:
- Create a virtual environment in your project directory:
python3 -m venv my_project_env- Activate the environment:
source my_project_env/bin/activateThe shell prompt changes to indicate the active environment, for example (my_project_env) user@router:~$.
- Install packages into the environment:
(my_project_env) $ pip3 install requests- Deactivate the environment when done:
(my_project_env) $ deactivate- Delete the environment by removing its directory:
rm -rf my_project_envConsiderations on routers:
- Storage: Each virtual environment stores its own packages, consuming additional storage. Use judiciously on resource-constrained routers.
- Automated scripts: For cron jobs or startup scripts, call the environment's Python interpreter directly rather than sourcing the activate script:
/path/to/my_project_env/bin/python your_script.pyDevelopment Notes
Developing Python scripts for Advantech routers requires consideration of their specific operating environment, which is typically based on BusyBox with inherent resource constraints.
BusyBox environment: BusyBox provides a compact set of Unix utilities with fewer options and sometimes slightly different behavior compared to full GNU equivalents. Scripts calling external commands should account for these differences.
Subprocess for command execution: Python's
subprocessmodule is strongly recommended overos.system()for running external shell commands. It provides better control over input/output streams and error handling.On-router text editing: The primary text editor available directly on the router is
vi. A BusyBox vi tutorial is available online.File system and volatility: The
/tmpdirectory is a RAM disk (tmpfs) — its contents are cleared on reboot. For persistent storage, use/opt,/mnt/user, or an attached USB drive, depending on the router model and configuration.Permissions: Python scripts require execute permissions (
chmod +x script.py) to run directly. Privileged operations may require root access.Resource constraints: Embedded routers have limited CPU, RAM, and storage. Write efficient code and avoid memory-intensive operations or unnecessarily large libraries.
Router SDK module (
um): For interacting with router-specific hardware — such as GPIOs, cellular signal strength, device temperature, expansion port configurations, or generating content for the router's web interface — Advantech provides theumPython module as part of the Advantech SDK. Refer to the SDK documentation for your target platform for details.Packages with C extensions: If a required package includes C extensions,
pipon the router may be unable to build them due to missing compilers or development headers. In such cases: cross-compile on a development machine using an ARM-targeted toolchain, find a pre-compiled ARM Linux wheel, or use a pure-Python alternative.
Script Examples
The following examples demonstrate practical use cases for Python on an Advantech router. All scripts are run from the router's CLI.
Gathering System Information
This script displays basic system information: uptime, memory usage, disk space, and hostname. Save the code below into a file named system_info.py.
#!/usr/bin/python3
import subprocess
print("Gathering Basic System Information...\n")
print("--- System Uptime ---")
try:
with open("/proc/uptime", "r") as f:
uptime_seconds = float(f.readline().split()[0])
days = int(uptime_seconds // (24 * 3600))
uptime_seconds %= (24 * 3600)
hours = int(uptime_seconds // 3600)
uptime_seconds %= 3600
minutes = int(uptime_seconds // 60)
seconds = int(uptime_seconds % 60)
print(f"System has been up for: {days} days, {hours} hours, {minutes} minutes, {seconds} seconds.")
except Exception as e:
print(f"Could not get uptime: {e}")
print()
print("--- Memory Usage ---")
try:
result = subprocess.run("free", shell=True, capture_output=True, text=True, check=True)
print(result.stdout.strip())
print("(Output is typically in kilobytes)")
except Exception as e:
print(f"Could not get memory usage: {e}")
print()
print("--- Disk Space ---")
try:
result = subprocess.run("df -k", shell=True, capture_output=True, text=True, check=True)
print(result.stdout.strip())
print("(Output is in 1K-blocks/kilobytes)")
except Exception as e:
print(f"Could not get disk space: {e}")
print()
print("--- Hostname ---")
try:
with open("/proc/sys/kernel/hostname", "r") as f:
hostname = f.read().strip()
print(hostname)
except Exception as e:
print(f"Could not get hostname: {e}")
print()The script reads uptime directly from /proc/uptime and the hostname from /proc/sys/kernel/hostname. Memory usage and disk space are retrieved by running free and df -k via subprocess. Each section uses a try...except block to handle errors gracefully.
Example output:
Gathering Basic System Information...
--- System Uptime ---
System has been up for: 0 days, 1 hours, 10 minutes, 34 seconds.
--- Memory Usage ---
total used free shared buff/cache available
Mem: 503840 38604 448744 184 16492 456496
Swap: 0 0 0
(Output is typically in kilobytes)
--- Disk Space ---
Filesystem 1024-blocks Used Available Use% Mounted on
/dev/root 64512 23544 40968 36% /
devtmpfs 251408 0 251408 0% /dev
none 251920 0 251920 0% /tmp
none 50384 184 50200 0% /var
/dev/mtdblock7 131072 19812 111260 15% /opt
/dev/mtdblock8 128 36 92 28% /var/data
(Output is in 1K-blocks/kilobytes)
--- Hostname ---
RouterBasic Network Reachability Test
This script pings a list of IP addresses to check their reachability. Save the code below into a file named network_test.py.
#!/usr/bin/python3
import subprocess
import sys
def ping_host(host_ip, count=1):
"""Pings a host and returns True if reachable, False otherwise."""
command = ["ping", "-c", str(count), "-W", "1", host_ip]
try:
process = subprocess.Popen(command, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
process.communicate()
return process.returncode == 0
except FileNotFoundError:
print(f"Error: 'ping' command not found.", file=sys.stderr)
return False
except Exception as e:
print(f"Error pinging {host_ip}: {e}", file=sys.stderr)
return False
if __name__ == "__main__":
hosts_to_check = ["8.8.8.8", "1.1.1.1", "192.168.1.254"]
if len(sys.argv) > 1:
hosts_to_check = sys.argv[1:]
print("--- Network Reachability Test ---")
for host in hosts_to_check:
print(f"Pinging {host}... ", end="")
if ping_host(host):
print("Reachable")
else:
print("Unreachable")The ping_host() function runs ping via subprocess.Popen, suppressing its output and checking only the return code (0 = reachable). The -W 1 flag sets a one-second timeout per packet, which is important for the BusyBox ping implementation. The default target list (8.8.8.8, 1.1.1.1, 192.168.1.254) can be overridden by passing IP addresses as command-line arguments.
Example output:
--- Network Reachability Test ---
Pinging 8.8.8.8... Reachable
Pinging 1.1.1.1... Reachable
Pinging 192.168.1.254... UnreachableSimple Log File Monitoring
This script monitors a log file and reports new lines matching specified keywords. Save the code below into a file named log_monitoring.py.
Caution
Continuously reading large log files can impact performance. This example is illustrative. For production use, consider more optimized log monitoring techniques or a more efficient file-tailing mechanism.
#!/usr/bin/python3
import sys
import re
import time
def monitor_log(log_file_path, keywords, interval_seconds=5):
"""Monitors a log file for lines containing specified keywords."""
print(f"Monitoring {log_file_path} for keywords: {keywords}")
print(f"Checking every {interval_seconds} seconds. Press Ctrl+C to stop.")
patterns = [re.compile(keyword, re.IGNORECASE) for keyword in keywords]
try:
last_lines_seen = set()
while True:
current_lines = set()
try:
with open(log_file_path, 'r') as f:
for line_number, line in enumerate(f, 1):
line = line.strip()
current_lines.add(line)
if line in last_lines_seen:
continue
for pattern in patterns:
if pattern.search(line):
print(f"[MATCH] Line {line_number}: {line}")
break
except FileNotFoundError:
print(f"Error: Log file '{log_file_path}' not found.", file=sys.stderr)
return
except Exception as e:
print(f"Error reading log file: {e}", file=sys.stderr)
last_lines_seen.update(current_lines)
time.sleep(interval_seconds)
except KeyboardInterrupt:
print("\nLog monitoring stopped.")
if __name__ == "__main__":
log_file = "/var/log/messages"
search_keywords = ["error", "warn", "dhcp"]
if len(sys.argv) > 1:
log_file = sys.argv[1]
if len(sys.argv) > 2:
search_keywords = sys.argv[2:]
try:
with open(log_file, 'r') as f:
pass
except Exception as e:
print(f"Cannot access log file {log_file}: {e}", file=sys.stderr)
sys.exit(1)
monitor_log(log_file, search_keywords)The script polls the log file every 5 seconds, compiles the keywords as case-insensitive regular expressions, and prints any new matching lines. Previously seen lines are tracked in a set to avoid duplicate reporting. The default log file (/var/log/messages) and keywords (error, warn, dhcp) can be overridden via command-line arguments. Press Ctrl-C to stop monitoring.
Example output:
Monitoring /var/log/messages for keywords: ['error', 'warn', 'dhcp']
Checking every 5 seconds. Press Ctrl+C to stop.
[MATCH] Line 15: 2025-05-22 12:34:43 [info] dhcpd: Wrote 0 leases to leases file.
[MATCH] Line 21: 2025-05-22 12:34:48 [warning] totd[1431]: Disabling rescanning of network interfaces
^C
Log monitoring stopped.