web-dev-qa-db-ja.com

カールを変換するPOSTリクエストをPython標準ライブラリのみを使用して

このcurlコマンドを、既存のスクリプトのPythonで使用できるものに変換したいと思います。

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

TEXTは、スクリプトの残りの部分によって生成されたメッセージに置き換えたいものです(これは、ベストプラクティスや信頼できる特殊性に従っているとは思いませんが、すでに合理的に機能しています。-適切に学習する方法を見つける必要があります。プログラムする(つまり、ものを組み立てるためにグーグルを使用しない))

可能であれば、これを標準ライブラリで動作させたいと思います。

20
Jimm

可能であれば、これを標準ライブラリで動作させたいと思います。

標準ライブラリは urllib およびhttplibURLを操作する場合:

_>>> 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
_

ただし、curl自体を実行する場合は、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}
_

標準ライブラリのみの制限を緩和する場合は、 PycURL を使用できます。あまりPythonicではないことに注意してください(libcurlの薄いベニヤにすぎません)。また、Python 3との互換性がどれほどあるかわかりません。

23
John Feminella

rllib2での認証 を処理する方法はありますが、基本認証(つまり、ユーザー名とパスワードをクリアテキストで効果的に送信する)を実行している場合は、urllib2で必要なすべてを実行できます。リクエストと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)

これを netcat でテストしたので、送信されたデータは、並べ替え順序を除いて、どちらの場合も同じであることがわかりました。ここでは、最初の1つはcurlで実行され、2つ目は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

(これは出力からわずかに調整されています。私のテストケースは、使用したのと同じURLパスを使用しませんでした。)

基盤となるhttplibを使用する必要はありません。これは、urllib2がプロキシサポートのように提供するものをサポートしていません。一方、urllib2は、この単純な種類のリクエスト以外では複雑であることがわかります。送信されるヘッダーと送信される順序をより適切にサポートしたい場合は、httplibを使用してください。

12
Andrew Dalke

いつもありがとう

これは動作します

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')
2
Jimm

Pycurlを見てください http://pycurl.sourceforge.net/

1
z33m