BlandCorporation
BlandCorporation

Reputation: 1344

How can this subprocess function that checks if a specified executable is running be changed to work with both Python 2 and 3?

I have a small function that is used to test if an executable seems to be running. It uses the command ps -A and the subprocess module and returns a boolean.

def running(program):

    results = subprocess.Popen(
        ["ps", "-A"],
        stdout = subprocess.PIPE
    ).communicate()[0].split("\n")

    matches = [
        line for line in results if program in line and "defunct" not in line
    ]

    if matches:

        return True

    else:

        return False

It works fine in Python 2, but when I try to use it in Python 3, I encounter the following error:

TypeError: a bytes-like object is required, not 'str'

It is not obvious to me how this function could be changed neatly to work in both Python 2 and 3. I would welcome guidance.

Upvotes: 2

Views: 39

Answers (2)

doze
doze

Reputation: 285

I guess the problem is that communicate() returns a byte string and you are trying to do 'if program in line' where program(i suppose) is passed as a string. You can try to convert the strings in byte-strings if program.encode() in line and "defunct".encode() not in line

EDIT

You can also try to pass 'universal_newlines=True' to Popen so to open the stream in text mode and get strings in return https://docs.python.org/3/library/subprocess.html#subprocess.Popen.communicate https://docs.python.org/3/library/subprocess.html#subprocess.Popen.stdout

It works both for python 2 and python 3.

Upvotes: 1

GIZ
GIZ

Reputation: 4633

You get this error due to fact that Python 3.X and Python 2.X treat byte strings differently, prefix your strings with b (for bytes) and don't intermix str with bytes this won't work under 3.X:

import subprocess
def running(program):
    results = subprocess.Popen(["ps", "-A"],stdout=subprocess.PIPE).communicate()[0].split(b"\n")

    matches = [line for line in results 
                        if program in line and b"defunct" not in line]
    if matches:
        return True
    else:
        return False

print(running(b"python33"))

If you're using a Unix system with procfs, you could abridge the whole thing with:

res =  not "Zombie" in os.popen("cat /proc/`pidof %s`/status" % 'python3')

Upvotes: 1

Related Questions