Requests: No se puede hacer una cadena de consulta de URL con un parámetro sin un valor

Creado en 25 jun. 2015  ·  32Comentarios  ·  Fuente: psf/requests

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'
3.0 Breaking API Change Feature Request

Comentario más útil

en 3.0, creo que podemos considerar hacer que la cadena vacía no resulte en un =

Todos 32 comentarios

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

¿Fue útil esta página
0 / 5 - 0 calificaciones

Temas relacionados

brainwane picture brainwane  ·  3Comentarios

NoahCardoza picture NoahCardoza  ·  4Comentarios

ReimarBauer picture ReimarBauer  ·  4Comentarios

avinassh picture avinassh  ·  4Comentarios

eromoe picture eromoe  ·  3Comentarios