Tullio_IRL
Tullio_IRL

Reputation: 99

error when trying to regex python3 subprocess command output

I've been banging my head against a wall here...

I want to run a particular cli command from within a python script and then regex it's output. But I get the following error:

"File "speedtestcork.py", line 18, in regex_speedtest
    for line in data.split("\n"):
TypeError: Type str doesn't support the buffer API"

Here's my short code:

import time
import re
import speedtest_cli
import subprocess



def regex_speedtest(data):
        #output, errors = data.communicate()
        #output1 = str(output)
        Down_Regex = re.compile(r'(Download:).(\d+\.\d+).(Mbit/s)')
        Up_Regex = re.compile(r'(Upload:).(\d+\.\d+).(Mbit/s)')

        for line in data.split("\n"):          # code seems to break at this line.
                print(line)
                #Downmatch = Down_Regex.search(line)
                #Upmatch = Up_Regex.search(line)
        #return (Downmatch.group(2), Upmatch.group(2))



while True:
        now = time.strftime("%H:%M:%S %d %m %Y")
        process = subprocess.Popen(["speedtest-cli", "--server", "2432"], shell=True, stdout=subprocess.PIPE)
        output, errors = process.communicate()
        down, up = regex_speedtest(output)

This should be simple to debug but I cannot find the solution.

Used the following post but still cannot resolve:

Regex woes with Subprocess output

Thanks in advance,

Paul

Upvotes: 0

Views: 384

Answers (1)

Sergei Lebedev
Sergei Lebedev

Reputation: 2679

In Python3 Popen.communicate returns bytes, while regex_speedtest expects str input.

Here's an updated version:

def regex_speedtest(data):
    Down_Regex = re.compile(rb'(Download:).(\d+\.\d+).(Mbit/s)')
    Up_Regex = re.compile(rb'(Upload:).(\d+\.\d+).(Mbit/s)')

    for line in data.splitlines():   
        print(line)

I've changed the r prefix to rb, which transforms string literals into byte literals and replaced split("\n") call with splitlines, since this works for both str and bytes.

Update: as noted by Duncan in the comments, replacing "\n" with b"\n" in the split call would work just as well.

Upvotes: 2

Related Questions