3
votes

quel est le codage par défaut lorsque les données de publication des requêtes python sont de type chaîne?

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'?


4 commentaires

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 manuellement payload = "text" .encode ('utf-8')


Les documents disent données 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 fait urllib3 avec les données.


Double possible de stackoverflow.com/questions/708915/...


3 Réponses :


3
votes

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 .


0 commentaires


1
votes

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'))


0 commentaires