avec le code suivant
payload = ''' å·¥ä½æ¥å æ»ä½æ åµï¼è¯å¥½ ''' r = requests.post("http://httpbin.org/post", data=payload)
quel est le codage par défaut lorsque les requêtes postent des données de type chaîne? UTF8 ou unicode-escape?
Si j'aime spécifier un type d'encodage, dois-je l'encoder moi-même et passer un objet bytes au paramètre 'data'?
3 Réponses :
Si vous essayez réellement votre exemple, vous trouverez:
$ python Python 3.7.2 (default, Jan 29 2019, 13:41:02) [Clang 10.0.0 (clang-1000.10.44.4)] on darwin Type "help", "copyright", "credits" or "license" for more information. >>> import requests >>> payload = ''' ... å·¥ä½æ¥å ... æ»ä½æ åµï¼è¯å¥½ ... ''' >>> r = requests.post("http://127.0.0.1:8888/post", data=payload) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/tmp/venv/lib/python3.7/site-packages/requests/api.py", line 116, in post return request('post', url, data=data, json=json, **kwargs) File "/tmp/venv/lib/python3.7/site-packages/requests/api.py", line 60, in request return session.request(method=method, url=url, **kwargs) File "/tmp/venv/lib/python3.7/site-packages/requests/sessions.py", line 533, in request resp = self.send(prep, **send_kwargs) File "/tmp/venv/lib/python3.7/site-packages/requests/sessions.py", line 646, in send r = adapter.send(request, **kwargs) File "/tmp/venv/lib/python3.7/site-packages/requests/adapters.py", line 449, in send timeout=timeout File "/tmp/venv/lib/python3.7/site-packages/urllib3/connectionpool.py", line 600, in urlopen chunked=chunked) File "/tmp/venv/lib/python3.7/site-packages/urllib3/connectionpool.py", line 354, in _make_request conn.request(method, url, **httplib_request_kw) File "/tmp/venv/lib/python3.7/http/client.py", line 1229, in request self._send_request(method, url, body, headers, encode_chunked) File "/tmp/venv/lib/python3.7/http/client.py", line 1274, in _send_request body = _encode(body, 'body') File "/tmp/venv/lib/python3.7/http/client.py", line 160, in _encode (name.title(), data[err.start:err.end], name)) from None UnicodeEncodeError: 'latin-1' codec can't encode characters in position 2-5: Body ('å·¥ä½æ¥å') is not valid Latin-1. Use body.encode('utf-8') if you want to send it encoded in UTF-8.
Comme décrit dans Détecter le codage des caractères d'une requête HTTP POST le codage par défaut pour HTTP POST est ISO-8859-1 aka Latin-1. Et comme le message d'erreur juste à la fin du tracé vous l'indique, vous pouvez le forcer en encodant une chaîne UTF-8 octets
; mais bien sûr, votre serveur doit également s'attendre à UTF-8; ou vous enverrez simplement un mojibake Latin-1 inutile.
Il n'y a aucun moyen dans l'interface POST elle-même de l'imposer, mais votre serveur pourrait en fait obliger les clients à spécifier explicitement leur codage de contenu en utilisant le charset ; peut-être retourner un code d'erreur 5xx spécifique avec un message d'erreur explicite s'il manque.
De manière un peu moins disciplinée, votre serveur pourrait tenter de décoder les demandes POST entrantes en UTF-8, et rejeter le POST si cela échoue .
Demandes utilise * le http.client.HTTPConnection.request < / a> pour envoyer des requêtes. Cette méthode encodera les données str
en latin-1 mais n'encodera pas les octets
.
Si vous fournissez une entrée encodée, vous devez ajouter un en-tête de type de contenu spécifiant l'encodage utilisé; à l'inverse, si vous fournissez un en-tête de type contenu, vous devez vous assurer que l'encodage du corps correspond à celui spécifié.
À partir de la documentation pour HTTPConnection.request
:
Si body est spécifié, les données spécifiées sont envoyées une fois les en-têtes terminés. Il peut s'agir d'une chaîne, d'un objet de type octets, d'un objet fichier ouvert ou d'un itérable d'octets. Si le corps est une chaîne, il est codé en ISO-8859-1, la valeur par défaut pour HTTP. S'il s'agit d'un objet de type octets, les octets sont envoyés tels quels. S'il s'agit d'un objet fichier, le contenu du fichier est envoyé; cet objet fichier doit prendre en charge au moins la méthode read (). Si l'objet fichier est une instance de io.TextIOBase, les données renvoyées par la méthode read () seront codées comme ISO-8859-1, sinon les données renvoyées par read () sont envoyées telles quelles. Si body est un itérable, les éléments de l'itérable sont envoyés tels quels jusqu'à ce que l'itérable soit épuisé.
* httplib a été renommé http.client en Python3
Conformément aux dernières spécifications JSON ( RFC-8259 ) lorsque vous utilisez des services externes, vous devez encodez vos charges utiles JSON en UTF-8 . Voici une solution rapide:
r = requests.post("http://httpbin.org/post", data=payload.encode('utf-8'), headers={'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8'})
requêtes
utilise httplib
qui utilise par défaut l'encodage latin-1
. Les tableaux d'octets ne sont pas automatiquement encodés, il est donc toujours préférable de les utiliser.
Je recommande également de définir le jeu de caractères en utilisant le paramètre headers
:
r = requests.post("http://httpbin.org/post", data=payload.encode('utf-8'))
obtenez-vous un message d'erreur lorsque vous l'exécutez? J'ai reçu un message d'erreur concernant l'encodage en
Latin-1
. Mais je n'ai pas de problème lorsque je l'encode manuellementpayload = "text" .encode ('utf-8')
Les documents disent
données code > doit être "Dictionnaire, liste de tuples, octets ou objet de type fichier". Les chaînes ne sont pas une option documentée.
Cela dit, le code semble accepter les chaînes Unicode, et je n'ai pas retracé le type d'encodage appliqué ni où l'encodage se produit si vous passez une chaîne Unicode. Il semble être non codé jusqu'à l'endroit où il est passé à
urllib3
, et je ne suis pas sûr de ce que faiturllib3
avec les données.Double possible de stackoverflow.com/questions/708915/...