为什么python打印延迟?

时间:2015-05-05 15:16:49

标签: python python-3.x web-crawler python-requests

我正在尝试使用请求下载文件,并且每次检索100k大小的文件时都打印一个点,但所有点都打印在最后。见代码。

with open(file_name,'wb') as file:
    print("begin downloading, please wait...")
    respond_file = requests.get(file_url,stream=True)
    size = len(respond_file.content)//1000000

    #the next line will not be printed until file is downloaded
    print("the file size is "+ str(size) +"MB")
    for chunk in respond_file.iter_content(102400):
        file.write(chunk)
        #print('',end='.')
        sys.stdout.write('.')
        sys.stdout.flush()
    print("")

3 个答案:

答案 0 :(得分:4)

您正在此处访问request.content

size = len(respond_file.content)//1000000

访问该属性会强制下载整个响应,对于大型响应,这需要一些时间。请改用int(respond_file.headers['content-length'])

size = int(respond_file.headers['content-length']) // 1000000

Content-Length标题由服务器提供,因为它是标题的一部分,您可以访问该信息,而无需先下载所有内容。

如果服务器选择使用Transfer-Encoding: chunked来传输响应,则不必设置Content-Length标头;你可能需要考虑到这一点:

content_length = respond_file.headers.get('content-length', None)
size_in_kb = '{}KB'.format(int(content_length) // 1024) if content_length else 'Unknown'
print("the file size is", size_in_kb)

其中以千字节为单位的大小是通过将长度除以1024而非100万来计算的。

或者,在单独的HEAD请求中询问大小(仅获取标题):

head_response = requests.get(file_url)
size = int(head_response.headers.get('content-length', 0))

答案 1 :(得分:2)

这应该与您的期望相符。得到respond_file的长度不是你想要的。而是检查内容长度标题。

注意:我更改了代码以显示KB(用于测试目的)。

import requests
import sys

file_url = "https://github.com/kennethreitz/requests/archive/master.zip"
file_name = "out.zip"

with open(file_name,'wb') as file:
    print("begin downloading, please wait...")
    respond_file = requests.get(file_url,stream=True)
    size = int(respond_file.headers['content-length'])//1024

    #the next line will not be printed until file is downloaded
    print("the file size is "+ str(size) +"KB")
    for chunk in respond_file.iter_content(1024):
        file.write(chunk)
        #print('',end='.')
        sys.stdout.write('.')
        sys.stdout.flush()
    print("")

答案 2 :(得分:0)

正如@kevin在评论中所写,respond.file.content会阻止执行,直到整个内容被下载。我的答案与他的评论之间的唯一区别是我不猜测;)