Hacer una llamada POST en lugar de GET usando urllib2

Hay muchas cosas por ahí en las llamadas urllib2 y POST, pero estoy atascado en un problema.

Estoy tratando de hacer una simple llamada POST a un servicio:

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

Puedo ver los registros del servidor y dice que estoy haciendo llamadas GET cuando envío el argumento de datos a urlopen.

La biblioteca está generando un error 404 (no encontrado), que es correcto para una llamada GET, las llamadas POST se procesan bien (también estoy intentando con un POST dentro de un formulario HTML).

Esto puede haber sido respondido antes: Python URLLib / URLLib2 POST .

Es probable que su servidor realice una redirección 302 de http://myserver/post_service a http://myserver/post_service/ . Cuando se realiza la redirección 302, la solicitud cambia de POST a GET (consulte el número 1401 ). Intente cambiar la url a http://myserver/post_service/ .

Hazlo en etapas, y modifica el objeto, así:

 # 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 esta manera, también puede ampliar las solicitudes PUT , DELETE , HEAD y OPTIONS , simplemente sustituyendo el valor del método o incluso envolviéndolo en una función. Dependiendo de lo que intente hacer, es posible que también necesite un controlador HTTP diferente, por ejemplo, para la carga de múltiples archivos.

El módulo de solicitudes puede aliviar su dolor.

 url = 'http://myserver/post_service' data = dict(name='joe', age='10') r = requests.post(url, data=data, allow_redirects=True) print r.content 

Lea el Manual faltante de urllib . Extraído de allí se encuentra el siguiente ejemplo simple de una solicitud 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() 

Según lo sugerido por @Michael Kent, considera las solicitudes , es genial.

EDITAR: Dicho esto, no sé por qué pasar datos a urlopen () no resulta en una solicitud POST; Debería. Sospecho que su servidor está redirigiendo, o mal comportamiento.

debería enviar un POST si proporciona un parámetro de datos (como lo está haciendo):

de la documentación: “la solicitud HTTP será un POST en lugar de un GET cuando se proporcione el parámetro de datos”

así que … agregue algo de salida de depuración para ver qué hay del lado del cliente.

Puedes modificar tu código para esto e intentarlo de nuevo:

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

Intenta esto en su lugar:

 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 
 url="https://myserver/post_service" data["name"] = "joe" data["age"] = "20" data_encoded = urllib2.urlencode(data) print urllib2.urlopen(url + "?" + data_encoded).read() 

Puede ser que esto pueda ayudar