web-dev-qa-db-fra.com

Passer un appel POST au lieu de GET en utilisant urllib2

Il y a beaucoup de choses sur les appels urllib2 et POST, mais je suis bloqué sur un problème.

J'essaie de faire un simple POST appel à un service:

url = 'http://myserver/post_service'
data = urllib.urlencode({'name' : 'joe',
                         'age'  : '10'})
content = urllib2.urlopen(url=url, data=data).read()
print content

Je peux voir les journaux du serveur et m'indiquer que je passe des appels GET, lorsque j'envoie l'argument de données à urlopen.

La bibliothèque génère une erreur 404 (non trouvée), qui est correcte pour un appel GET. Les appels POST sont bien traités (j'essaie également avec un POST dans un formulaire HTML).

53
alfonso.kim

Vous avez peut-être déjà répondu à cette question: Python URLLib/URLLib2 POST .

Votre serveur est probablement en train d'effectuer une redirection 302 à partir de http://myserver/post_service à http://myserver/post_service/. Lorsque la redirection 302 est effectuée, la demande passe de POST à GET (voir numéro 1401 ). Essayez de remplacer url par http://myserver/post_service/.

43
Gregg

Faites-le par étapes et modifiez l'objet de la manière suivante:

# make a string with the request type in it:
method = "POST"
# create a handler. you can specify different handlers here (file uploads etc)
# but we go for the default
handler = urllib2.HTTPHandler()
# create an openerdirector instance
opener = urllib2.build_opener(handler)
# build a request
data = urllib.urlencode(dictionary_of_POST_fields_or_None)
request = urllib2.Request(url, data=data)
# add any other information you want
request.add_header("Content-Type",'application/json')
# overload the get method function with a small anonymous function...
request.get_method = lambda: method
# try it; don't forget to catch the result
try:
    connection = opener.open(request)
except urllib2.HTTPError,e:
    connection = e

# check. Substitute with appropriate HTTP code.
if connection.code == 200:
    data = connection.read()
else:
    # handle the error case. connection.read() will still contain data
    # if any was returned, but it probably won't be of any use

De cette façon, vous pouvez également faire des requêtes PUT, DELETE, HEAD et OPTIONS, simplement en substituant la valeur de method ou même en les enveloppant. dans une fonction. Selon ce que vous essayez de faire, vous aurez peut-être également besoin d'un autre gestionnaire HTTP, par exemple. pour le téléchargement de plusieurs fichiers.

43
user257111

Le module demandes peut soulager votre douleur.

url = 'http://myserver/post_service'
data = dict(name='joe', age='10')

r = requests.post(url, data=data, allow_redirects=True)
print r.content
11
Michael Kent

Lisez attentivement le manuel manquant d'urllib . Tiré de là, voici l'exemple simple suivant d'une requête POST.

url = 'http://myserver/post_service'
data = urllib.urlencode({'name' : 'joe', 'age'  : '10'})
req = urllib2.Request(url, data)
response = urllib2.urlopen(req)
print response.read()

Comme suggéré par @Michael Kent, considérez demandes , c'est génial.

EDIT: Ceci dit, je ne sais pas pourquoi transmettre des données à urlopen () n'entraîne pas une demande POST Je suppose que votre serveur redirige ou se comporte mal.

10
Rob Cowie

il devrait envoyer un POST si vous fournissez un paramètre de données (comme vous le faites):

from the docs: "la requête HTTP sera un POST au lieu d'un GET lorsque le paramètre de données est fourni"

alors .. ajoutez une sortie de débogage pour voir ce qui se passe du côté client.

vous pouvez modifier votre code en cela et réessayer:

import urllib
import urllib2

url = 'http://myserver/post_service'
opener = urllib2.build_opener(urllib2.HTTPHandler(debuglevel=1))
data = urllib.urlencode({'name' : 'joe',
                         'age'  : '10'})
content = opener.open(url, data=data).read()
5
Corey Goldberg

Essayez ceci à la place:

url = 'http://myserver/post_service'
data = urllib.urlencode({'name' : 'joe',
                         'age'  : '10'})
req = urllib2.Request(url=url,data=data)
content = urllib2.urlopen(req).read()
print content
1
rupello