python请求-使用'idna'编解码器编码失败(UnicodeError:标签为空或太长)错误 [英] python requests - encoding with 'idna' codec failed (UnicodeError: label empty or too long) error

查看:925
本文介绍了python请求-使用'idna'编解码器编码失败(UnicodeError:标签为空或太长)错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直与请求包一起使用的api调用突然返回以下错误: " UnicodeError:使用'idna'编解码器的编码失败(UnicodeError:标签为空或太长)"

An api call I have been using with the requests package is suddenly returning the following error: "UnicodeError: encoding with 'idna' codec failed (UnicodeError: label empty or too long)"

,我不知道如何解决此问题.我的代码如下所示,此示例伪造了某些凭据:

and I have no clue how to fix this. My code looks like the following, with certain credentials faked for this example:

api_key= '123abc'
password = '12345' #password that only idiots use on their luggage
shop_name = 'myshopname'
shop_url = 'https://%s:%s@%s.myecommercesite.com/admin/customers/1234567.json' %(api_key, password, shop_name)

a = requests.get(shop_url)

当我打印shop_url并将其粘贴到我的浏览器中时,我得到了期望在json中返回的数据.但是,当我运行此请求时,我得到了idna编解码器错误.

when I print the shop_url and paste it into my browser, I get the data returned that I am expecting in a json. But when I run this request, I get the idna codec error.

这曾经可以正常工作,但是某些地方显然有所改变,我不确定这是与电子商务网站还是与请求有关,或者是什么原因造成的.

This used to work without problem, but something changed somewhere apparently, and I'm not sure if it is with the ecommerce site or with requests or what that is causing this.

有人遇到这种错误或知道如何解决吗?

Has anyone encountered this type of error or know how to fix it?

如果我打印网址,它将看起来像: https://123abc:12345@myshopname.myecommercesite.com/admin/customers/1234567.json

if I print the url, it would look like: https://123abc:12345@myshopname.myecommercesite.com/admin/customers/1234567.json

edit2: 忘记在我的代码示例中包含%(api_key,password,shop_name) 完整的错误消息如下:

edit2: forgot to include %(api_key, password, shop_name) on my code example edit: entire error message below:

UnicodeError                              Traceback (most recent call last)
~/anaconda3/lib/python3.6/encodings/idna.py in encode(self, input, errors)
    164                 if not (0 < len(label) < 64):
--> 165                     raise UnicodeError("label empty or too long")
    166             if len(labels[-1]) >= 64:

UnicodeError: label empty or too long

The above exception was the direct cause of the following exception:

UnicodeError                              Traceback (most recent call last)
<ipython-input-15-f834b116b751> in <module>()
----> 1 a = requests.get(shop_url)

~/anaconda3/lib/python3.6/site-packages/requests/api.py in get(url, params, **kwargs)
     70 
     71     kwargs.setdefault('allow_redirects', True)
---> 72     return request('get', url, params=params, **kwargs)
     73 
     74 

~/anaconda3/lib/python3.6/site-packages/requests/api.py in request(method, url, **kwargs)
     56     # cases, and look like a memory leak in others.
     57     with sessions.Session() as session:
---> 58         return session.request(method=method, url=url, **kwargs)
     59 
     60 

~/anaconda3/lib/python3.6/site-packages/requests/sessions.py in request(self, method, url, params, data, headers, cookies, files, auth, timeout, allow_redirects, proxies, hooks, stream, verify, cert, json)
    497 
    498         settings = self.merge_environment_settings(
--> 499             prep.url, proxies, stream, verify, cert
    500         )
    501 

~/anaconda3/lib/python3.6/site-packages/requests/sessions.py in merge_environment_settings(self, url, proxies, stream, verify, cert)
    670             # Set environment's proxies.
    671             no_proxy = proxies.get('no_proxy') if proxies is not None else None
--> 672             env_proxies = get_environ_proxies(url, no_proxy=no_proxy)
    673             for (k, v) in env_proxies.items():
    674                 proxies.setdefault(k, v)

~/anaconda3/lib/python3.6/site-packages/requests/utils.py in get_environ_proxies(url, no_proxy)
    690     :rtype: dict
    691     """
--> 692     if should_bypass_proxies(url, no_proxy=no_proxy):
    693         return {}
    694     else:

~/anaconda3/lib/python3.6/site-packages/requests/utils.py in should_bypass_proxies(url, no_proxy)
    674     with set_environ('no_proxy', no_proxy_arg):
    675         try:
--> 676             bypass = proxy_bypass(netloc)
    677         except (TypeError, socket.gaierror):
    678             bypass = False

~/anaconda3/lib/python3.6/urllib/request.py in proxy_bypass(host)
   2610             return proxy_bypass_environment(host, proxies)
   2611         else:
-> 2612             return proxy_bypass_macosx_sysconf(host)
   2613 
   2614     def getproxies():

~/anaconda3/lib/python3.6/urllib/request.py in proxy_bypass_macosx_sysconf(host)
   2587     def proxy_bypass_macosx_sysconf(host):
   2588         proxy_settings = _get_proxy_settings()
-> 2589         return _proxy_bypass_macosx_sysconf(host, proxy_settings)
   2590 
   2591     def getproxies_macosx_sysconf():

~/anaconda3/lib/python3.6/urllib/request.py in _proxy_bypass_macosx_sysconf(host, proxy_settings)
   2560             if hostIP is None:
   2561                 try:
-> 2562                     hostIP = socket.gethostbyname(hostonly)
   2563                     hostIP = ip2num(hostIP)
   2564                 except OSError:

UnicodeError: encoding with 'idna' codec failed (UnicodeError: label empty or too long)

推荐答案

似乎这是socket模块的问题. URL超过64个字符时,它将失败.这仍然是一个未解决的问题 https://bugs.python.org/issue32958

It seems this is an issue from the socket module. It fails when the URL exceed 64 characters. This is still an open issue https://bugs.python.org/issue32958

当URL主机名的第一个子字符串长于64个字符时,可以一致地重现该错误,例如"0123456789012345678901234567890123456789012345678901234567890123.example.com".这不会有问题,只是它似乎没有从主机名的第一个子字符串中分离出凭据,因此整个"[user]:[secret] @XXX"部分的长度必须少于65个字符.对于使用更长的API密钥并期望通过基本身份验证提交的服务而言,这是有问题的.

The error can be consistently reproduced when the first substring of the url hostname is greater than 64 characters long, as in "0123456789012345678901234567890123456789012345678901234567890123.example.com". This wouldn't be a problem, except that it doesn't seem to separate out credentials from the first substring of the hostname so the entire "[user]:[secret]@XXX" section must be less than 65 characters long. This is problematic for services that use longer API keys and expect their submission over basic auth.

要使用Shopify API时,还有另一种解决方案: 在base64中对{api_key}:{password}进行编码,然后在您的请求的标头中发送该值,即{'Authorization': 'Basic {token_base_64}'}

As you want to use Shopify API, there is an alternative solution: encode {api_key}:{password} in base64 and send this value in the headers of your request ie. {'Authorization': 'Basic {token_base_64}'}

请在下面找到示例,它对我有用.

Please find example below, it works for me.

    import base64
    import requests

    (...)

    auth = "[API KEY]:[PASSWORD]"

    headers = {
        'Authorization': 'Basic {token}'.format(
            token=base64.b64encode(auth.encode()).decode('ascii'))
    }

    response = requests.get(
        url="https://[YOUR SHOP].myshopify.com/admin/[ENDPOINT]", 
        headers=headers
    )

这篇关于python请求-使用'idna'编解码器编码失败(UnicodeError:标签为空或太长)错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆