cURL REquest mit Python 2.7

Code-Stücke können hier veröffentlicht werden.
andyritter
User
Beiträge: 29
Registriert: Montag 7. März 2016, 16:27

Hallo zusammen, bin noch eine Neuling in Python und versuche diese Abfrage mit Python umzusetzten

curl -s -H 'X-Auth-Token:abcd' "http://127.0.0.1:5000/v2.0/Liste"

Als Antwort kommt in der Shell ein JSON.

Danke für eure Hilfe

Gruß Andreas
Sirius3
User
Beiträge: 17737
Registriert: Sonntag 21. Oktober 2012, 17:20

@andyritter: Du willst jetzt nicht wissen, dass es dafür in der Standardbibliothek das Modul urllib2 gibt und man am besten das 3rd-party Modul requests für solche Aufgaben nimmt. Denn das sagt einem google wenn man nur nach python und http sucht.
andyritter
User
Beiträge: 29
Registriert: Montag 7. März 2016, 16:27

Hallo Sirius3,

ich habe das Problem, dass bei meinen bisherigen Versuchen als Neuling in Python immer wieder einen Bad Request vom Server zurückerhalten oder bin gar nicht bis zum Server durchgekommen. Da ich das ganze noch nicht so nachvollziehen kann und auch mit den Modulen noch zum Teil am Verständnis hänge, hier die Nachfrage.
Gruß Andy
DasIch
User
Beiträge: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

Bei einem Bad Request würde ich mal davon ausgehen dass der X-Auth-Token Header nicht gesetzt ist.
Sirius3
User
Beiträge: 17737
Registriert: Sonntag 21. Oktober 2012, 17:20

@andyritter: das sind z.B. Informationen, die man in eine Frage schreiben könnte. Dazu ist immer hilfreich den Code zu posten, der den Fehler produziert und auch die vollständige Fehlermeldung inklusive Traceback.
andyritter
User
Beiträge: 29
Registriert: Montag 7. März 2016, 16:27

Danke Sirius, ich gelobe Besserung ;-)

Ich habe bereits eine Abfrage an den Server wegen des Tokens, dies wird mit httplib2 ausgeführt und ist erfolgreich. In gleicher Manier wollte ich nun auch diese Liste abrufen.

Shell, (liefert eine JSON Antwort.)
curl -s -H 'X-Auth-Token:abcd' "http://127.0.0.1:5000/v2.0/Liste"


Mein Versuch mit httplib2

import httplib2 as http
import json
import base64
try:
from urlparse import urlparse
except ImportError:
from urllib.parse import urlparse
token_id = 'abcd'
body_string_tenants = 'X-Auth-Token:' + token_id

headers = {
'Accept': 'application/json',
'Content-Type': 'application/json; charset=UTF-8'
}

uri = 'http://127.0.0.1:5000'
path = '/v2.0/Liste'

target = urlparse(uri+path)
method = 'GET'
body = '{"X-Auth-Token:abcd"}'

h = http.Http()

response, tenant_list = h.request(
target.geturl(),
method,
body,
headers)


Die Fehlermeldung:
{"error": {"message": "Expecting to find valid JSON in request body - the server could not comply with the request since it is either malformed or otherwise incorrect. The client is assumed to be in error.", "code": 400, "title": "Bad Request"}}
DasIch
User
Beiträge: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

Nun die Fehlermeldung beschreibt das Problem doch recht deutlich und ist auch offensichtlich richtig.
andyritter
User
Beiträge: 29
Registriert: Montag 7. März 2016, 16:27

@DasIch
Die Fehlermeldung an sich verstehe ich ja, allerdings komme ich zu keine Lösung, in der das dann funktioniert.

lasse ich die ' im body weg erhalte ich folgende Fehlermeldung:

Traceback (most recent call last):
File "/home/andreas/Schreibtisch/Liste.py", line 41, in <module>
headers)
File "/usr/lib/python2.7/site-packages/httplib2-0.8-py2.7.egg/httplib2/__init__.py", line 1570, in request
(response, content) = self._request(conn, authority, uri, request_uri, method, body, headers, redirections, cachekey)
File "/usr/lib/python2.7/site-packages/httplib2-0.8-py2.7.egg/httplib2/__init__.py", line 1317, in _request
(response, content) = self._conn_request(conn, request_uri, method, body, headers)
File "/usr/lib/python2.7/site-packages/httplib2-0.8-py2.7.egg/httplib2/__init__.py", line 1253, in _conn_request
conn.request(method, request_uri, body, headers)
File "/usr/lib64/python2.7/httplib.py", line 979, in request
self._send_request(method, url, body, headers)
File "/usr/lib64/python2.7/httplib.py", line 1013, in _send_request
self.endheaders(body)
File "/usr/lib64/python2.7/httplib.py", line 975, in endheaders
self._send_output(message_body)
File "/usr/lib64/python2.7/httplib.py", line 839, in _send_output
self.send(message_body)
File "/usr/lib64/python2.7/httplib.py", line 811, in send
self.sock.sendall(data)
File "/usr/lib64/python2.7/socket.py", line 224, in meth
return getattr(self._sock,name)(*args)
TypeError: must be string or buffer, not set

daher komme ich mit meinem Anfängerwissen hier leider nicht weiter.

Mit Wireshark habe ich die Anfragen mit geschnitten und folgende Ausgaben erhalten:

Curl:
GET /v2.0/tenants HTTP/1.1
User-Agent: curl/7.29.0
Host: 127.0.0.1:5000
Accept: */*
X-Auth-Token:abcd

HTTP/1.1 200 OK
Date: Fri, 11 Mar 2016 08:29:58 GMT
Server: Apache/2.4.6 (Red Hat Enterprise Linux)
Vary: X-Auth-Token
Content-Length: 427
Connection: close
Content-Type: application/json

{......Liste....}]} => alles ok

mit Python und meiner Abfrage:
GET /v2.0/tenants HTTP/1.1
Host: 127.0.0.1:5000
Content-Length: 49
accept-encoding: gzip, deflate
accept: */*
user-agent: Python-httplib2/0.8 (gzip)

{"X-Auth-Token:abcd"}HTTP/1.1 400 Bad Request
Date: Fri, 11 Mar 2016 08:56:03 GMT
Server: Apache/2.4.6 (Red Hat Enterprise Linux)
Vary: X-Auth-Token
Content-Length: 245
Connection: close
Content-Type: application/json

{"error": {"message": "Expecting to find valid JSON in request body - the server could not comply with the request since it is either malformed or otherwise incorrect. The client is assumed to be in error.", "code": 400, "title": "Bad Request"}}

Gibt es eine einfachere Weise um an der REST Schnittstelle von OpenStack diese Liste zu erhalten?
Sirius3
User
Beiträge: 17737
Registriert: Sonntag 21. Oktober 2012, 17:20

Wußte gar nicht, dass irgendein Server bei einem GET-Request den Body parst. Macht ja auch wenig Sinn.
Dav1d
User
Beiträge: 1437
Registriert: Donnerstag 30. Juli 2009, 12:03
Kontaktdaten:

Steht doch da .. Einmal schickst du den X-Auth-Token als Header mit (curl) und einmal versuchst du den über den Body zu übergeben (Python).

Edit: Du willst dir eventuell requests anschauen. Wenn du eine Requests-Session verwendest, kannst du den Header hinzufügen und brauchst dich nicht mehr darum zu kümmern.
the more they change the more they stay the same
andyritter
User
Beiträge: 29
Registriert: Montag 7. März 2016, 16:27

@Dav1d
leider habe ich Deine Antwort nicht verstanden.

Verwende ich requests, so erhalte ic folgende Fehlermeldung:

import requests
r = requests.get('http://127.0.0.1:5000/v2.0/Liste')
r.json()


Meldung:
Traceback (most recent call last):
File "/home/andreas/Schreibtisch/tenants_list_requests_test.py", line 1, in <module>
import requests
File "/usr/lib/python2.7/site-packages/requests-2.9.1-py2.7.egg/requests/__init__.py", line 58, in <module>
from . import utils
File "/usr/lib/python2.7/site-packages/requests-2.9.1-py2.7.egg/requests/utils.py", line 26, in <module>
from .compat import parse_http_list as _parse_list_header
File "/usr/lib/python2.7/site-packages/requests-2.9.1-py2.7.egg/requests/compat.py", line 38, in <module>
from urllib2 import parse_http_list
File "/home/andreas/Schreibtisch/urllib2.py", line 4, in <module>
AttributeError: 'module' object has no attribute 'POST'


und das deutet für mich eher an, dass im Modul requests etwas nicht korrekt ist oder?
Wie würde deiner Meinung nach denn der Code mit requests aussehen?
Sirius3
User
Beiträge: 17737
Registriert: Sonntag 21. Oktober 2012, 17:20

@andyritter: das Problem ist, dass Du ein Modul der Standardbibliothek (urllib2) durch Deine eigene Python-Datei urllib2.py überlagerst.
andyritter
User
Beiträge: 29
Registriert: Montag 7. März 2016, 16:27

@Sirius3
ich finde in diesem Pfad keine Datei urllib2.py, wie könnte so etwas zustande kommen?
Sirius3
User
Beiträge: 17737
Registriert: Sonntag 21. Oktober 2012, 17:20

Und was für eine Datei ist /home/andreas/Schreibtisch/urllib2.py?
andyritter
User
Beiträge: 29
Registriert: Montag 7. März 2016, 16:27

die Datei hat die Erweiterung .pyc

Sorry, ich möchte hier niemanden angreifen oder beleidigen. Ich habe erst seit kurzem eine CetOS 7 Umgebung und auch mit Python erst vor kurzem angefangen. Daher sind das sicher alles Anfängerfragen...
andyritter
User
Beiträge: 29
Registriert: Montag 7. März 2016, 16:27

@Dav1d

Bei requests komme ich leider auch nicht weiter. Ich habe mir jetzt schon eine zweite CentOS7 Maschine eingerichtet, damit ich alle Zusatzmodule unter root einrichte und nicht unter meinem User.
Bei meinem Code
import requests

url = 'http://127.0.0.1:5000/v2.0/Liste'
header = {'X-Auth-Token: abcd'}

r= requests.get(url, headers=header)

r.json()
print(r)


erhalte ich folgende Meldung:

Traceback (most recent call last):
File "/home/andreas/Dokumente/tenants_list_requests.py", line 6, in <module>
r= requests.get(url, headers=header)
File "/usr/lib/python2.7/site-packages/requests-2.9.1-py2.7.egg/requests/api.py", line 67, in get
return request('get', url, params=params, **kwargs)
File "/usr/lib/python2.7/site-packages/requests-2.9.1-py2.7.egg/requests/api.py", line 53, in request
return session.request(method=method, url=url, **kwargs)
File "/usr/lib/python2.7/site-packages/requests-2.9.1-py2.7.egg/requests/sessions.py", line 454, in request
prep = self.prepare_request(req)
File "/usr/lib/python2.7/site-packages/requests-2.9.1-py2.7.egg/requests/sessions.py", line 388, in prepare_request
hooks=merge_hooks(request.hooks, self.hooks),
File "/usr/lib/python2.7/site-packages/requests-2.9.1-py2.7.egg/requests/models.py", line 294, in prepare
self.prepare_headers(headers)
File "/usr/lib/python2.7/site-packages/requests-2.9.1-py2.7.egg/requests/models.py", line 405, in prepare_headers
self.headers = CaseInsensitiveDict((to_native_string(name), value) for name, value in headers.items())
AttributeError: 'set' object has no attribute 'items'


Was mache ich falsch?
Benutzeravatar
pillmuncher
User
Beiträge: 1484
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

@andyritter: vergleich mal:

Code: Alles auswählen

>>> header = {'X-Auth-Token: abcd'}
>>> type(header)
<type 'set'>
>>> header['X-Auth-Token']
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'set' object has no attribute '__getitem__'
>>> header.items()                                                              
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'set' object has no attribute 'items'

Code: Alles auswählen

>>> header = {'X-Auth-Token': 'abcd'}
>>> type(header)                                                                
<type 'dict'>
>>> header['X-Auth-Token']                                                      
'abcd'
>>> header.items()
[('X-Auth-Token', 'abcd')]
In specifications, Murphy's Law supersedes Ohm's.
andyritter
User
Beiträge: 29
Registriert: Montag 7. März 2016, 16:27

@pillmuncher
ich kann Dir da im Moment leider nicht folgen. Was möchtest Du mir damit denn erklären?

Im oberen Script wird versucht ein Set zu verwenden und im zweiten ein dictionary?

In der Dokumentation unter http://docs.python-requests.org/en/mast ... rs-in-urls finde ich nichts konkretes zu meinem Problem :-(
Benutzeravatar
pillmuncher
User
Beiträge: 1484
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

@andyritter: Vergleich mal Zeichen für Zeichen:

Code: Alles auswählen

>>> header = {'X-Auth-Token: abcd'}
>>> header = {'X-Auth-Token': 'abcd'}
In specifications, Murphy's Law supersedes Ohm's.
BlackJack

@andyritter: Wenn man ein Problem beim `header` hat, sollte man auch *dort* in der Dokumentation schauen und nicht bei der Übergabe von Daten: http://docs.python-requests.org/en/mast ... om-headers ;-)
Antworten