2010-01-02 8 views
20

Je voudrais convertir cette commande curl en quelque chose que je peux utiliser en Python pour un script existant.Convertir une requête POST curl en Python uniquement en utilisant la bibliothèque standard

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

TEXTE est ce que je voudrais remplacer par un message généré par le reste du script (qui fonctionne déjà raisonnable, bien que je ne pense pas qu'il suit les meilleures pratiques ou particularité fiable -.. Besoin pour savoir comment apprendre correctement à programmer (ie ne pas utiliser google pour assembler des choses))

Je voudrais que cela fonctionne avec la bibliothèque standard si possible.

+1

Rendez-vous ici - http://stackoverflow.com/questions/4348061/how-to-use-python-urllib2-to-send-json- data-for-login/7469725 # 7469725 – treecoder

Répondre

23

Je voudrais que cela fonctionne avec la bibliothèque standard si possible.

La bibliothèque standard fournit urllib et httplib pour travailler avec des 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 

Si vous voulez exécuter curl lui-même, cependant, vous pouvez simplement invoquer 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 vous souhaitez assouplir la restriction de la bibliothèque standard, vous pouvez utiliser PycURL. Méfiez-vous que ce n'est pas très Pythonic (c'est juste un mince placage sur libcurl), et je ne suis pas sûr de savoir comment il est compatible avec Python 3.

+0

Utiliser httplib signifie ignorer certaines des fonctionnalités de urllib et urllib2, comme le support des proxies. –

+1

@dalke »C'est vrai; ceci est juste un exemple simple pour faire une demande 'GET' ou' POST', ce qui est je pense que le PO était après. –

+2

'c'est vrai.Je viens de trouver que l'utilisation de httplib et de faire URL munging ne vaut généralement pas l'effort étant donné que urllib2 vous donne tout cela et plus encore. –

12

Bien qu'il existe des moyens de gérer authentication in urllib2, si vous êtes autorisation de base faisant, (ce qui signifie envoyer efficacement le nom d'utilisateur et mot de passe en texte clair), vous pouvez faire tout ce que vous voulez avec un urllib2.Request et 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) 

Je l'ai testé cela avec netcat pour que je puisse voir que les données envoyées étaient, à l'exception de l'ordre de tri, identiques dans les deux cas. Ici, le premier a été fait avec boucle et le second avec 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 

(Ceci est légèrement modifié de la sortie. Mon cas de test n'a pas utilisé le même chemin d'URL que vous avez utilisé.)

Il n'y a pas besoin d'utiliser le httplib sous-jacent, qui ne supporte pas les choses qu'urllib2 vous donne comme support proxy. D'autre part, je trouve que urllib2 est compliqué en dehors de ce type de requête simple et si vous voulez un meilleur support pour les en-têtes qui sont envoyés et l'ordre qu'ils sont envoyés, utilisez httplib.

+0

je vous remercie pour l'extrait de chat net – nkint

2

Merci tous

cela fonctionne

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') 
Questions connexes