La cadena de consulta de URL puede contener un parámetro, que no tiene ningún valor, es decir, http: // host / ruta /? Foo o http: // host / ruta /? A = 1 & foo. Actualmente, Requests no brinda soporte para eso.
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
Esperado:
'a=1&foo'
Puedo ver algo de valor en esto. Por razones de API, solo podría funcionar con el enfoque de 'lista de tuplas', pero estaría de acuerdo con que agreguemos soporte para esto. @ sigmavirus24?
No creo que lo usemos (todavía) pero parece que urllib3 usa urlencode
y nosotros también
Si examinamos cómo se comporta, puede ver que no le gusta ninguna de las formas propuestas de trabajar con esto. {'foo': None}
"funcionará" pero no hace lo correcto. Probablemente esta sea la razón por la que evitamos esto antes. Dicho esto, RFC 3986 tiene una definición muy ... flexible de la parte de
>>> 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
Relacionado: "urlencode de un valor None usa la cadena 'None'" - https://bugs.python.org/issue18857
Proporcione la entrada de @ piotr-dobrogost, @agilevic ,
Protuberancia. =)
>>> import requests
>>> r = requests.get('https://httpbin.org/get', params={'foo': ''})
>>> r.request.url
'https://httpbin.org/get?foo='
No es lo mismo que tener un parámetro sin valor. El suyo representa el signo = después del nombre del parámetro. Algunas aplicaciones funcionarán, pero como cuestión de proporcionar una solución completa, se debe abordar este caso exacto. Que urllib no lo haga no tiene importancia. Las solicitudes hacen muchas cosas mejor que las bibliotecas estándar para HTTP, esa es su razón de ser.
@agilevic ¿Cuál sería el diseño de API propuesto para esta función?
Aquí hay un pensamiento loco:
>>> import requests
>>> r = requests.get('https://httpbin.org/get', params={'foo': None})
>>> r.request.url
'https://httpbin.org/get?foo'
Eso es lo que creo que debería estar pasando.
Qué está pasando realmente:
'https://httpbin.org/get'
:(
@frnhr Entonces, la razón por la que no funciona con nuestra API es que establecer una clave en None
es la señal de "elimine esta clave del mapa". Tenemos esa señal porque algunos parámetros pueden persistir en un objeto de sesión en sí, y los usuarios ocasionalmente quieren poder suprimir esos parámetros por solicitud.
Me temo que no veo qué tiene que ver el objeto de sesión con este trozo de API, sinceramente. Pero bueno, tal vez False
entonces, o incluso algo de SpecialImportableObject
lugar de None
?
El 17 de septiembre de 2016, a las 07:47, Cory Benfield [email protected] escribió:
@frnhr Entonces, la razón por la que no funciona con nuestra API es que establecer una clave en Ninguno es la señal de "elimine esta clave del mapa". Tenemos esa señal porque algunos parámetros pueden persistir en un objeto de sesión en sí, y los usuarios ocasionalmente quieren poder suprimir esos parámetros por solicitud.
-
Recibes esto porque te mencionaron.
Responda a este correo electrónico directamente, véalo en GitHub o silencie el hilo.
@frnhr La Session
es relevante porque la API requests.
está construida sobre la API Session
: es un subconjunto de esa funcionalidad, una envoltura de conveniencia.
Así que ciertamente podríamos hacerlo, pero no estoy seguro de hasta qué punto vale la pena. Cuando no utilice el mapeo de clave-valor, simplemente debe pasar una cadena al campo params
: params="foo"
.
¿Qué pasaría si tuviéramos que hacer un argumento mecanografiado específico que pudiera indicar a las solicitudes que el parámetro se agregará sin un valor?
# 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'
No es None, no es una constante escalar ... por lo que debería ser compatible con versiones anteriores. Bajo el capó ... podríamos verificar ese tipo de valor y agregar especialmente este parámetro a la URL construida.
Entonces, si bien eso definitivamente funcionará, no creo que la API supere a Kenneth.
Sí, No. Preferiría admitir una función integrada como None
, y no estoy seguro de que sea la mejor idea, pero podría funcionar bien. False
no lo haría.
None
tampoco funcionará: el código base ya le da el significado de "desarmar el valor establecido en el nivel de sesión.
Sin embargo, sería un cambio bastante importante y no creo que beneficie a mucha gente. Quizás se podría considerar una tupla vacía. (por ejemplo, (,)
.
No estoy seguro de si esto se resolvió, pero encontré este hilo tratando de hacer exactamente lo mismo que agregar una clave sin un valor. "QueryAll" en mi caso, pero he tenido varias causas en mi Automatización RestAPI para hacer uso de este tipo de función.
¿Qué pasa si pasa {'QueryAll': ''}
?
Obtengo & QueryAll = al final.
Parece que depende de la API cómo maneja el "=" abierto, entonces, la API de PasswordState lo tomó tanto tiempo como estaba al final de mi lista de parámetros, si lo moví al principio, se produjo un error.
en 3.0, creo que podemos considerar hacer que la cadena vacía no resulte en un =
Eso sería genial :-D Hasta ahora, mi proyecto Passwordstate puede avanzar con el formato QueryAll = al final de la cadena de parámetros, así que estoy de nuevo en el camino correcto. Veré este hilo :-D
¡Gracias Kenneth!
No he escuchado ni visto nada todavía, pero no he dado la vuelta para ver si se han publicado actualizaciones.
Mella
De: Alex Zagoro [email protected]
Enviado: sábado 22 de septiembre de 2018 10:19 a.m.
Para: solicitudes / solicitudes [email protected]
Cc: Ellson, Nick [email protected] ; Comentario [email protected]
Asunto: Re: [solicitudes / solicitudes] No se puede crear una cadena de consulta de URL con un parámetro sin un valor (# 2651)
heya, ¿alguna actualización sobre esto?
También me encuentro con este problema en este momento. ¿Alguien más ha encontrado alguna forma de solucionar este problema?
Creo que todavía no hay solución en las solicitudes de esta característica simple pero muy común. extraño.
Desafortunadamente, enfrenta el mismo problema.
¿No sería un mejor patrón u opción poder inyectar / pasar un formateador / codificador personalizado opcional o una bandera específica para manejar el comportamiento Ninguno?
@Lukasa Parece que conoces el código base mejor que la mayoría de nosotros, ¿qué opinas al respecto?
¿No se resolvería eso en un cambio irreversible, @kennethreitz? Los valores predeterminados pueden configurarse para imitar el comportamiento de 2.x.
Parece que esto todavía está agregando el = cuando se pasa una cadena vacía. ¡Es hora de hacer una solución!
¿Entonces supongo que esto sigue siendo un problema?
Si tiene parámetros que no tienen valor, puede enumerarlos como parte de la URL y cualquier parámetro adicional se agregará con &
lugar de comenzar con ?
:
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'
¿Qué tal esta regla?
{ key: undefined }
a ?
_ (no incluido) _
{ key: null }
a ?key
{ key: '' }
a ?key=
{ key: 'null' }
a ?key=null
2020 ... y sigue siendo un problema ... SMH
Comentario más útil
en 3.0, creo que podemos considerar hacer que la cadena vacía no resulte en un =