当前位置: 首页 > 知识库问答 >
问题:

使用Python请求和响应模拟下载文件

樊令秋
2023-03-14

我有一些python代码,它使用请求成功地从URL下载图像,并将其保存到/tmp/中。我想测试一下,它应该做什么。我使用响应来测试JSON文件的获取,但我不确定如何模拟获取文件的行为。

我假设这类似于嘲笑一个标准的响应,就像下面一样,但是我想我忽略了如何将body设置为文件...

@responses.activate
def test_download():
    responses.add(responses.GET, 'http://example.org/images/my_image.jpg',
              body='', status=200,
              content_type='image/jpeg')
    #...

更新:在Ashafix的评论之后,我正在尝试这个(python 3):

from io import BytesIO

@responses.activate
def test_download():
    with open('tests/images/tester.jpg', 'rb') as img1:
        imgIO = BytesIO(img1.read())

    responses.add(responses.GET, 'http://example.org/images/my_image.jpg',
              body=imgIO, status=200,
              content_type='image/jpeg')
    imgIO.seek(0)
    #...

但随后,当我正在测试的代码尝试执行我得到的请求时:

a bytes-like object is required, not '_io.BytesIO'

感觉几乎是对的,但我被难住了。

更新2:试图遵循史蒂夫·杰索普的建议:

@responses.activate
def test_download():
    with open('tests/images/tester.jpg', 'rb') as img1:
        responses.add(responses.GET, 'http://example.org/images/my_image.jpg',
                  body=img1.read(), status=200,
                  content_type='image/jpeg')
        #...

但是这次测试的代码提出了这个问题:

I/O operation on closed file.

当然,图像应该仍然在块中打开?

更新3:我正在测试的代码如下:

r = requests.get(url, stream=True)
if r.status_code == 200:
     with open('/tmp/temp.jpg', 'wb') as f:
        r.raw.decode_content = True
        shutil.copyfileobj(r.raw, f)

似乎最后的shutil行正在生成“对已关闭文件的I/O操作”错误我对文件的流式传输理解不够,不知道如何最好地模拟这种行为,测试下载的文件是否保存到/tmp/


共有2个答案

郎诚
2023-03-14

首先,总结一下我现在过于冗长的问题...我在测试一些代码,类似于:

def download_file(url):
    r = requests.get(url, stream=True)
    if r.status_code == 200:
         filename = os.path.basename(url)
         with open('/tmp/%s' % filename, 'wb') as f:
            r.raw.decode_content = True
            shutil.copyfileobj(r.raw, f)
         return filename

它下载一个图像,并将其流式传输,保存到/tmp/。我想嘲笑这个请求,这样我就可以测试其他东西。

@responses.activate
def test_downloads_file(self):
    url = 'http://example.org/test.jpg'
    with open('tests/images/tester.jpg', 'rb') as img:
        responses.add(responses.GET, url,
                        body=img.read(), status=200,
                        content_type='image/jpg',
                        adding_headers={'Transfer-Encoding': 'chunked'})
        filename = download_file(url)
        # assert things here.

一旦我找到了为此使用open()的方法,我仍然可以从shutil.copyfileobj()获得I/O操作。停止这一点的是添加Transver-Encode标头,当我发出真正的请求时,它会出现在标头中。

欢迎对其他更好的解决方案提出任何建议!

穆俊名
2023-03-14

您可能需要将stream=True传递给响应。添加呼叫。比如:

@responses.activate
def test_download():
    with open("tests/images/tester.jpg", "rb") as img1:
        responses.add(
            responses.GET,
            "http://example.org/images/my_image.jpg",
            body=img1.read(),
            status=200,
            content_type="image/jpeg",
            stream=True,
        )
 类似资料:
  • 在我的views.py中,我有一个函数,它每次使用不同的响应来调用各种requests.get() 在我的测试类中,我想做这样的事情,但无法计算出确切的方法调用 步骤1: 验证响应包含“a response”、“b response”、“c response” 如何完成步骤1(模拟请求模块)?

  • 问题内容: 我正在尝试从网站下载PDF文件并将其保存到磁盘。我的尝试因编码错误而失败,或者导致PDF空白。 我知道这是某种编解码器问题,但我似乎无法使其正常工作。 问题答案: 在这种情况下,您应该使用: 从文件: 对于非文本请求,您还可以字节形式访问响应主体: 因此,这意味着:将输出作为字符串对象返回,在下载 文本文件 时使用它。如HTML文件等 并以字节对象返回输出,在下载 二进制文件 时使用它

  • 问题内容: 这是我的代码: 这使我可以访问csv文件。我尝试了其他方法来处理下载: 这将给csv文件一个字符串: 这将打印第一行并返回错误:_csv.Error:在未引用的字段中看到换行符 这将在每行中打印一个字母,并且不会打印出整个内容: 我的问题是:在这种情况下读取CSV文件的最有效方法是什么。以及如何下载。 谢谢 问题答案: 这应该有助于: 输出样本: 答案相关的问题: 使用此功能将csv加

  • 问题内容: 请求是一个非常不错的库。我想用它来下载大文件。问题是不可能将整个文件保留在内存中,我需要分块读取它。这是以下代码的问题 由于某种原因,它无法按这种方式工作。仍将响应加载到内存中,然后再将其保存到文件中。 更新 如果你需要一个小型客户端,可以从FTP下载大文件,则可以在此处找到它。它支持多线程和重新连接(它确实监视连接),还可以为下载任务调整套接字参数。 问题答案: 使用以下流代码,无论

  • 问题内容: 我想在单击按钮时发送“ ajax下载请求”,所以我尝试了这种方式: javascript: download.php: 但是没有按预期工作,我该怎么办?先感谢您 问题答案: 2015年4月27日更新 进入HTML5场景的是download属性。它支持在Firefox和Chrome,并很快来到IE11。根据您的需求,只要您要下载的文件与您的网站位于同一来源,就可以使用它代替AJAX请求(

  • 问题内容: 我正在做一个项目,其中我的解析器 窃取了 有关特定站点上每个视频的数据,并将其保存到我的数据库中。除了指向隐藏视频的完整链接之外,我已完成所有工作。 有一个播放器,它会自动从页面加载开始。我发现启动播放器的JavaScript代码: 通话后,因此,如果没有错误发现它开始使用播放器 的文件名 从 响应 。那就是我所需要的。 我重新检查了 Live HTTP标头中 的呼叫: 因此它使用特定