Requests: 无法使用没有值的参数生成 URL 查询字符串

创建于 2015-06-25  ·  32评论  ·  资料来源: psf/requests

URL 查询字符串可能包含一个没有值的参数,即http://host/path/?foohttp://host/path/?a=1&foo。 目前 Requests 不提供支持。

In [68]: d
Out[68]: {'a': 1, 'foo': None}

In [69]: tl
Out[69]: [('a', 1), ('foo',)]

In [70]: RequestEncodingMixin._encode_params(d)
Out[70]: 'a=1'

In [71]: RequestEncodingMixin._encode_params(tl)
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-71-5d4dac855108> in <module>()
----> 1 RequestEncodingMixin._encode_params(tl)

/home/f557010/jpm/local/lib/python2.7/site-packages/requests/models.pyc in _encode_params(data)
     87         elif hasattr(data, '__iter__'):
     88             result = []
---> 89             for k, vs in to_key_val_list(data):
     90                 if isinstance(vs, basestring) or not hasattr(vs, '__iter__'):
     91                     vs = [vs]

ValueError: need more than 1 value to unpack

预期的:

'a=1&foo'
3.0 Breaking API Change Feature Request

最有用的评论

在 3.0 中,我认为我们可以考虑使空字符串不会导致 =

所有32条评论

我可以从中看到一些价值。 由于 API 原因,它只能与“元组列表”方法一起使用,但我愿意为我们添加对此的支持。 @sigmavirus24?

我不认为我们(还)使用它,但似乎urllib3 使用urlencode我们也是

如果我们检查它的行为方式,您会发现它不喜欢任何建议的处理方式。 {'foo': None}会“工作”,但不会做正确的事情。 这可能就是我们之前避免这种情况的原因。 也就是说,RFC 3986 对 URI 的查询部分有一个非常...松散的定义,所以在我看来,我们_应该_处理它。 也就是说,我不确定是否有任何工具可以让我们轻松处理它。 =/

>>> u = urlparse.urlparse('http://example.com/foo?bar')
>>> u
ParseResult(scheme='http', netloc='example.com', path='/foo', params='', query='bar', fragment='')
>>> urlparse.parse_qs(u.query)
{}
>>> urllib.urlencode({'foo': None})
'foo=None'
>>> urllib.urlencode([('foo',)])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/Cellar/python/2.7.9/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib.py", line 1336, in urlencode
    for k, v in query:
ValueError: need more than 1 value to unpack

相关:“无值的 urlencode 使用字符串 'None'” – https://bugs.python.org/issue18857

给@彼得- dobrogost的输入,@agilevic你试图使用空字符串值吗? 它适用于您的 API 服务器吗?

撞。 =)

>>> import requests
>>> r = requests.get('https://httpbin.org/get', params={'foo': ''})
>>> r.request.url
'https://httpbin.org/get?foo='

这与没有值的参数不同。 您在参数名称后呈现 = 符号。 某些应用程序可以工作,但作为提供完整解决方案的问题,应该解决这个确切的情况。 那个 urllib 不这样做是没有意义的。 Requests 比 HTTP 的标准库做得更好——这就是它存在的原因。

@agilevic您为此功能提议的 API 设计是什么?

这是一个疯狂的想法:

>>> import requests
>>> r = requests.get('https://httpbin.org/get', params={'foo': None})
>>> r.request.url
'https://httpbin.org/get?foo'

这就是我认为应该发生的事情。

实际发生的事情:

'https://httpbin.org/get'

:(

@frnhr因此,我们的 API 不起作用的原因是将键设置为None是“请从地图中删除此键”的信号。 我们有这个信号是因为某些参数可以持久保存在 Session 对象本身上,并且用户偶尔希望能够在每个请求的基础上抑制这些参数。

恐怕我不明白会话对象与这一点 API 有什么关系,真诚地。 但是好吧,也许False那么,或者甚至一些SpecialImportableObject而不是None

在2016年9月17日,在07:47,科里菲尔德[email protected]写道:

@frnhr因此,我们的 API 不起作用的原因是将键设置为 None 是“请从地图中删除此键”的信号。 我们有这个信号是因为某些参数可以持久保存在 Session 对象本身上,并且用户偶尔希望能够在每个请求的基础上抑制这些参数。


你收到这个是因为你被提到了。
直接回复此邮件,在 GitHub 上查看,或将线程静音。

@frnhr Session API 是相关的,因为requests. API 建立在Session API 之上:它是该功能的一个子集,一个方便的包装器。

所以我们当然可以做到,但我不确定它在多大程度上值得。 当不使用键值映射时,您应该只将一个字符串传递给params字段: params="foo"

如果我们要创建一个特定的类型化参数,它可以向请求表明要添加没有值的参数会怎样?

# defined somewhere in requests
class ValuelessParam(object):
    pass
....
....

params = {'foo': 'some_param', 'bar': requests.ValuelessParam()}

requests.get('http://something', params=params)

# url should be 'http://something?foo=some_param&bar'

它不是 None,也不是标量常数……所以它应该是向后兼容的。 在幕后……我们可以检查该值类型并专门将此参数附加到构造的 url 中。

所以虽然这肯定会奏效,但我认为 API 不会超过 Kenneth。

是的,不。我宁愿支持像None这样的内置函数,我不确定这是最好的主意——但它可以很好地工作。 False不会。

None也不起作用:代码库已经赋予它“取消设置在会话级别设置的值”的含义。

不过,这将是一个非常重大的变化,我认为它不会使很多人受益。 也许可以考虑一个空元组。 (例如(,)

不确定这是否已解决,但我发现该线程试图执行添加没有值的键的确切操作。 在我的例子中是“QueryAll”,但在我的 RestAPI 自动化中有很多原因可以使用这种功能。

如果你通过{'QueryAll': ''}什么?

最后我得到 &QueryAll= 。

看起来它有点取决于 API 如何处理打开的“=”,然后,PasswordState 的 API 将它放在我的参数列表的末尾,如果我将它移到开头,它就会出错。

在 3.0 中,我认为我们可以考虑使空字符串不会导致 =

那太好了:-D 到目前为止,我的 Passwordstate 项目可以在 params 字符串末尾使用 QueryAll= 格式向前移动,所以我回到了正轨。 我会看这个线程:-D

谢谢肯尼斯!

还没有听到或看到任何东西,但还没有回过头来看看是否已经发布了任何更新。

缺口

来源:亚历克斯Zagoro [email protected]
发送时间:2018 年 9 月 22 日星期六 10:19
至:请求/请求[email protected]
抄送:埃尔森,尼克[email protected] ; 评论[email protected]
主题:回复:[请求/请求] 无法使用没有值的参数生成 URL 查询字符串 (#2651)

嘿,这有什么更新吗?

我目前也遇到了这个问题。 有没有其他人找到解决这个问题的方法?

我相信对于这个简单但非常常见的功能的请求仍然没有解决方案。 奇怪的。

不幸面临同样的问题。
能够注入/传递可选的自定义格式化程序/编码器或用于处理 None 行为的特定标志不是更好的模式或选项吗?

@Lukasa你似乎比我们大多数人更了解代码库,你怎么看?

@kennethreitz,这不会在不间断的更改中解决吗? 默认值可以设置为模仿 2.x 行为。

当传入空字符串时,这似乎仍在添加 =。是时候解决问题了!

所以我猜这仍然是一个问题?

如果您有没有值的参数,您可以将它们列为 url 的一部分,任何其他参数将附加&而不是以?开头:

In [3]: r = requests.get("http://www.google.com", params={'test': 'true'})

In [4]: r.url
Out[4]: 'http://www.google.com/?test=true'

In [5]: r = requests.get("http://www.google.com?test2", params={'test': 'true'})

In [6]: r.url
Out[6]: 'http://www.google.com/?test2&test=true'

这个规定怎么样?

{ key: undefined }? _(不包括在内)_
{ key: null }?key
{ key: '' }?key=
{ key: 'null' }?key=null

2020 年......仍然是一个问题...... SMH

此页面是否有帮助?
0 / 5 - 0 等级