Подтвердить что ты не робот

Подпроцесс и тип Str не поддерживают API-интерфейс буфера

У меня

cmd = subprocess.Popen('dir',shell=True,stdout=subprocess.PIPE)
for line in cmd.stdout:
  columns = line.split(' ')
  print (columns[3])

имеют ошибку в строке 3 Тип Str не поддерживает API-интерфейс буфера.

Что я делаю неправильно, я на Python 3.3

4b9b3361

Ответ 1

Вы читаете двоичные данные, а не str, поэтому вам нужно сначала декодировать вывод. Если аргумент universal_newlines установлен на True, то stdout автоматически декодируется с использованием результата метода locale.getpreferredencoding()  (так же, как для открытия текстовых файлов):

cmd = subprocess.Popen(
    'dir', shell=True, stdout=subprocess.PIPE, universal_newlines=True)
for line in cmd.stdout:
    columns = line.decode().split()
    if columns:
        print(columns[-1])

Если вы используете Python 3.6 или новее, вы можете использовать явный аргумент encoding для вызова Popen() для указания другого кодека для использования, например, UTF-8:

cmd = subprocess.Popen(
    'dir', shell=True, stdout=subprocess.PIPE, encoding='utf8')
for line in cmd.stdout:
    columns = line.split()
    if columns:
        print(columns[-1])

Если вам нужно использовать другой кодек в Python 3.5 или ранее, не используйте universal_newlines, просто расшифруйте текст из байтов явно.

Вы пытались разделить значение bytes с помощью аргумента str:

>>> b'one two'.split(' ')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: Type str doesn't support the buffer API

При декодировании вы избегаете этой проблемы, и ваш вызов print() не должен будет добавлять вывод с помощью b'..'.

Однако вы, скорее всего, просто захотите использовать модуль os, чтобы получить информацию о файловой системе:

import os

for filename in os.listdir('.'):
    print(filename)

Ответ 2

Более простым решением первой части ответа Martijn Pieters является передача аргумента universal_newlines=True вызову Popen.

Я бы даже упростил это:

output = subprocess.check_output('dir', universal_newlines=True)
columns = output.split()
print(columns)

ПРИМЕЧАНИЕ. Если имена файлов или каталогов содержат пробелы, используйте os.listdir('.'), как указано в Martijn Pieters answer, или что-то вроде следующего:

output = subprocess.check_output('dir', universal_newlines=True)
columns = []
for e in output.split():
    if len(columns) > 0 and columns[-1].endswith('\\'):
        columns[-1] = columns[-1][:-1] + " " + e
    else:
        columns.append(e)
print(columns)

Ответ 3

Лучше использовать binascii.b2a_uu, который преобразует двоичные данные в строку символов ASCII

from binascii import b2a_uu 
cmd = b2a_uu(subprocess.Popen('dir',shell=True,stdout=subprocess.PIPE))