Requests: Impossible de créer une chaîne de requête URL avec un paramètre sans valeur

Créé le 25 juin 2015  ·  32Commentaires  ·  Source: psf/requests

La chaîne de requête d'URL peut contenir un paramètre qui n'a aucune valeur, c'est-à-dire http://host/path/?foo ou http://host/path/?a=1&foo. Actuellement, Requests ne fournit pas de support pour cela.

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

Attendu:

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

Commentaire le plus utile

en 3.0, je pense que nous pouvons envisager de faire en sorte que la chaîne vide ne donne pas un =

Tous les 32 commentaires

Je peux voir une certaine valeur à cela. Pour des raisons d'API, cela ne pourrait jamais fonctionner qu'avec l'approche "liste de tuples", mais je serais d'accord pour que nous ajoutions la prise en charge de cela. @sigmavirus24 ?

Je ne pense pas que nous l' utilisions (encore) mais il semble que nous aussi

Si nous examinons comment cela se comporte, vous pouvez voir qu'il n'aime aucune des façons proposées de travailler avec cela. {'foo': None} "fonctionnera" mais ne fera pas ce qu'il faut. C'est probablement pourquoi nous avons évité cela avant. Cela dit, la RFC 3986 a une définition très… vague de la partie requête d'un URI, donc à mon avis, nous devrions la gérer. Cela dit, je ne suis pas sûr qu'il existe des outils pour nous permettre facilement de le gérer. =/

>>> 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

Connexe : "le code urlen d'une valeur None utilise la chaîne 'None'" - https://bugs.python.org/issue18857

Donnez l'entrée de @piotr-dobrogost, @agilevic avez-vous essayé d'utiliser la chaîne vide comme valeur là-bas ? Fonctionne-t-il avec votre serveur API ?

Cogner. =)

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

Ce n'est pas la même chose que d'avoir un paramètre sans valeur. Le vôtre affiche le signe = après le nom du paramètre. Certaines applications fonctionneront, mais pour fournir une solution complète, ce cas précis doit être traité. Que urllib ne le fasse pas n'a aucune importance. Les requêtes font beaucoup mieux que les bibliothèques standard pour HTTP - c'est sa raison d'être.

@agilevic Quelle serait la conception de votre API proposée pour cette fonctionnalité ?

Voici une pensée folle :

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

C'est ce que je pense devrait se produire.

Que se passe-t-il réellement :

'https://httpbin.org/get'

:(

@frnhr Donc, la raison qui ne fonctionne pas avec notre API est que la définition d'une clé sur None est le signal "veuillez supprimer cette clé de la carte". Nous avons ce signal car certains paramètres peuvent être conservés sur un objet Session lui-même, et les utilisateurs veulent parfois pouvoir supprimer ces paramètres sur une base par demande.

Je crains de ne pas voir ce que l'objet de session a à voir avec ce morceau d'API, sincèrement. Mais bon, peut-être False alors, ou même quelques SpecialImportableObject au lieu de None ?

Le 17 septembre 2016, à 07h47, Cory Benfield [email protected] a écrit :

@frnhr Donc, la raison pour laquelle cela ne fonctionne pas avec notre API est que la définition d'une clé sur None est le signal "veuillez supprimer cette clé de la carte". Nous avons ce signal car certains paramètres peuvent être conservés sur un objet Session lui-même, et les utilisateurs veulent parfois pouvoir supprimer ces paramètres sur une base par demande.

-
Vous recevez ceci parce que vous avez été mentionné.
Répondez directement à cet e-mail, affichez-le sur GitHub ou coupez le fil de discussion.

@frnhr L' Session est pertinente car l'API requests. est construite au-dessus de l'API Session : c'est un sous-ensemble de cette fonctionnalité, un wrapper pratique.

Donc, nous pourrions certainement le faire, mais je ne sais pas dans quelle mesure cela en vaut la peine. Lorsque vous n'utilisez pas le mappage clé-valeur, vous devez simplement transmettre une chaîne au champ params : params="foo" .

Et si nous devions faire un argument typé spécifique qui pourrait indiquer aux requêtes que le paramètre doit être ajouté sans valeur ?

# 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'

Ce n'est pas Aucun, ce n'est pas une constante scalaire... donc il devrait être rétrocompatible. Sous le capot... nous pourrions vérifier ce type de valeur et spécialement ajouter ce paramètre à l'URL construite.

Donc, même si cela fonctionnera certainement, je ne pense pas que l'API dépassera Kenneth.

Oui, non. Je préférerais prendre en charge un élément intégré comme None , et je ne suis pas sûr que ce soit la meilleure idée, mais cela pourrait bien fonctionner. False ne le ferait pas.

None ne fonctionnera pas non plus : la base de code lui donne déjà le sens de "unset la valeur définie au niveau de la session.

Ce serait un changement assez important cependant, et je ne pense pas que cela profiterait à beaucoup de gens. Peut-être qu'un tuple vide pourrait être envisagé. (par exemple (,) .

Je ne sais pas si cela a été résolu, mais j'ai trouvé ce fil en train d'essayer de faire exactement la chose d'ajouter une clé sans valeur. "QueryAll" dans mon cas, mais j'ai eu un certain nombre de raisons dans mon RestAPI Automation pour utiliser ce type de fonction.

que se passe-t-il si vous passez {'QueryAll': ''} ?

J'obtiens &QueryAll= à la fin.

On dirait que c'est un peu à l'API de savoir comment elle gère le "=" ouvert, alors, l'API de PasswordState l'a pris aussi longtemps qu'il était à la fin de ma liste de paramètres, si je l'ai déplacé au début, il a généré une erreur.

en 3.0, je pense que nous pouvons envisager de faire en sorte que la chaîne vide ne donne pas un =

Ce serait génial :-D Jusqu'à présent, mon projet Passwordstate peut avancer avec le format QueryAll= à la fin de la chaîne de paramètres, donc je suis de retour sur la bonne voie. Je vais regarder ce fil :-D

Merci Kenneth !

Je n'ai encore rien entendu ou vu, mais je n'ai pas fait le tour pour voir si des mises à jour avaient été publiées.

pseudo

De : Alex Zagoro [email protected]
Envoyé : samedi 22 septembre 2018 10:19
À : requests/requests [email protected]
Cc : Ellson, Nick [email protected] ; Commentaire [email protected]
Objet : Re : [requests/requests] Impossible de créer une chaîne de requête URL avec un paramètre sans valeur (#2651)

heya, des mises à jour à ce sujet?

Je rencontre également ce problème en ce moment. Quelqu'un d'autre a-t-il trouvé un moyen de contourner ce problème ?

Je crois qu'il n'y a toujours pas de solution dans les demandes pour cette fonctionnalité simple mais très courante. bizarre.

Malheureusement confronté au même problème.
Ne serait-ce pas un meilleur modèle ou une meilleure option pour pouvoir injecter/passer un formateur/encodeur personnalisé facultatif ou un indicateur spécifique pour gérer le comportement Aucun ?

@Lukasa Vous semblez mieux connaître la base de code que la plupart d'entre nous, qu'en pensez-vous ?

Cela ne se résoudrait-il pas dans un changement ininterrompu, @kennethreitz ? Les valeurs par défaut peuvent être définies pour imiter le comportement 2.x.

Il semble que cela ajoute toujours le = lorsqu'une chaîne vide est transmise. Il est temps de trouver une solution de contournement !

Donc je suppose que c'est toujours un problème ?

Si vous avez des paramètres qui n'ont aucune valeur, vous pouvez les lister dans l'URL et tous les paramètres supplémentaires seront ajoutés avec & au lieu de commencer par ? :

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'

Et cette règle ?

{ key: undefined } à ? _(non inclus)_
{ key: null } à ?key
{ key: '' } à ?key=
{ key: 'null' } à ?key=null

2020... et toujours un problème... SMH

Cette page vous a été utile?
0 / 5 - 0 notes