Python popen () - communicate (str.encode (encoding= "utf-8", errors= "ignore")) сбой

использование Python 3.4.3 в Windows.

мой скрипт запускает небольшую java-программу в консоли и должен получить вывод:

import subprocess
p1 = subprocess.Popen([ ... ], stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
out, err = p1.communicate(str.encode("utf-8"))

это приводит к нормальной

' UnicodeDecodeError:' charmap'кодек не может декодировать байт 0x9d в позиции 135: отображение символов в '.

теперь я хочу игнорировать ошибки:

out, err = p1.communicate(str.encode(encoding="utf-8", errors="ignore"))

это приводит к более интересной ошибке, я не нашел помощи для использования google:

TypeError: дескриптору 'encode' объекта ' str ' нужен аргумент

поэтому кажется, что python даже не знает больше, какие аргументы для str.кодировать.(..) АР. То же самое относится и к части "ошибки".

2 ответов


universal_newlines=True включает текстовый режим. В сочетании с stdout=PIPE, это заставляет декодировать вывод дочернего процесса с помощью locale.getpreferredencoding(False) это не utf-8 в Windows. Вот почему вы видите UnicodeDecodeError.

чтобы прочитать вывод подпроцесса с помощью кодировки utf-8, drop 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") эквивалентно "utf-8".encode(). Нет смысла передавать его .communicate(), если значение stdin=PIPE и дочерний процесс ожидает b'utf-8' bytestring как вход.

str.encode(encoding="utf-8", errors="ignore) имеет форму klass.method(**kwargs). .encode() метод ожидает self (строковый объект) вот почему вы видите 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'

не используйте klass.method(obj) вместо obj.method() без уважительной причины.


вы не должны называть .encode() на самом классе. Что вы, вероятно, хотите сделать что-то вроде

p1.communicate("FOOBAR".encode("utf-8"))

сообщение об ошибке вы получаете означает, что encode() функция не имеет ничего для кодирования, так как вы вызвали ее в классе, а не в экземпляре (который затем будет передан как до encode()).