Progress of Python requests post

后端 未结 5 936
我在风中等你
我在风中等你 2020-12-13 05:29

I am uploading a large file using the Python requests package, and I can\'t find any way to give data back about the progress of the upload. I have seen a number of progress

5条回答
  •  刺人心
    刺人心 (楼主)
    2020-12-13 06:19

    Usually you would build a streaming datasource (a generator) that reads the file chunked and reports its progress on the way (see kennethreitz/requests#663. This does not work with requests file-api, because requests doesn’t support streaming uploads (see kennethreitz/requests#295) – a file to upload needs to be complete in memory before it starts getting processed.

    but requests can stream content from a generator as J.F. Sebastian has proven before, but this generator needs to generate the complete datastream including the multipart encoding and boundaries. This is where poster comes to play.

    poster is originally written to be used with pythons urllib2 and supports streaming generation of multipart requests, providing progress indication as it goes along. Posters Homepage provides examples of using it together with urllib2 but you really don’t want to use urllib2. Check out this example-code on how to to HTTP Basic Authentication with urllib2. Horrrrrrrrible.

    So we really want to use poster together with requests to do file uploads with tracked progress. And here is how:

    # load requests-module, a streamlined http-client lib
    import requests
    
    # load posters encode-function
    from poster.encode import multipart_encode
    
    
    
    # an adapter which makes the multipart-generator issued by poster accessable to requests
    # based upon code from http://stackoverflow.com/a/13911048/1659732
    class IterableToFileAdapter(object):
        def __init__(self, iterable):
            self.iterator = iter(iterable)
            self.length = iterable.total
    
        def read(self, size=-1):
            return next(self.iterator, b'')
    
        def __len__(self):
            return self.length
    
    # define a helper function simulating the interface of posters multipart_encode()-function
    # but wrapping its generator with the file-like adapter
    def multipart_encode_for_requests(params, boundary=None, cb=None):
        datagen, headers = multipart_encode(params, boundary, cb)
        return IterableToFileAdapter(datagen), headers
    
    
    
    # this is your progress callback
    def progress(param, current, total):
        if not param:
            return
    
        # check out http://tcd.netinf.eu/doc/classnilib_1_1encode_1_1MultipartParam.html
        # for a complete list of the properties param provides to you
        print "{0} ({1}) - {2:d}/{3:d} - {4:.2f}%".format(param.name, param.filename, current, total, float(current)/float(total)*100)
    
    # generate headers and gata-generator an a requests-compatible format
    # and provide our progress-callback
    datagen, headers = multipart_encode_for_requests({
        "input_file": open('recordings/really-large.mp4', "rb"),
        "another_input_file": open('recordings/even-larger.mp4', "rb"),
    
        "field": "value",
        "another_field": "another_value",
    }, cb=progress)
    
    # use the requests-lib to issue a post-request with out data attached
    r = requests.post(
        'https://httpbin.org/post',
        auth=('user', 'password'),
        data=datagen,
        headers=headers
    )
    
    # show response-code and -body
    print r, r.text
    

提交回复
热议问题