Requests: Não é possível criar string de consulta de URL com um parâmetro sem valor

Criado em 25 jun. 2015  ·  32Comentários  ·  Fonte: psf/requests

A string de consulta de URL pode conter um parâmetro sem valor, ou seja, http: // host / caminho /? Foo ou http: // host / caminho /? A = 1 & foo. Atualmente, o Requests não oferece suporte para isso.

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

Comentários muito úteis

no 3.0, acho que podemos considerar fazer com que a string vazia não resulte em um =

Todos 32 comentários

Eu posso ver algum valor nisso. Por motivos de API, ele só funcionaria com a abordagem de 'lista de tuplas', mas concordaria em adicionar suporte para isso. @ sigmavirus24?

Acho que não usamos (ainda), mas parece que urllib3 usa urlencode e nós também

Se examinarmos como isso se comporta, você pode ver que não gosta de nenhuma das formas propostas de trabalhar com isso. {'foo': None} "funcionará", mas não faz a coisa certa. É provavelmente por isso que evitamos isso antes. Dito isso, o RFC 3986 tem uma definição muito ... vaga da parte da

>>> 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 um valor Nenhum usa a string 'Nenhum'" - https://bugs.python.org/issue18857

Dê a entrada de @ piotr-dobrogost, @agilevic você tentou usar a string vazia como o valor lá? Funciona com o seu servidor API?

Ressalto. =)

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

Não é o mesmo que ter um parâmetro sem valor. O seu renderiza o sinal = após o nome do parâmetro. Alguns aplicativos funcionarão, mas como uma questão de fornecer uma solução completa, esse caso exato deve ser abordado. Que o urllib não o faça não tem importância. Requests faz muitas coisas melhor do que bibliotecas padrão para HTTP - essa é a razão de sua existência.

@agilevic Qual seria sua proposta de design de API para esse recurso?

Aqui está um pensamento maluco:

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

Isso é o que eu acho que deveria estar acontecendo.

O que realmente está acontecendo:

'https://httpbin.org/get'

:(

@frnhr Portanto, o motivo que não funciona com a nossa API é que definir uma chave como None é o sinal para "remova esta chave do mapa". Temos esse sinal porque alguns parâmetros podem ser persistentes no próprio objeto de Sessão, e os usuários ocasionalmente desejam suprimir esses parâmetros por solicitação.

Infelizmente, não vejo o que o objeto de sessão tem a ver com esse pedaço de API. Mas ok, talvez False então, ou mesmo algum SpecialImportableObject vez de None ?

Em 17 de setembro de 2016, às 07:47, Cory Benfield [email protected] escreveu:

@frnhr Portanto, o motivo que não funciona com nossa API é que definir uma chave como Nenhum é o sinal para "remova esta chave do mapa". Temos esse sinal porque alguns parâmetros podem ser persistentes no próprio objeto de Sessão, e os usuários ocasionalmente desejam suprimir esses parâmetros por solicitação.

-
Você está recebendo isso porque foi mencionado.
Responda a este e-mail diretamente, visualize-o no GitHub ou ignore a conversa.

@frnhr A Session é relevante porque a API requests. é construída sobre a API Session : é um subconjunto dessa funcionalidade, um invólucro de conveniência.

Certamente poderíamos fazer isso, mas não tenho certeza de até que ponto vale a pena. Quando não estiver usando o mapeamento de valor-chave, você deve apenas passar uma string para o campo params : params="foo" .

E se tivéssemos de fazer um argumento digitado específico que pudesse indicar às solicitações que o parâmetro deve ser adicionado sem um 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'

Não é nenhum, não é uma constante escalar ... então deve ser compatível com versões anteriores. Nos bastidores ... poderíamos verificar esse tipo de valor e, especialmente, anexar esse parâmetro à url construída.

Portanto, embora isso definitivamente funcione, não acho que a API passará pelo Kenneth.

Sim, não. Prefiro oferecer suporte a um sistema integrado como None , e não tenho certeza se essa é a melhor ideia - mas poderia funcionar bem. False não.

None também não funcionará: a base de código já lhe dá o significado de "desconfigurar o valor definido no nível da sessão.

Isso seria uma grande mudança, porém, e não acho que beneficiaria muitas pessoas. Talvez uma tupla vazia possa ser considerada. (por exemplo, (,) .

Não tenho certeza se isso foi resolvido, mas encontrei este tópico tentando fazer a coisa exata de adicionar uma chave sem um valor. "QueryAll" no meu caso, mas tive várias causas na minha Automação RestAPI para fazer uso desse tipo de função.

o que acontece se você passar {'QueryAll': ''} ?

Recebo & QueryAll = no final.

Parece que depende da API como ela lida com o open "=", então, a API do PasswordState demorou tanto quanto estava no final da minha lista de parâmetros, se eu movesse para o início, seria um erro.

no 3.0, acho que podemos considerar fazer com que a string vazia não resulte em um =

Isso seria ótimo :-D Até agora, meu projeto Passwordstate pode avançar com o formato QueryAll = no final da string de parâmetros, então estou de volta aos trilhos. Vou assistir a este tópico :-D

Obrigado Kenneth!

Ainda não ouvi ou vi nada, mas não voltei para ver se alguma atualização foi lançada.

usuario

De: Alex Zagoro [email protected]
Enviado: sábado, 22 de setembro de 2018 10:19
Para: solicitações / solicitações solicitaçõ[email protected]
Cc: Ellson, Nick [email protected] ; Comentário [email protected]
Assunto: Re: [solicitações / solicitações] Não é possível fazer string de consulta de URL com um parâmetro sem um valor (# 2651)

heya, alguma atualização sobre isso?

Também estou enfrentando esse problema no momento. Alguém mais encontrou alguma maneira de contornar este problema?

Acredito que ainda não haja solução nas solicitações desse recurso simples, mas muito comum. estranhas.

Infelizmente, enfrentando o mesmo problema.
Não seria um padrão ou opção melhor ser capaz de injetar / passar um formatador / codificador personalizado opcional ou um sinalizador específico para lidar com o comportamento Nenhum?

@Lukasa Você parece conhecer a base de código melhor do que a maioria de nós, o que você acha disso?

Isso não resolveria em uma mudança ininterrupta, @kennethreitz? Os padrões podem ser definidos para simular o comportamento 2.x.

Parece que isso ainda está adicionando o = quando uma string vazia é passada. É hora de encontrar uma solução alternativa!

Acho que isso ainda é um problema?

Se você tiver parâmetros sem valor, poderá listá-los como parte do url e quaisquer parâmetros adicionais incluirão & vez de começar com ? :

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'

Que tal essa regra?

{ key: undefined } a ? _ (não incluído) _
{ key: null } a ?key
{ key: '' } a ?key=
{ key: 'null' } a ?key=null

2020 ... e ainda um problema ... SMH

Esta página foi útil?
0 / 5 - 0 avaliações

Questões relacionadas

javixeneize picture javixeneize  ·  37Comentários

pensnarik picture pensnarik  ·  33Comentários

invisiblethreat picture invisiblethreat  ·  57Comentários

scoder picture scoder  ·  44Comentários

ghost picture ghost  ·  36Comentários