Convierta una solicitud POST de rizo a Python solo usando la biblioteca estándar

Me gustaría convertir este comando curl a algo que pueda usar en Python para un script existente.

curl -u 7898678:X -H 'Content-Type: application/json' \ -d '{"message":{"body":"TEXT"}}' http://sample.com/36576/speak.json 

TEXTO es lo que me gustaría reemplazar con un mensaje generado por el rest de la secuencia de comandos (que ya está funcionando de manera razonable, aunque no creo que siga las mejores prácticas o particularidades confiables). para progtwigr (es decir, no usar google para ensamblar cosas)

Me gustaría que esto funcione con la biblioteca estándar si es posible.

Me gustaría que esto funcione con la biblioteca estándar si es posible.

La biblioteca estándar proporciona urllib y httplib para trabajar con URL:

 >>> import httplib, urllib >>> params = urllib.urlencode({'apple': 1, 'banana': 2, 'coconut': 'yummy'}) >>> headers = {"Content-type": "application/x-www-form-urlencoded", ... "Accept": "text/plain"} >>> conn = httplib.HTTPConnection("example.com:80") >>> conn.request("POST", "/some/path/to/site", params, headers) >>> response = conn.getresponse() >>> print response.status, response.reason 200 OK 

Sin embargo, si desea ejecutar curl , puede invocar os.system() :

 import os TEXT = ... cmd = """curl -u 7898678:X -H 'Content-Type: application/json'""" \ """-d '{"message":{"body":"%{t}"}}' http://sample.com/36576/speak.json""" % \ {'t': TEXT} 

Si estás dispuesto a relajar la restricción estándar de la biblioteca, puedes usar PycURL . Tenga en cuenta que no es muy Pythonic (es más o menos una chapa fina sobre libcurl), y no estoy seguro de qué tan compatible es con Python 3.

Si bien hay formas de manejar la autenticación en urllib2 , si está realizando una Autorización básica (lo que significa enviar efectivamente el nombre de usuario y la contraseña en texto sin cifrar), puede hacer todo lo que quiera con urllib2.Request y urllib2.urlopen:

 import urllib2 def basic_authorization(user, password): s = user + ":" + password return "Basic " + s.encode("base64").rstrip() req = urllib2.Request("http://localhost:8000/36576/speak.json", headers = { "Authorization": basic_authorization("7898678", "X"), "Content-Type": "application/json", # Some extra headers for fun "Accept": "*/*", # curl does this "User-Agent": "my-python-app/1", # otherwise it uses "Python-urllib/..." }, data = '{"message":{"body":"TEXT"}}') f = urllib2.urlopen(req) 

Probé esto con netcat para poder ver que los datos enviados eran, a excepción del orden, idénticos en ambos casos. Aquí el primero fue hecho con curl y el segundo con urllib2.

 % nc -l 8000 POST /36576/speak.json HTTP/1.1 Authorization: Basic Nzg5ODY3ODpY User-Agent: curl/7.19.4 (universal-apple-darwin10.0) libcurl/7.19.4 OpenSSL/0.9.8k zlib/1.2.3 Host: localhost:8000 Accept: */* Content-Type: application/json Content-Length: 27 {"message":{"body":"TEXT"}} ^C % nc -l 8000 POST /36576/speak.json HTTP/1.1 Accept-Encoding: identity Content-Length: 27 Connection: close Accept: */* User-Agent: my-python-app/1 Host: localhost:8000 Content-Type: application/json Authorization: Nzg5ODY3ODpY {"message":{"body":"TEXT"}}^C 

(Esto está ligeramente modificado de la salida. Mi caso de prueba no usó la misma ruta url que usó).

No hay necesidad de usar el httplib subyacente, que no es compatible con las cosas que urllib2 le brinda como soporte de proxy. Por otro lado, me parece que urllib2 es complicado fuera de este tipo de solicitud simple y si desea un mejor soporte para qué encabezados se envían y el orden en que se envían, utilice httplib.

Gracias a todos

esto funciona

 import urllib2 def speak(status): def basic_authorization(user, password): s = user + ":" + password return "Basic " + s.encode("base64").rstrip() req = urllib2.Request("http://example.com/60/speak.json", headers = { "Authorization": basic_authorization("2345670", "X"), "Content-Type": "application/json", "Accept": "*/*", "User-Agent": "my-python-app/1", }, data = '{"message":{"body":'+ status +'}}') f = urllib2.urlopen(req) speak('Yay') 

Eche un vistazo a pycurl http://pycurl.sourceforge.net/