TypeError: данные POST должны быть байтами или итерабельными байтами. Это не может быть str

Я только что обновил с python 3.1 до python 3.2 (отформатированный HD), и один из моих скриптов перестал работать. Это дает мне ошибку в названии.

Я бы исправил это сам, но я даже не знаю, что итерабельность байтов LOL. Я попробовал байты (данные) для создания типов, но это тоже не сработало. TypeError: строковый аргумент без кодировки

url = "http://example.com/index.php?app=core&module=global&section=login&do=process"
values = {"username" : USERNAME, 
          "password" : PASSWORD}
data = urllib.parse.urlencode(values)
req = urllib.request.Request(url, data)
urllib.request.urlopen(req)

Сбой в последней строке.

Работает в 3.1, но не 3.2

Ответ 1

В основном вы пытались преобразовать строку в байты, но вы сделали это неправильно. У Python нет приведения типов (так что вы делали не приведение типов).

Способ сделать это - кодировать текстовые данные в байтовые данные, которые вы выполняете с помощью функции кодирования:

binary_data = data.encode('encoding')

От чего зависит кодировка. Вероятно, вы должны использовать здесь "ascii". Если у вас есть символы, которые не являются ASCII, вам нужно использовать другую кодировку, обычно "utf8", но тогда вам также необходимо сообщить получающему веб-серверу, что это UTF-8. Это может также не хотеть UTF8, но тогда вы должны спросить об этом, и это усложняется.: -)

Ответ 2

@Эндерс, я знаю, что это старый вопрос, но я хотел бы объяснить еще кое-что для кого-то, борющегося с этой проблемой.

В частности, эта строка кода здесь:

data = urllib.parse.urlencode(values)

У вас возникают проблемы, так как вы пытаетесь закодировать данные: values ​​(urlencode).

Если вы ссылаетесь на документацию urllib.parse, прокрутите страницу вниз, чтобы узнать, что делает urlencode: https://docs.python.org/3/library/urllib.parse.html < ~ вы увидите что вы пытаетесь закодировать своего пользователя/передать в строку данных:

Преобразовать объект сопоставления или последовательность двухэлементных кортежей, которые могут содержать объекты str или байтов, в текстовую строку ASCII с процентным кодированием. Если результирующая строка должна использоваться в качестве данных для операции POST с функцией urlopen(), она должна быть закодирована в байты, иначе это приведет к типу TypeError.

Возможно, то, что вы пытаетесь сделать здесь, это сделать какое-то шифрование вашего пользователя/пароля, но я действительно не думаю, что это правильный путь. Если это так, то вам, вероятно, нужно убедиться, что получающая сторона (пункт назначения вашего URL-адреса) знает, что вы кодируете своего пользователя/пароль с этим.

Более современный подход заключается в использовании мощной библиотеки запросов. Они совместимы с очень распространенными протоколами аутентификации: http://docs.python-requests.org/en/master/user/authentication/

В этом случае я бы сделал что-то вроде этого:

requests.get(url, auth=('user', 'pass'))