pythonpython-3.xiperf3

Python script that reads iperf3 output


I am writing a python scripts that reads the output of iperf3 client and fetches the required data in yml. Basically the script reads the output table and it has to capture the receiver's values for interval, transfer and bandwidth. To an extent the pattern matching is working, but the output is quite junky and not as expected. Please find my python script below:

import re

output = """
Connecting to host 9.10.21.01, port 5201
[  4] local 9.17.201.011 port 44466 connected to 9.10.21.01 port 5201
[ ID] Interval           Transfer     Bandwidth       Retr  Cwnd
[  4]   0.00-2.00   sec  1.71 GBytes  7.36 Gbits/sec  264    789 KBytes
[  4]   2.00-4.00   sec  1.63 GBytes  6.99 Gbits/sec  133    865 KBytes
[  4]   4.00-5.00   sec   732 MBytes  6.14 Gbits/sec   11    826 KBytes
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval           Transfer     Bandwidth       Retr
[  4]   0.00-5.00   sec  4.06 GBytes  6.97 Gbits/sec  408             sender
[  4]   0.00-5.00   sec  4.05 GBytes  6.96 Gbits/sec                  receiver
"""
receiver_line = re.search(r'\[\s+\d+\]\s+(.*?)\s+sec\s+(.*?)\s+(.*?)\s+receiver', output)
if receiver_line:
    interval, transfer, bandwidth = receiver_line.groups()
    output_yaml = f"Interval: {interval}\nTransfer: {transfer}\nBandwidth: {bandwidth}"
    print(output_yaml)
else:
    print("Receiver data not found in the output.")

My code seems to execute without any errors but somehow the pattern matching seems to be messed up. The output that is returned from the code is

Interval: 0.00-5.00
Transfer: 4.06 GBytes  6.97 Gbits/sec  408             sender
Bandwidth: [  4]   0.00-5.00   sec  4.05 GBytes  6.96 Gbits/sec

The expected output should be something like shown below. Is there some tweaks I need to make or is there any other approach I can try?

Interval: 0.00-5.00
Transfer: 4.05 GBytes
Bandwidth: 6.96 Gbits/sec

Solution

  • Your code should work as expected if you use the following regex pattern:

    import re
    
    output = """
    Connecting to host 9.10.21.01, port 5201
    [  4] local 9.17.201.011 port 44466 connected to 9.10.21.01 port 5201
    [ ID] Interval           Transfer     Bandwidth       Retr  Cwnd
    [  4]   0.00-2.00   sec  1.71 GBytes  7.36 Gbits/sec  264    789 KBytes
    [  4]   2.00-4.00   sec  1.63 GBytes  6.99 Gbits/sec  133    865 KBytes
    [  4]   4.00-5.00   sec   732 MBytes  6.14 Gbits/sec   11    826 KBytes
    - - - - - - - - - - - - - - - - - - - - - - - - -
    [ ID] Interval           Transfer     Bandwidth       Retr
    [  4]   0.00-5.00   sec  4.06 GBytes  6.97 Gbits/sec  408             sender
    [  4]   0.00-5.00   sec  4.05 GBytes  6.96 Gbits/sec                  receiver
    """
    receiver_line = re.search(r'([\d.]+-[\d.]+)\s+sec\s+([\d.]+\s+\w?Bytes)\s+([\d.]+\s+\w?bits/sec)\s+receiver', output)
    if receiver_line:
        interval, transfer, bandwidth = receiver_line.groups()
        output_yaml = f"Interval: {interval}\nTransfer: {transfer}\nBandwidth: {bandwidth}"
        print(output_yaml)
    else:
        print("Receiver data not found in the output.")
    

    Alternatively since you indicated that column widths are fixed you could also iterate over lines and read out the different data fields with string indexing:

    output = """
    Connecting to host 9.10.21.01, port 5201
    [  4] local 9.17.201.011 port 44466 connected to 9.10.21.01 port 5201
    [ ID] Interval           Transfer     Bandwidth       Retr  Cwnd
    [  4]   0.00-2.00   sec  1.71 GBytes  7.36 Gbits/sec  264    789 KBytes
    [  4]   2.00-4.00   sec  1.63 GBytes  6.99 Gbits/sec  133    865 KBytes
    [  4]   4.00-5.00   sec   732 MBytes  6.14 Gbits/sec   11    826 KBytes
    - - - - - - - - - - - - - - - - - - - - - - - - -
    [ ID] Interval           Transfer     Bandwidth       Retr
    [  4]   0.00-5.00   sec  4.06 GBytes  6.97 Gbits/sec  408             sender
    [  4]   0.00-5.00   sec  4.05 GBytes  6.96 Gbits/sec                  receiver
    """
    for line in output.split('\n'):
        interval = line[6:18].strip()
        transfer = line[25:37]
        bandwidth = line[38:53]
        role = line[70:79].strip()
        if role == 'receiver':
            output_yaml = f"Interval: {interval}\nTransfer: {transfer}\nBandwidth: {bandwidth}"
            print(output_yaml)
            break
    else:
        print("Receiver data not found in the output.")