Requests: UnicodeEncodeError: codec 'latin-1' tidak dapat menyandikan karakter

Dibuat pada 20 Des 2013  ·  7Komentar  ·  Sumber: psf/requests

Permintaan adalah versi terbaru.
Ketika saya mencoba memposting data yang berisi karakter Cina, pengecualian ini dilemparkan.

Traceback (most recent call last):
  File "X/threading.py", line 639, in _bootstrap_inner
  File "X/threading.py", line 596, in run
  File "C:\Users\Administrator\Dropbox\Sublime3056\Data\Packages\SublimeApex\salesforce\api.py", line 546, in execute_anonymous
    headers=headers)
  File "C:\Users\Administrator\Dropbox\Sublime3056\Data\Packages\SublimeApex\requests\api.py", line 88, in post
    return request('post', url, data=data, **kwargs)
  File "C:\Users\Administrator\Dropbox\Sublime3056\Data\Packages\SublimeApex\requests\api.py", line 44, in request
    return session.request(method=method, url=url, **kwargs)
  File "C:\Users\Administrator\Dropbox\Sublime3056\Data\Packages\SublimeApex\requests\sessions.py", line 338, in request
    resp = self.send(prep, **send_kwargs)
  File "C:\Users\Administrator\Dropbox\Sublime3056\Data\Packages\SublimeApex\requests\sessions.py", line 441, in send
    r = adapter.send(request, **kwargs)
  File "C:\Users\Administrator\Dropbox\Sublime3056\Data\Packages\SublimeApex\requests\adapters.py", line 292, in send
    timeout=timeout
  File "C:\Users\Administrator\Dropbox\Sublime3056\Data\Packages\SublimeApex\requests\packages\urllib3\connectionpool.py", line 428, in urlopen
    body=body, headers=headers)
  File "C:\Users\Administrator\Dropbox\Sublime3056\Data\Packages\SublimeApex\requests\packages\urllib3\connectionpool.py", line 280, in _make_request
    conn.request(method, url, **httplib_request_kw)
  File "X/http/client.py", line 1049, in request
  File "X/http/client.py", line 1086, in _send_request
UnicodeEncodeError: 'latin-1' codec can't encode characters in position 1632-1633: ordinal not in range(256)

Komentar yang paling membantu

Jadi, ST 3, tapi bukan revisi terbaru. Oke, itu memberi kita sesuatu. Secara khusus, Sublime Text 3 menggunakan Python 3.3, bukan Python 2.7 (yang digunakan Sublime Text 2). Ini berarti semua string default di Sublime Apex adalah string unicode.

Jika Anda membuka file Python 3.3 http.client , Anda akan menemukan bahwa fungsi _send_request() terlihat seperti ini:

# Honor explicitly requested Host: and Accept-Encoding: headers.
header_names = dict.fromkeys([k.lower() for k in headers])
skips = {}
if 'host' in header_names:
    skips['skip_host'] = 1
if 'accept-encoding' in header_names:
    skips['skip_accept_encoding'] = 1

self.putrequest(method, url, **skips)

if body is not None and ('content-length' not in header_names):
    self._set_content_length(body)
for hdr, value in headers.items():
    self.putheader(hdr, value)
if isinstance(body, str):
    # RFC 2616 Section 3.7.1 says that text default has a
    # default charset of iso-8859-1.
    body = body.encode('iso-8859-1')
self.endheaders(body)

Sekarang, ISO-8859-1 adalah alias untuk Latin-1, yang merupakan codec yang bermasalah. Masalah yang kami dapatkan adalah bahwa Sublime Apex menyediakan badan string unicode untuk Permintaan, yang perlu dikodekan oleh httplib menjadi byte. Mengambil default dari RFC 2616, itu menyimpulkan Anda menginginkan Latin-1, yang tidak menyertakan karakter Cina apa pun. Jelas, penyandian gagal, dan Anda mendapatkan pengecualian yang dimaksud.

Mempertimbangkan bahwa Sublime Apex mengklaim di header yang dikirimnya untuk mengirim data yang disandikan UTF-8 (yang merupakan kebohongan saat ini), Sublime Apex ingin mengkodekan data sebagai UTF-8 sebelum mengirimnya. Ini berarti setiap baris pengiriman data (dalam hal ini baris 545 dari salesforce/api.py ) harus dibaca seperti ini:

response = requests.post(self.apex_url, soap_body.encode('utf-8'), verify=False, headers=headers)

Demi siapa pun yang ingin mengonfirmasi diagnosis saya, berikut ini sedikit contoh kode yang mengonfirmasi masalah:

a = "\u13E0\u19E0\u1320"
a.encode('latin1')  # Throws UnicodeEncodeError, proves that this can't be expressed in ISO-8859-1.
a.encode('utf-8')  # Totally fine.
r = requests.post('http://httpbin.org/post', data=a)  # Using unicode string, throws UnicodeEncodeError blaming Latin1.
r = requests.post('http://httpbin.org/post', data=a.encode('utf-8'))  # Works fine.

Terima kasih telah menyampaikan ini bersama kami, tetapi ini bukan bug Permintaan. =)

Semua 7 komentar

Berkas "X/http/client.py"

Apakah Anda menulis X karena itu adalah jalur ke file lokal? Jika demikian, struktur direktori Anda mungkin membingungkan urllib3. Jika tidak, maka Anda mungkin harus mengangkat ini di bugs.python.org karena ini bukan sesuatu yang menurut saya harus ditangani oleh permintaan. Ini sepertinya naik dari httplib (atau http pada Python 3 yang saya kira Anda gunakan).

@sigmavirus24 ,

Saya menggunakan permintaan di plugin luhur, jika soap_body dalam pernyataan di bawah ini tidak mengandung karakter Cina, tidak akan ada pengecualian.

response = requests.post(self.apex_url, soap_body, verify=False, headers=headers)

Pertama, kecuali Anda menggunakan versi Sublime Apex yang berbeda dengan yang ada di repositori publik mereka, Permintaan _bukan_ versi terbaru, ini versi 1.2.3. Bisakah Anda memberi tahu saya versi Sublime Text yang Anda gunakan?

Ini teks luhur 3056

Jadi, ST 3, tapi bukan revisi terbaru. Oke, itu memberi kita sesuatu. Secara khusus, Sublime Text 3 menggunakan Python 3.3, bukan Python 2.7 (yang digunakan Sublime Text 2). Ini berarti semua string default di Sublime Apex adalah string unicode.

Jika Anda membuka file Python 3.3 http.client , Anda akan menemukan bahwa fungsi _send_request() terlihat seperti ini:

# Honor explicitly requested Host: and Accept-Encoding: headers.
header_names = dict.fromkeys([k.lower() for k in headers])
skips = {}
if 'host' in header_names:
    skips['skip_host'] = 1
if 'accept-encoding' in header_names:
    skips['skip_accept_encoding'] = 1

self.putrequest(method, url, **skips)

if body is not None and ('content-length' not in header_names):
    self._set_content_length(body)
for hdr, value in headers.items():
    self.putheader(hdr, value)
if isinstance(body, str):
    # RFC 2616 Section 3.7.1 says that text default has a
    # default charset of iso-8859-1.
    body = body.encode('iso-8859-1')
self.endheaders(body)

Sekarang, ISO-8859-1 adalah alias untuk Latin-1, yang merupakan codec yang bermasalah. Masalah yang kami dapatkan adalah bahwa Sublime Apex menyediakan badan string unicode untuk Permintaan, yang perlu dikodekan oleh httplib menjadi byte. Mengambil default dari RFC 2616, itu menyimpulkan Anda menginginkan Latin-1, yang tidak menyertakan karakter Cina apa pun. Jelas, penyandian gagal, dan Anda mendapatkan pengecualian yang dimaksud.

Mempertimbangkan bahwa Sublime Apex mengklaim di header yang dikirimnya untuk mengirim data yang disandikan UTF-8 (yang merupakan kebohongan saat ini), Sublime Apex ingin mengkodekan data sebagai UTF-8 sebelum mengirimnya. Ini berarti setiap baris pengiriman data (dalam hal ini baris 545 dari salesforce/api.py ) harus dibaca seperti ini:

response = requests.post(self.apex_url, soap_body.encode('utf-8'), verify=False, headers=headers)

Demi siapa pun yang ingin mengonfirmasi diagnosis saya, berikut ini sedikit contoh kode yang mengonfirmasi masalah:

a = "\u13E0\u19E0\u1320"
a.encode('latin1')  # Throws UnicodeEncodeError, proves that this can't be expressed in ISO-8859-1.
a.encode('utf-8')  # Totally fine.
r = requests.post('http://httpbin.org/post', data=a)  # Using unicode string, throws UnicodeEncodeError blaming Latin1.
r = requests.post('http://httpbin.org/post', data=a.encode('utf-8'))  # Works fine.

Terima kasih telah menyampaikan ini bersama kami, tetapi ini bukan bug Permintaan. =)

Terima kasih.

r = request.post(' http://httpbin.org/post ', data=a.encode('utf-8'))
sangat berguna,
Terima kasih!

Apakah halaman ini membantu?
0 / 5 - 0 peringkat