Utilisation de Python 3.4.3 sous Windows.
Mon script exécute un petit programme Java dans la console et devrait obtenir le résultat:
import subprocess
p1 = subprocess.Popen([ ... ], stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
out, err = p1.communicate(str.encode("utf-8"))
Cela conduit à une normale
'UnicodeDecodeError: le codec' charmap 'ne peut pas décoder l'octet 0x9d en position 135: les mappages de caractères sur <non défini>'.
Maintenant, je veux ignorer les erreurs:
out, err = p1.communicate(str.encode(encoding="utf-8", errors="ignore"))
Cela conduit à une erreur plus intéressante je n'ai trouvé aucune aide pour utiliser Google:
TypeError: le descripteur 'encode' de l'objet 'str' a besoin d'un argument
Il semble donc que python ne sache même plus quels sont les arguments de str.encode (...). Il en va de même lorsque vous omettez la partie erreurs.
universal_newlines=True
active le mode texte. Combiné à stdout=PIPE
, il force le décodage de la sortie du processus enfant à l'aide de locale.getpreferredencoding(False)
qui n'est pas utf-8 sous Windows. C'est pourquoi vous voyez UnicodeDecodeError
.
Pour lire la sortie du sous-processus en utilisant le codage utf-8, supprimez universal_newlines=True
:
#!/usr/bin/env python3
from subprocess import Popen, PIPE
with Popen(r'C:\path\to\program.exe "arg 1" "arg 2"',
stdout=PIPE, stderr=PIPE) as p:
output, errors = p.communicate()
lines = output.decode('utf-8').splitlines()
str.encode("utf-8")
est équivalent à "utf-8".encode()
. Il est inutile de le transmettre à .communicate()
à moins que vous ne définissiez stdin=PIPE
et que le processus enfant attende b'utf-8'
bytestring en tant qu'entrée.
str.encode(encoding="utf-8", errors="ignore)
a la forme klass.method(**kwargs)
. La méthode .encode()
attend self
(un objet chaîne), raison pour laquelle vous voyez TypeError
.
>>> str.encode("abc", encoding="utf-8", errors="ignore") #XXX don't do it
b'abc'
>>> "abc".encode(encoding="utf-8", errors="ignore")
b'abc'
N'utilisez pas klass.method(obj)
au lieu de obj.method()
sans une bonne raison.
Vous n'êtes pas censé appeler .encode()
sur la classe elle-même. Ce que vous voulez probablement faire est quelque chose comme
p1.communicate("FOOBAR".encode("utf-8"))
Le message d'erreur que vous obtenez signifie que la fonction encode()
n'a rien à coder, puisque vous l'avez appelée sur la classe plutôt que sur une instance (qui serait ensuite passée en tant que paramètre self
à encode()
).