Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/apache-spark/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何限制python3请求中的下载速度?_Python_Python Requests_Bandwidth Throttling - Fatal编程技术网

如何限制python3请求中的下载速度?

如何限制python3请求中的下载速度?,python,python-requests,bandwidth-throttling,Python,Python Requests,Bandwidth Throttling,我使用请求在运行Linux的小型嵌入式设备上下载一个大的~50MiB文件 将文件写入附加的MMC 不幸的是,MMC的写入速度低于网络速度,我看到内存消耗增加,在一些情况下,我甚至让内核无法处理页面。。。错误 该设备只有128MiB RAM 我使用的代码是: 对于requests.getURL,stream=True为r: 如果r.status_代码!=200: log.errorf'???下载返回{r.status_code}' 返回-偏移量+r.状态\ U代码 大小=0 使用opensfn,“

我使用请求在运行Linux的小型嵌入式设备上下载一个大的~50MiB文件

将文件写入附加的MMC

不幸的是,MMC的写入速度低于网络速度,我看到内存消耗增加,在一些情况下,我甚至让内核无法处理页面。。。错误

该设备只有128MiB RAM

我使用的代码是:

对于requests.getURL,stream=True为r: 如果r.status_代码!=200: log.errorf'???下载返回{r.status_code}' 返回-偏移量+r.状态\ U代码 大小=0 使用opensfn,“wb”作为fo: 对于r.iter\u contentchunk\u size=4096中的块: fo.writechunk siz+=lenchunk 返回大小 如何在写入MMC时临时停止服务器

                if r.status_code != 200:
                    log.error(f'??? download returned {r.status_code}')
                    return -(offset + r.status_code)
                siz = 0
                with open(sfn, 'wb') as fo:
                    for chunk in r.iter_content(chunk_size=4096):
                        fo.write(chunk)
                        siz += len(chunk)
                return siz
您可以将其重写为协同程序

import requests

def producer(URL,temp_data,n):
    with requests.get(URL,  stream=True) as r:
        if r.status_code != 200:
            log.error(f'??? download returned {r.status_code}')
            return -(offset + r.status_code)
        for chunk in r.iter_content(chunk_size=n):
            temp_data.append(chunk)
            yield #waiting to finish the consumer
            

def consumer(temp_data,fname):
    with open(fname, 'wb') as fo:
        while True:
            while len(temp_data) > 0:
                for data in temp_data:
                    fo.write(data)
                    temp_data.remove(data) # To remove it from the list
                    # You can add sleep here
                    yield #waiting for more data


def coordinator(URL,fname,n=4096):
    temp_data = list()
    c = consumer(temp_data,fname)
    p = producer(URL,temp_data,n)
    while True:
        try:
            #getting data
            next(p)
        except StopIteration:
            break
        finally:
            #writing data
            next(c)
这些都是您需要的功能。 称之为

URL = "URL"
fname = 'filename'
coordinator(URL,fname)
您可以将其重写为协同程序

import requests

def producer(URL,temp_data,n):
    with requests.get(URL,  stream=True) as r:
        if r.status_code != 200:
            log.error(f'??? download returned {r.status_code}')
            return -(offset + r.status_code)
        for chunk in r.iter_content(chunk_size=n):
            temp_data.append(chunk)
            yield #waiting to finish the consumer
            

def consumer(temp_data,fname):
    with open(fname, 'wb') as fo:
        while True:
            while len(temp_data) > 0:
                for data in temp_data:
                    fo.write(data)
                    temp_data.remove(data) # To remove it from the list
                    # You can add sleep here
                    yield #waiting for more data


def coordinator(URL,fname,n=4096):
    temp_data = list()
    c = consumer(temp_data,fname)
    p = producer(URL,temp_data,n)
    while True:
        try:
            #getting data
            next(p)
        except StopIteration:
            break
        finally:
            #writing data
            next(c)
这些都是您需要的功能。 称之为

URL = "URL"
fname = 'filename'
coordinator(URL,fname)

如果web服务器支持,则可以请求仅下载大文件的一部分,然后逐部分浏览整个文件

请看,James Mills给出了以下示例代码:

from requests import get

url = "http://download.thinkbroadband.com/5MB.zip"
headers = {"Range": "bytes=0-100"}  # first 100 bytes

r = get(url, headers=headers)

由于您的问题是内存,您可能希望停止服务器立即向您发送整个文件,因为这肯定会被设备上的某些代码缓冲。除非您可以让请求删除它接收的部分数据,否则这将始终是一个问题。请求下游的附加缓冲区将不会有帮助。

如果web服务器支持,您可以请求仅下载大文件的一部分,然后逐部分浏览整个文件

请看,James Mills给出了以下示例代码:

from requests import get

url = "http://download.thinkbroadband.com/5MB.zip"
headers = {"Range": "bytes=0-100"}  # first 100 bytes

r = get(url, headers=headers)

由于您的问题是内存,您可能希望停止服务器立即向您发送整个文件,因为这肯定会被设备上的某些代码缓冲。除非您可以让请求删除它接收的部分数据,否则这将始终是一个问题。请求下游的附加缓冲区将没有帮助。

您可以尝试使用此bash命令减小TCP接收缓冲区的大小:

echo 'net.core.rmem_max=1000000' >> /etc/sysctl.conf
1MB,你可以调整这个

这就避免了在流程的这个阶段出现巨大的缓冲区积累

然后编写代码,使其仅从TCP堆栈读取,并以指定的间隔写入MMC,以防止缓冲区在系统中的其他位置累积,例如MMC写入缓冲区-例如@e3n的答案


希望这会导致数据包被丢弃,然后在缓冲区再次打开时由服务器重新发送。

您可以尝试使用此bash命令减小TCP接收缓冲区的大小:

echo 'net.core.rmem_max=1000000' >> /etc/sysctl.conf
1MB,你可以调整这个

这就避免了在流程的这个阶段出现巨大的缓冲区积累

然后编写代码,使其仅从TCP堆栈读取,并以指定的间隔写入MMC,以防止缓冲区在系统中的其他位置累积,例如MMC写入缓冲区-例如@e3n的答案


希望这会导致数据包被丢弃,然后在缓冲区再次打开时由服务器重新发送。

这是否回答了您的问题@python_user:除非我遗漏了什么,否则那里的代码与我已经在使用的代码是等价的。我的问题是磁盘写入部分比从网络获取慢。显然,在这种情况下,请求或下面的东西会不断分配内存来缓冲尚未处理的传入数据。我需要一种减缓来源的方法,例如:延迟发送帧确认也相关:这是否回答了您的问题@python_user:除非我遗漏了什么,否则那里的代码与我已经在使用的代码是等价的。我的问题是磁盘写入部分比从网络获取慢。显然,在这种情况下,请求或下面的东西会不断分配内存来缓冲尚未处理的传入数据。我需要一种方法来减缓来源,例如:延迟发送帧确认也相关:谢谢。我肯定会尝试这个方法,但我不明白它将如何减慢这个过程。我的写操作已经太慢了,怎么能让它们更慢呢?显然,请求不会等待我轮询r.iter_内容来填充它。我需要在请求代码中插入一个睡眠调用,如果我没弄错的话。是的,你可以在调用nextobj for循环之前添加睡眠调用。请稍等片刻,我正在重新写作it@ZioByte它现在完成了,你可以使用它了。它也可以解决你的记忆问题,因为它正在一块一块地写one@e3n但是如果你睡觉,操作系统会不会只是在内存中的某个地方缓冲接收到的数据包,从而保持内存问题?@Anonymous1847我在文件处理方面没有太多经验。但是在这里,我们产生块并手动使用它,所以我认为不应该有任何与内存相关的问题。睡眠是一种选择

纳尔。我不推荐,但也许@Ziobyte设备速度慢,所以他可能需要它。我肯定会尝试这个方法,但我不明白它将如何减慢这个过程。我的写操作已经太慢了,怎么能让它们更慢呢?显然,请求不会等待我轮询r.iter_内容来填充它。我需要在请求代码中插入一个睡眠调用,如果我没弄错的话。是的,你可以在调用nextobj for循环之前添加睡眠调用。请稍等片刻,我正在重新写作it@ZioByte它现在完成了,你可以使用它了。它也可以解决你的记忆问题,因为它正在一块一块地写one@e3n但是如果你睡觉,操作系统会不会只是在内存中的某个地方缓冲接收到的数据包,从而保持内存问题?@Anonymous1847我在文件处理方面没有太多经验。但是在这里,我们产生块并手动使用它,所以我认为不应该有任何与内存相关的问题。睡眠是可选的。我不推荐使用它,但可能@Ziobyte设备速度慢,所以他可能需要它。请尝试我的升级,但我的服务器既不支持范围,也不支持重新启动:这很不幸。如果你只想把文件下载到磁盘上,可以考虑不要使用请求,但是可以通过OS.Stor或子进程等调用CURL之类的外部工具。CURL支持带宽限制,参见很好的尝试我投票,但是我的服务器既不支持范围也不支持重新启动:这是不幸的。如果你只想把文件下载到磁盘上,可以考虑不要使用请求,但是可以通过OS.Stor或子进程等调用CURL等外部工具。有趣的是,我当前的值no/etc/sysctl.confat非常低:net.core.rmem_max=180224。我想在基本TCP之上,在我的应用程序级别之下,有什么东西在做缓冲。@ZioByte可能是python库在缓冲什么东西。也许有减少缓冲区大小的选项?或者你可以尝试另一个图书馆。嗯。。。有趣的是,我当前的值no/etc/sysctl.confat非常低:net.core.rmem_max=180224。我想在基本TCP之上,在我的应用程序级别之下,有什么东西在做缓冲。@ZioByte可能是python库在缓冲什么东西。也许有减少缓冲区大小的选项?或者你可以尝试另一个图书馆。