129 votes

Pourquoi Popen.communicate() renvoie-t-il b'hi ? \n au lieu de "salut" ?

Quelqu'un peut-il m'expliquer pourquoi le résultat que je veux, "hi", est précédé de la lettre "b" et suivi d'une nouvelle ligne ?

J'utilise Python 3.3

>>> import subprocess
>>> print(subprocess.Popen("echo hi", shell=True,
                           stdout=subprocess.PIPE).communicate()[0])
b'hi\n'

Ce "b" supplémentaire n'apparaît pas si je l'exécute avec python 2.7.

119voto

zigg Points 4823

Le site b indique que ce que vous avez est bytes qui est une séquence binaire d'octets plutôt qu'une chaîne de caractères Unicode. Les sous-processus produisent des octets, et non des caractères, et c'est donc ce qu'ils font. communicate() est de retour.

Le site bytes n'est pas directement print() capable, donc on vous montre le repr de la bytes dont vous disposez. Si vous connaissez l'encodage des octets que vous avez reçus du sous-processus, vous pouvez utiliser decode() pour les convertir en une version imprimable str :

>>> print(b'hi\n'.decode('ascii'))
hi

Bien entendu, cet exemple spécifique ne fonctionne que si vous recevez réellement un message ASCII du sous-processus. S'il ne s'agit pas d'ASCII, vous obtiendrez une exception :

>>> print(b'\xff'.decode('ascii'))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xff in position 0…

La nouvelle ligne fait partie de ce que echo hi a une sortie. echo Le travail de l'utilisateur est d'afficher les paramètres que vous lui passez, suivis d'une nouvelle ligne. Si vous n'êtes pas intéressé par l'espace blanc entourant la sortie du processus, vous pouvez utiliser la commande strip() comme ça :

>>> b'hi\n'.strip()
b'hi'

96voto

Danil Points 2373

Comme mentionné précédemment, echo hi retourne effectivement hi\n qui est un comportement attendu.

Mais vous souhaitez probablement obtenir les données dans un format "correct" sans vous soucier de l'encodage. Tout ce que vous avez à faire est de passer universal_newlines=True option pour subprocess.Popen() comme ça :

>>> import subprocess
>>> print(subprocess.Popen("echo hi",
                           shell=True,
                           stdout=subprocess.PIPE,
                           universal_newlines=True).communicate()[0])
hi

De cette façon Popen() remplacera ces symboles indésirables par lui-même.

27voto

Necrolyte2 Points 718

La commande echo renvoie par défaut un caractère de nouvelle ligne.

Comparez avec ceci :

print(subprocess.Popen("echo -n hi", \
    shell=True, stdout=subprocess.PIPE).communicate()[0])

Quant à la b précédant la chaîne de caractères indique qu'il s'agit d'une séquence d'octets, ce qui est équivalent à une chaîne de caractères normale en Python 2.6+.

http://docs.python.org/3/reference/lexical_analysis.html#literals

12voto

Jenish Points 382

B est la représentation de l'octet et \n est le résultat de la sortie de l'écho.

Ce qui suit n'imprimera que les données du résultat

import subprocess
print(subprocess.Popen("echo hi", shell=True,stdout=subprocess.PIPE).communicate()[0].decode('utf-8').strip())

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X