Найти - Пользователи
Полная версия: [РЕШЕНО] Python 3 POST-запрос multipart/form-data в requests с кодировкой Windows-1251
Начало » Web » [РЕШЕНО] Python 3 POST-запрос multipart/form-data в requests с кодировкой Windows-1251
1 2
omatic
ZZZ, спасибо за картинку

В том то и проблема, когда пишу:
"Post" : 'тест'.encode('cp1251')

то на форуме, в созданой теме, вместо нормальних букв, вместо слова тест:
b'\xf2\xe5\xf1\xf2'
omatic
Что- то я совсем запутался в кодировках Python 3, вот что проверил:


Python2 код возвращает на форуме в теме слово “тест” в нормальной кодировке:
#!/usr/bin/env python2
# -*- coding: utf-8 -*-
s_utf8 = u'тест'
s_cp1251 = str(s_utf8.encode('cp1251'))
	postdata = {
		"TopicTitle" : s_cp1251
	}
# код requests ...

Тот же код на Python3, возвращает b'\xf2\xe5\xf1\xf2'

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
s_utf8 = 'тест'
s_cp1251 = str(s_utf8.encode('cp1251'))
	postdata = {
		"TopicTitle" : s_cp1251
	}
# код requests ...

Почему? о_О Строки в Python 3 по умолчанию юникод, так ведь? Код должен работать идентично…


Уже даже так делал(Python3):
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
s_utf8 = 'тест' # текст в unicode utf8 (строка)  
s_uni = s_utf8.encode('utf8')  #  последовательность байт (unicode)
s_cp1251 = s_uni.decode('cp1251') # текст в unicode cp1251 (строка)  
print(s_utf8)
print(s_uni)
print(s_cp1251)

Результат на екране при локалях cp1251 в системе:
����
b'\xd1\x82\xd0\xb5\xd1\x81\xd1\x82'
тест

Результат на екране при локалях utf-8 в системе:
тест
b'\xd1\x82\xd0\xb5\xd1\x81\xd1\x82'
тест

На форум вставилось:
тест

Не пойму где косяк
bismigalis
не пиши s_utf8, там юникод. пиши s_unicode и просто s в python3

в текстовом файле скрипта utf8, когда интерпритатор его считывает, он конвертирует в unicode
omatic
bismigalis
не пиши s_utf8, там юникод. пиши s_unicode и просто s в python3в текстовом файле скрипта utf8, когда интерпритатор его считывает, он конвертирует в unicode

еммм не понял, скрипт в utf-8, когда делаю строку, например s='тест', и Python3 читает, то конвертует ее в unicode так? Но вопрос в другом, как перевести ее в cp1251 и передать через POST.

.encode('utf8') дает нам последовательность байт b'\xd1\x82\xd0\xb5\xd1\x81\xd1\x82'
.decode('cp1251') дает нам теоретически cp1251 тест
но через POST requests передается что-то такое: тест
reclosedev
omatic
Тот же код на Python3, возвращает b'\xf2\xe5\xf1\xf2'

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
s_utf8 = 'тест'
s_cp1251 = str(s_utf8.encode('cp1251'))
	postdata = {
		"TopicTitle" : s_cp1251
	}
# код requests ...
str() то тут каким боком? Вам уже несколько раз правильное решение подсказали:
#!/usr/bin/env python3
s_utf8 = 'тест'
s_cp1251 = s_utf8.encode('cp1251')
	postdata = {
		"TopicTitle" : s_cp1251
	}
Т.е.
postdata = {
		"TopicTitle" :  'тест'.encode('cp1251')
	}
bismigalis
наверное теперь request заботливо отправляет представление b'\xf2\xe5\xf1\xf2' вместо самих байтов
omatic
reclosedev, сори str() тут не причем, я с примера брал какого-то,но сути не меняет если просто сделать .encode() то посылается последовательность байт

код
#!/usr/bin/env python3
s_utf8 = 'тест'
s_cp1251 = s_utf8.encode('cp1251')
	postdata = {
		"TopicTitle" : s_cp1251
	}

или
postdata = {
		"TopicTitle" :  'тест'.encode('cp1251')
	}

на форуме, в поле TopicTitle получаю:
b'\xf2\xe5\xf1\xf2'

bismigalis, именно, вот не понимаю , что это, или я как-то не так передаю в request или сам request передает не так

reclosedev я тут много нафлудил и может запутал Вас, на python2 код работает, спасибо за подсказку, но на python3 отправляет представление b'\xf2\xe5\xf1\xf2' вместо самих байтов текста

П.С. я так понимаю это баг модуля requests?
reclosedev
omatic
П.С. я так понимаю это баг модуля requests?
Хм. Действительно, в r.request.body b'\xf2\xe5\xf1\xf2' на Python3.

А форум не принимает form-urlencoded, т.е. без files={'':''}? Потому что в этом случае все декодируется правильно.
omatic
reclosedev
А форум не принимает form-urlencoded, т.е. без files={'':''}? Потому что в этом случае все декодируется правильно.

Емммм очень странно, форум не принимал form-urlencoded, только через multipart/form-data. Я специально инфу перерывал как послать multipart/form-data , нашел что костылем files={'':''} заставляют передаваться правильно, впринципе в Python2 так и передавалось. Но в Python3 вылез баг с кодировкой. С этого всего я апдейтнул с git-a requests вручную (раньше устанавливал через pip install), и сейчас попробовал, форум прекрасно понял что ему передал requests через form-urlencoded в Python3, и с правильной кодировкой.

Огромное спасибо

P.S. правда интересно что же с multipart/form-data, попробую запостить в багтрекер
omatic
Получил ответ с git-хаба на багтрекере, так-что использовать только UTF-8 по умолчанию и никак по другому.

Lukasa commented:
Welcome to the exciting world of Python string handling!

The reason this is happening is that, somewhere in the web stack, someone is calling str() on your string. In Python3, calling str() on a bytestring returns the exact same thing as calling repr(). In this case, that's the byte literal form.

Unfortunately, the current rule is that urllib3 must take native strings. This means you cannot encode your post data: they need to stay as unicode, to be encoded later.
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB