2017-09-28 1 views
2

J'ai une petite fonction qui est utilisée pour tester si un exécutable semble être en cours d'exécution. Il utilise la commande ps -A et le module subprocess et renvoie un booléen.Comment cette fonction de sous-processus qui vérifie si un exécutable spécifié est en cours d'exécution peut-elle être modifiée pour fonctionner avec Python 2 et 3?

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 

Il fonctionne très bien en Python 2, mais lorsque je tente de l'utiliser en Python 3, je rencontre l'erreur suivante:

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

Il est pas évident pour moi comment cette fonction pourrait être modifiée proprement pour travailler dans les deux Python 2 et 3. Je serais ravi d'être guidé.

Répondre

1

Je suppose que le problème est que communic() renvoie une chaîne d'octets et que vous essayez de faire 'si programme en ligne' où programme (je suppose) est passé comme une chaîne. Vous pouvez essayer de convertir les chaînes en octets cordes if program.encode() in line and "defunct".encode() not in line

EDIT

Vous pouvez aussi passer « universal_newlines = True » à Popen afin d'ouvrir le flux en mode texte et obtenir des chaînes en retour https://docs.python.org/3/library/subprocess.html#subprocess.Popen.communicate https://docs.python.org/3/library/subprocess.html#subprocess.Popen.stdout

Il fonctionne aussi bien pour python 2 et python 3.

+0

Hey, merci pour votre Solution. Je n'avais pas entendu parler de cette option 'universal_newlines'. – BlandCorporation

1

Vous obtenez cette erreur en raison de fait que Python 3.x et des chaînes d'octets traiter Python 2.X différemment, préfixe vos chaînes avec b (pour les octets) et ne pas mélanger str avec bytes cela ne fonctionne pas sous 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")) 

Si vous utilisez un système Unix avec procfs, vous pouvez abréger le tout avec:

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

Nous vous remercions de votre solution. Je suis allé avec l'option 'universal_newlines' pour faciliter la compatibilité avec Python 2 et 3. Le one-liner est génial. – BlandCorporation