2015-05-24 3 views
1

Я получаю эту ошибку, когда я запускаю этот скрипт в Python 3.4закодировать строку в Python 3.4

Traceback (most recent call last): 
File "qcdlcomm.py", line 23, in <module> 
if not call('whoami')[0] == 'root': 
File "qcdlcomm.py", line 20, in call 
return subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE).stdout.read().strip().split("\n") 
TypeError: 'str' does not support the buffer interface 

Я думаю, что ответ здесь TypeError: 'str' does not support the buffer interface, но я не знаю, как это осуществить.

qcdlcomm.py

+0

Возможный дубликат [Преобразование байтов в строку Python] (http://stackoverflow.com/questions/606191/convert-bytes-to-a-python-string) – JDong

ответ

0

Строки трактуются по-разному в Python3. Строки не совпадают с байтами. То, что вы получаете от вызова whoami, является массивом байтов. Чтобы исправить эту функцию call, просто декодировать байты в строку:

def call(cmd,hide_stderr=True):             
    return subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE).stdout.read().decode("utf-8").strip().split("\n") 

Это аналогичная проблема, как указано в Convert bytes to a Python string.

Обратите внимание, что это только быстрое решение, но оно будет работать в вашем случае использования. Просто введите .decode('utf-8') в строку 20 между .read() и .strip().

+1

В общем, вы не должны жестко кодировать 'utf -8' кодировка. Передайте 'universal_newlines = True' или используйте кодировку' locale.getpreferredencoding (False) '. – jfs

+0

Спасибо за помощь. Будет ли это работать? 'def call (cmd, hide_stderr = True): \t return subprocess.Popen (cmd, shell = True, stdout = subprocess.PIPE) .stdout.read(). decode ("utf-8"). strip() .split ("\ n") ' ' # make sure we are root if not call ('whoami', universal_newlines = True) [0] == 'root': \t print ("run as root") \t sys.exit() ' – lunaticMonk

+0

№ Функция' call', определенная в строке 19, не имеет аргумента 'universal_newlines'. Просто замените определение функции на строках 19-20 версией, которую я дал вам в качестве быстрого исправления. – JDong

1

bytes.split() method не принимает str (типа Unicode в Python 3):

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

Сообщение об ошибке в Python 3.5 улучшено:

>>> b"abc".split("\n") 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: a bytes-like object is required, not 'str' 

"\n" (str типа) является строкой Unicode (текст), который не является bytes-like (двоичные данные) в Python 3.


Чтобы получить вывод команды whoami в виде строки Unicode:

#!/usr/bin/env python 
from subprocess import check_output 

username = check_output(['whoami'], universal_newlines=True).rstrip("\n") 

universal_newlines позволяет в текстовом режиме. check_output() автоматически перенаправляет дочерний stdout и создает исключение из своего ненулевого статуса выхода.

Примечание: shell=True здесь не нужно (вам не нужна оболочка, чтобы запустить whoami).


Unrelated: выяснить, являетесь ли вы root в Python, вы можете использовать geteuid():

import os 

if os.geteuid() == 0: 
    # I'm root (or equivalent e.g., `setuid`) 

Если вам нужно find out what is the current user name in Python:

import getpass 

print('User name', getpass.getuser()) 

Осторожно: don't use getuser() for access control purposes!

0

Обычно, если вы хотите используйте текстовый режим с Popen в Python 3 (и предположим, что вы используете реализацию cPython), вы можете передать либо аргумент encoding, error, либо universal_newlines для конструктора Popen.Например:

return subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, universal_newlines=True).stdout.read().strip().split("\n") 

Это потому, что в реализации CPython в __init__ в Popen есть следующая строка:

text_mode = encoding or errors or universal_newlines 

Это также то, что check_output в CPython внутренне делает - это гарантирует, что input ключевое слово аргумент (если присутствует, и None) имеет соответствующий тип и передает аргументы ключевого слова в run (который позже вызывает Popen):

def check_output(*popenargs, timeout=None, **kwargs): 
    if 'stdout' in kwargs: 
     raise ValueError('stdout argument not allowed, it will be overridden.') 

    if 'input' in kwargs and kwargs['input'] is None: 
     # Explicitly passing input=None was previously equivalent to passing an 
     # empty string. That is maintained here for backwards compatibility. 
     kwargs['input'] = '' if kwargs.get('universal_newlines', False) else b'' 

    return run(*popenargs, stdout=PIPE, timeout=timeout, check=True, 
**kwargs).stdout 

См. Больше в subprocess.py source.

Смежные вопросы