Requests: URL-Abfragezeichenfolge kann nicht mit einem Parameter ohne Wert erstellt werden

Erstellt am 25. Juni 2015  ·  32Kommentare  ·  Quelle: psf/requests

Die URL-Abfragezeichenfolge kann einen Parameter enthalten, der keinen Wert hat, zB http://host/path/?foo oder http://host/path/?a=1&foo. Derzeit bietet Requests keinen Support dafür.

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

Erwartet:

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

Hilfreichster Kommentar

in 3.0 denke ich, dass wir in Betracht ziehen können, dass eine leere Zeichenfolge nicht zu einem = . führt

Alle 32 Kommentare

Darin sehe ich einen gewissen Wert. Aus API-Gründen könnte es immer nur mit dem Ansatz "Liste der Tupel" funktionieren, aber ich wäre in Ordnung, wenn wir dies unterstützen. @sigmavirus24?

Ich glaube, wir verwenden es (noch) nicht, aber es scheint, dass urllib3 urlencode und wir auch

Wenn wir untersuchen, wie sich das verhält, können Sie feststellen, dass es keine der vorgeschlagenen Methoden zum Arbeiten damit mag. {'foo': None} wird "funktionieren", tut aber nicht das Richtige. Dies ist wahrscheinlich der Grund, warum wir dies zuvor vermieden haben. Das heißt, RFC 3986 hat eine sehr ... lose Definition des Abfrageteils eines URI, daher _sollten_ wir meiner Meinung nach damit umgehen. Das heißt, ich bin mir nicht sicher, ob es Tools gibt, mit denen wir ohne weiteres damit umgehen können. =/

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

Verwandte: "urlencode eines None-Werts verwendet die Zeichenfolge 'None'" – https://bugs.python.org/issue18857

Geben Sie die Eingabe von @piotr-dobrogost, @agilevic, haben Sie versucht, die leere Zeichenfolge als Wert dort zu verwenden? Funktioniert es mit Ihrem API-Server?

Stoßen. =)

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

Es ist nicht dasselbe wie einen Parameter ohne Wert zu haben. Ihre gibt das = Zeichen nach dem Parameternamen wieder. Einige Anwendungen werden funktionieren, aber um eine vollständige Lösung bereitzustellen, sollte genau dieser Fall angegangen werden. Dass die URL das nicht tut, ist ohne Bedeutung. Requests macht viele Dinge besser als Standardbibliotheken für HTTP - das ist der Grund für seine Existenz.

@agilevic Was wäre Ihr vorgeschlagenes API-Design für diese Funktion?

Hier ist ein verrückter Gedanke:

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

Das sollte meiner Meinung nach passieren.

Was passiert eigentlich:

'https://httpbin.org/get'

:(

@frnhr Der Grund, der mit unserer API nicht funktioniert, ist, dass das Setzen eines Schlüssels auf None das Signal für "bitte diesen Schlüssel von der Karte entfernen" ist. Wir haben dieses Signal, weil einige Parameter in einem Sitzungsobjekt selbst beibehalten werden können und Benutzer gelegentlich in der Lage sein möchten, diese Parameter auf Anfragebasis zu unterdrücken.

Ich fürchte, ich verstehe ehrlich gesagt nicht, was das Sitzungsobjekt mit dieser API zu tun hat. Aber ok, dann vielleicht False oder sogar SpecialImportableObject statt None ?

Am 17. September 2016 um 07:47 Uhr schrieb Cory Benfield [email protected] :

@frnhr Der Grund, der mit unserer API nicht funktioniert, ist, dass das Setzen eines Schlüssels auf None das Signal für "bitte diesen Schlüssel von der Karte entfernen" ist. Wir haben dieses Signal, weil einige Parameter in einem Sitzungsobjekt selbst beibehalten werden können und Benutzer gelegentlich in der Lage sein möchten, diese Parameter auf Anfragebasis zu unterdrücken.


Sie erhalten dies, weil Sie erwähnt wurden.
Antworten Sie direkt auf diese E-Mail, zeigen Sie sie auf GitHub an oder schalten Sie den Thread stumm.

@frnhr Die Session API ist relevant, weil die requests. API auf der Session API aufgebaut ist: sie ist eine Teilmenge dieser Funktionalität, ein praktischer Wrapper.

Wir könnten es also sicherlich tun, aber ich bin mir nicht sicher, inwieweit es sich lohnt. Wenn Sie die Schlüsselwertzuordnung nicht verwenden, sollten Sie einfach einen String an das Feld params : params="foo" .

Was wäre, wenn wir ein bestimmtes typisiertes Argument machen würden, das Anfragen anzeigen könnte, dass der Parameter ohne Wert hinzugefügt werden soll?

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

Es ist nicht None, es ist keine skalare Konstante ... also sollte es abwärtskompatibel sein. Unter der Haube ... könnten wir nach diesem Werttyp suchen und diesen Parameter speziell an die konstruierte URL anhängen.

Das wird zwar definitiv funktionieren, aber ich glaube nicht, dass API an Kenneth vorbeikommen wird.

Ja, nein. Ich würde eher ein integriertes System wie None , und ich bin mir nicht sicher, ob das die beste Idee ist – aber es könnte gut funktionieren. False würde nicht.

None wird auch nicht funktionieren: Die Codebasis gibt ihm bereits die Bedeutung von "unset the value set on the session level.

Das wäre jedoch eine ziemlich große Änderung, und ich glaube nicht, dass es vielen Menschen nützen würde. Vielleicht könnte ein leeres Tupel in Betracht gezogen werden. (zB (,) .

Ich bin mir nicht sicher, ob dies behoben wurde, aber ich habe diesen Thread gefunden, der versucht hat, genau einen Schlüssel ohne Wert hinzuzufügen. "QueryAll" in meinem Fall, aber ich hatte eine Reihe von Gründen in meiner RestAPI-Automatisierung, um diese Art von Funktion zu verwenden.

Was passiert, wenn Sie {'QueryAll': ''} passieren?

Ich bekomme &QueryAll= am Ende.

Es sieht so aus, als ob es an der API liegt, wie sie mit dem offenen "=" umgeht.

in 3.0 denke ich, dass wir in Betracht ziehen können, dass eine leere Zeichenfolge nicht zu einem = . führt

Das wäre toll :-D Bisher kann mein Passwordstate-Projekt mit dem QueryAll=-Format am Ende des Parameter-Strings vorankommen, damit ich wieder auf dem richtigen Weg bin. Ich werde mir diesen Thread anschauen :-D

Danke Kenneth!

Ich habe noch nichts gehört oder gesehen, aber nicht zurückgekehrt, um zu sehen, ob Updates veröffentlicht wurden.

Nick

Von: Alex Zagoro [email protected]
Gesendet: Samstag, 22. September 2018 10:19
An: Anfragen/Anfragen [email protected]
Cc: Ellson, Nick [email protected] ; Kommentar [email protected]
Betreff: Re: [requests/requests] URL-Abfragestring mit Parameter ohne Wert kann nicht erstellt werden (#2651)

Hey, gibt es dazu Neuigkeiten?

Ich beschäftige mich derzeit auch mit diesem Problem. Hat noch jemand einen Weg gefunden, dieses Problem zu umgehen?

Ich glaube, es gibt immer noch keine Lösung in Anfragen für dieses einfache, aber sehr verbreitete Feature. seltsam.

Stehe leider vor dem gleichen Problem.
Wäre es nicht ein besseres Muster oder eine bessere Option, einen optionalen benutzerdefinierten Formatierer/Encoder oder ein bestimmtes Flag für die Behandlung des Verhaltens „Keine“ injizieren/übergeben zu können?

@Lukasa Du

Würde sich das nicht in einer nicht brechenden Änderung lösen, @kennethreitz? Die Standardeinstellungen können so eingestellt werden, dass sie das 2.x-Verhalten nachahmen.

Es scheint, dass dies immer noch das = hinzufügt, wenn eine leere Zeichenfolge übergeben wird. Zeit, einen Workaround zu finden!

Also ich vermute das ist immer noch ein Problem?

Wenn Sie Parameter ohne Wert haben, können Sie sie als Teil der URL auflisten und alle zusätzlichen Parameter werden mit & angehängt, anstatt mit ? :

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'

Wie wäre es mit dieser Regel?

{ key: undefined } bis ? _(nicht enthalten)_
{ key: null } bis ?key
{ key: '' } bis ?key=
{ key: 'null' } bis ?key=null

2020... und immer noch ein Thema.... SMH

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen

Verwandte Themen

gabor picture gabor  ·  39Kommentare

digitaldavenyc picture digitaldavenyc  ·  39Kommentare

EB123 picture EB123  ·  33Kommentare

emgerner-msft picture emgerner-msft  ·  38Kommentare

philip-goh picture philip-goh  ·  53Kommentare