Requests: Невозможно создать строку запроса URL с параметром без значения

Созданный на 25 июн. 2015  ·  32Комментарии  ·  Источник: psf/requests

Строка URL-запроса может содержать параметр, который не имеет значения, например http: // host / path /? Foo или http: // 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 использует строку« None »» - https://bugs.python.org/issue18857

Укажите ввод @ piotr-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 является сигналом для «пожалуйста, удалите этот ключ с карты». У нас есть этот сигнал, потому что некоторые параметры могут сохраняться в самом объекте сеанса, и пользователи иногда хотят иметь возможность подавлять эти параметры для каждого запроса.

Боюсь, я искренне не понимаю, какое отношение объект сеанса имеет к этому API. Но ладно, может тогда False , или даже SpecialImportableObject вместо None ?

17 сентября 2016 г. в 07:47 Кори Бенфилд [email protected] написал:

@frnhr Итак, причина, по которой это не работает с нашим API, заключается в том, что установка ключа на None является сигналом для «пожалуйста, удалите этот ключ с карты». У нас есть этот сигнал, потому что некоторые параметры могут сохраняться в самом объекте сеанса, и пользователи иногда хотят иметь возможность подавлять эти параметры для каждого запроса.

-
Вы получаете это, потому что вас упомянули.
Ответьте на это письмо напрямую, просмотрите его на GitHub или отключите обсуждение.

@frnhr API Session актуален, потому что 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 пройдет мимо Кеннета.

Да, нет. Я бы предпочел поддерживать встроенную функцию вроде None , и я не уверен, что это лучшая идея, но она может хорошо сработать. False нет.

None тоже не будет работать: кодовая база уже дает ему значение "сбросить значение, установленное на уровне сеанса".

Это было бы довольно серьезное изменение, и я не думаю, что многим оно принесет пользу. Возможно, можно было бы рассмотреть пустой кортеж. (например, (,) .

Не уверен, что это было решено, но я обнаружил, что этот поток пытается сделать то же самое, что и добавить ключ без значения. «QueryAll» в моем случае, но у меня было несколько причин в моей RestAPI Automation, чтобы использовать этот вид функции.

что произойдет, если вы передадите {'QueryAll': ''} ?

В конце я получаю & QueryAll =.

Похоже, это похоже на API относительно того, как он обрабатывает open "=", тогда API PasswordState использовал его столько, сколько он был в конце моего списка параметров, если я переместил его в начало, он вызвал ошибку.

в 3.0, я думаю, мы можем подумать о том, чтобы пустая строка не приводила к =

Это было бы здорово :-D Пока мой проект Passwordstate может двигаться вперед с форматом QueryAll = в конце строки параметров, так что я снова на правильном пути. Я посмотрю эту ветку :-D

Спасибо, Кеннет!

Еще ничего не слышал и не видел, но не обошел вокруг, чтобы посмотреть, были ли выпущены какие-либо обновления.

Ник

От: Алекс Загоро [email protected]
Отправлено: суббота, 22 сентября 2018 г., 10:19
Кому: запросы / запросы [email protected]
Копия: Эллсон, Ник [email protected] ; Комментарий [email protected]
Тема: Re: [запросы / запросы] Невозможно создать строку запроса 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 рейтинги