我需要计算从CDN服务器下载的镜像的哈希值.使用同步库时,一切都运行得很好.我直接将请求的结果(Res)传递给Image.open(),并接收一个带有图像作为输出的对象(Img).

import requests
import imagehash
from PIL import Image

# sync
def get_picture():
    url = 'https://ae01.alicdn.com/kf/Sec174725eb944b4693342178da975d52z.jpg'
    res = requests.get(url, stream=True).raw
    img = Image.open(res)
    hash = imagehash.phash(img, hash_size=6)
    print(f'hash: {hash}')

但是我需要判断很多照片,并且需要异步执行请求,在这里我遇到了一个问题,因为我不能直接将带有图像的请求对象传输到Image.Open(),只有首先将其保存到文件,但这个选项不适合我(我不需要服务器上的文件).

import imagehash
from PIL import Image
from aiohttp import ClientSession
from config.settings import BASE_DIR

# async
async def get_aio_picture():
    url = 'https://ae01.alicdn.com/kf/Sec174725eb944b4693342178da975d52z.jpg'
    async with ClientSession() as session:
        async with session.get(url=url) as response:
            response.auto_decompress = False
            with open('picture.jpg', 'wb') as fd:
                async for line in response.content:
                    fd.write(line)
            img = Image.open(f'{BASE_DIR}/picture.jpg')
            hash = imagehash.phash(img, hash_size=6)
            print(f'hash: {hash}')


async def main():
    task = asyncio.create_task(get_aio_picture())
    await task


def aio_hash():
    asyncio.run(main())

如果我以直接将结果传递给Image.open()的方式更改函数代码:

async def get_aio_picture():
    url = 'https://ae01.alicdn.com/kf/Sec174725eb944b4693342178da975d52z.jpg'
    async with ClientSession() as session:
        async with session.get(url=url) as response:
            response.auto_decompress = False
            async for line in response.content:
                img = Image.open(line)
                hash = imagehash.phash(img, hash_size=6)
                print(f'hash: {hash}')

然后我得到错误:(

...
File "/home/.../main/services/aio/help.py", line 37, in get_aio_picture
    img = Image.open(line)
File "/home/.../env/lib/python3.10/site-packages/PIL/Image.py", line 3247, in open
    fp = builtins.open(filename, "rb")
ValueError: embedded null byte

如何更改代码以避免在磁盘上创建文件? 帮帮我!

推荐答案

您可以使用函数response.read()并使用io.BytesIO将结果存储在字节变量缓冲区中.从该缓冲区生成哈希.

import asyncio
import imagehash
from PIL import Image
from aiohttp import ClientSession
import io

# async
async def get_aio_picture():
    url = 'https://ae01.alicdn.com/kf/Sec174725eb944b4693342178da975d52z.jpg'
    async with ClientSession() as session:
        async with session.get(url=url) as response:
            response.auto_decompress = False
            buffer = io.BytesIO(await response.read())
            img = Image.open(buffer)
            hash = imagehash.phash(img, hash_size=6)
            print(f'hash: {hash}')
                
async def main():
    task = asyncio.create_task(get_aio_picture())
    await task


def aio_hash():
    asyncio.run(main())

aio_hash()

输出:

hash: fbc843946

Python相关问答推荐

Python会扔掉未使用的表情吗?

使用FASTCGI在IIS上运行Django频道

如何让剧作家等待Python中出现特定cookie(然后返回它)?

处理(潜在)不断增长的任务队列的并行/并行方法

当从Docker的--env-file参数读取Python中的环境变量时,每个\n都会添加一个\'.如何没有额外的?

Python解析整数格式说明符的规则?

使用Python从URL下载Excel文件

如何防止Pandas将索引标为周期?

OpenGL仅渲染第二个三角形,第一个三角形不可见

Cython无法识别Numpy类型

Python pint将1/华氏度转换为1/摄氏度°°

从源代码显示不同的输出(机器学习)(Python)

Django Table—如果项目是唯一的,则单行

使用SQLAlchemy从多线程Python应用程序在postgr中插入多行的最佳方法是什么?'

在任何要保留的字段中添加引号的文件,就像在Pandas 中一样

在一个数据帧中,我如何才能发现每个行号是否出现在一列列表中?

如何关联来自两个Pandas DataFrame列的列表项?

利用广播使减法更有效率

基于2级列表的Pandas 切片3级多索引

如何在微调Whisper模型时更改数据集?