subprocess модуль использует байты для обмена данными с дочерним процессом.
b'\r\n' это текстовое представление (repr(bytes_object)) двоичных данных, представленных типом bytes в Питоне -- объект, представляющий последовательность двух байт (0x0d, 0x0a) в этом примере. Обычно текстовое представление показывается в интерактивной консоле Питона, где sys.displayhook использует repr(), чтобы показать объекты по умолчанию (полезно для отладки) или если вы пытаетесь напечатать байты, используя текстовый интерфейс (например, print(bytes_object)) -- нужно текст передавать вместо этого.
Как получить текст из вывода внешней команды
Чтобы получить текст из байт, их необходимо декодировать в Юникод, используя зависящую от команды, её опций и окружения кодировку:
text = subprocess.check_output("ipconfig", encoding=encoding)
До Python 3.6, Popen() не принимал encoding параметр, поэтому чтобы произвольную кодировку передать, можно явно io.TextIOWrapper() создать. Чтобы построчно вывод прочитать:
#!/usr/bin/env python3
import io
from subprocess import Popen, PIPE, STDOUT
with Popen("ipconfig", stdout=PIPE, stderr=STDOUT, bufsize=1) as process:
for line in io.TextIOWrapper(process.stdout, encoding=encoding):
# здесь с line можно работать
print(line, end='')
Если передать universal_newlines=True в Popen(), то TextIOWrapper() используется неявно и соответственно locale.getpreferredencoding(False) кодировка используется, чтобы декодировать байты в текст. Дополнительно, окончания строк нормализируются, например, '\r\n' на входе преобразуется в '\n'.
Обычно ipconfig расположен в одном из стандартных путей, просматриваемых Popen() в поиске исполняемого файла и ipconfig не является внутренней командой в cmd.exe, поэтому shell=True не нужно использовать.
Как определить кодировку, чтобы вывод команды декодировать
Не нужно жёстко прошивать кодировку окружения, в котором исполняется ваш Питон-скрипт. Иначе получатся кракозябы, если вы запустите команду в окружении, которое может использовать другую несовместимую кодировку символов. См.:
Используемая кодировка для вывода зависит от команды, её опций и текущего окружения, например, Питон 3 использует encoding=locale.getpreferredencoding(False) по умолчанию -- что-нибудь вроде cp1251 на русской Винде. cmd.exe по умолчанию использует OEM code page (см. вывод chcp команды) -- что-нибудь вроде cp866. Если родительский процесс подключён к той же консоле и chcp не был использован для смены кодировки, то можно использовать encoding=os.device_encoding(1), который вызывает GetConsoleOutputCP() на Windows (это значение может отличаться от encoding=ctypes.windll.kernel32.GetOEMCP()). cmd /U использует utf-16 кодировку.
Наиболее вероятно, что вывод ipconfig можно декодировать, используя encoding=os.device_encoding(1) or ctypes.windll.kernel32.GetOEMCP() в этом случае (первое не None значение).
netifacesпакет (pip install netifaces) вместо вызоваipconfigи распознавания его вывода. – jfs Feb 27 '16 at 14:03