Python 3.0 urllib.parse ошибка «Тип str не поддерживает буфер API» - PullRequest
23 голосов
/ 12 февраля 2009
  File "/usr/local/lib/python3.0/cgi.py", line 477, in __init__
    self.read_urlencoded()
  File "/usr/local/lib/python3.0/cgi.py", line 577, in read_urlencoded
    self.strict_parsing):
  File "/usr/local/lib/python3.0/urllib/parse.py", line 377, in parse_qsl
    pairs = [s2 for s1 in qs.split('&') for s2 in s1.split(';')]
TypeError: Type str doesn't support the buffer API

Кто-нибудь может указать мне, как этого избежать? Я получаю это через подачу данных в cgi.Fieldstorage и, похоже, никак не могу это сделать другим способом.

Ответы [ 2 ]

28 голосов
/ 12 февраля 2009

urllib пытается сделать:

b'a,b'.split(',')

Что не работает. байтовые строки и строки юникода смешиваются в Py3k еще менее плавно, чем раньше - намеренно, чтобы проблемы кодирования шли не так, как раньше, а не позже.

Таким образом, ошибка довольно непрозрачно говорит вам: «Вы не можете передать строку байта в urllib.parse». Предположительно, вы выполняете запрос POST, где закодированная строка входит в cgi как тело содержимого; тело содержимого по-прежнему является байтовой строкой / потоком, поэтому теперь оно конфликтует с новым urllib.

Так что да, это ошибка в cgi.py, еще одной жертве преобразования 2to3, которая не была исправлена ​​должным образом для новой строковой модели. Это должно быть преобразование входящего потока байтов в символы перед передачей их в urllib.

Я упоминал, что библиотеки Python 3.0 (особенно связанные с сетью) все еще довольно шумен? : -)

13 голосов
/ 29 января 2010

Из руководства по питону (http://www.python.org/doc/3.0/tutorial/stdlib.html) приведен пример использования метода urlopen. Вызывает ту же ошибку.

for line in urlopen('http://tycho.usno.navy.mil/cgi-bin/timer.pl'):
    if 'EST' in line or 'EDT' in line:  # look for Eastern Time
        print(line)

Вам нужно будет использовать функцию str для преобразования байта в строку с правильной кодировкой. Следующим образом:

for line in urlopen('http://tycho.usno.navy.mil/cgi-bin/timer.pl'):
    lineStr = str( line, encoding='utf8' )
    if 'EST' in lineStr or 'EDT' in lineStr:  # look for Eastern Time
        print(lineStr)
...