3

現在、HTTP リクエストにPythonリクエストを使用していますが、API の制限により、ライブラリを使い続けることができません。

送信するすべてのデータがすぐに利用できるわけではないため、ストリーミング ファイルのような方法でリクエスト本文を記述できるライブラリが必要です。また、できるだけ多くのメモリを節約したいです。リクエストをするとき。次のような PUT リクエストを送信できる使いやすいライブラリはありますか。

request = HTTPRequest()
request.headers['content-type'] = 'application/octet-stream'
# etc
request.connect()

# send body
with open('myfile', 'rb') as f:
    while True:
        chunk = f.read(64 * 1024)
        request.body.write(chunk)
        if not len(chunk) == 64 * 1024:
            break

# finish
request.close()

より具体的には、作業するスレッドが 1 つあります。このスレッドを使用して、ネットワーク経由でストリームを受信すると、コールバックを受信します。基本的に、これらのコールバックは次のようになります。

class MyListener(Listener):
    def on_stream_start(stream_name):
        pass

    def on_stream_chunk(chunk):
        pass

    def on_stream_end(total_size):
        pass

基本的に、メソッドでアップロード リクエストを作成し、on_stream_startメソッドでチャンクをアップロードしてから、メソッドでon_stream_chunkアップロードを完了する必要がありon_stream_endます。したがって、次のような方法をサポートするライブラリが必要ですwrite(chunk)

class MyListener(Listener):
    request = None

    def on_stream_start(stream_name):
        request = RequestObject(get_url(), "PUT")
        request.headers.content_type = "application/octet-stream"
        # ...

    def on_stream_chunk(chunk):
        request.write_body(chunk + sha256(chunk).hexdigest())

    def on_stream_end(total_size):
        request.close()

このライブラリは、読み取りrequests用のファイルのようなオブジェクトとジェネレーターをサポートしていますが、要求を書き出すためのものはサポートしていません: プッシュではなくプルです。データをサーバーにプッシュできるライブラリはありますか?

4

4 に答える 4

1

Requests は実際には、次のfilesパラメータを使用してマルチパート エンコードされたリクエストをサポートしています。

公式ドキュメントのマルチパート POST の例:

url = 'http://httpbin.org/post'
files = {'file': open('report.xls', 'rb')}

r = requests.post(url, files=files)
r.text
{
  ...
  "files": {
    "file": "<censored...binary...data>"
  },
  ...
}

必要に応じて独自のファイルのようなストリーミング オブジェクトを作成することもできますが、同じ要求でストリームとファイルを混在させることはできません。

あなたにとってうまくいくかもしれない単純なケースは、ファイルを開いて、チャンク、ジェネレーターベースのリーダーを返すことです:

def read_as_gen(filename, chunksize=-1): # -1 defaults to read the file to the end, like a regular .read()
    with open(filename, mode='rb') as f:
        while True:
            chunk = f.read(chunksize)
            if len(chunk) > 0:
                yield chunk
            else:
                raise StopIteration

# Now that we can read the file as a generator with a chunksize, give it to the files parameter
files = {'file': read_as_gen(filename, 64*1024)}

# ... post as normal.

しかし、別のネットワーク バッファなど、他の何かでチャンクをブロックする必要がある場合は、同じ方法で処理できます。

def read_buffer_as_gen(buffer_params, chunksize=-1): # -1 defaults to read the file to the end, like a regular .read()
    with buffer_open(*buffer_params) as buf: # some function to open up your buffer
    # you could also just pass in the buffer itself and skip the `with` block
        while True:
            chunk = buf.read(chunksize)
            if len(chunk) > 0:
                yield chunk
            else:
                raise StopIteration
于 2013-04-15T20:42:19.490 に答える
-2

これは役立つかもしれません

import urllib2

request = urllib2.Request(uri, data=data)
request.get_method = lambda: 'PUT' # or 'DELETE'
response = urllib2.urlopen(request)
于 2013-04-18T01:15:41.487 に答える