gpt4 book ai didi

python - PIL─Python Imaging Library─通过CherryPy将图像缩略图上传到SQLAlchemy数据库

转载 作者:太空宇宙 更新时间:2023-11-04 06:12:18 25 4
gpt4 key购买 nike

# ! /usr/bin/env python
# -*- coding: utf-8 -*-
# image_upload.py

""" Python 2.7.3
Cherrypy 3.2.2
PostgreSQL 9.1
psycopy2 2.4.5
SQLAlchemy 0.7.10
PIL 1.1.7
"""


我正在尝试从客户端的本地文件将图像及其缩略图保存在SQLAlchemy数据库中。通过HTML表单将数据上传到CherryPy服务器。然后,使用Python Imaging Library(PIL)处理图像以获取缩略图。最后,应将结果保存在SQLAlchemy数据库中,该数据库可能由于缩略图而失败。

注意:我尝试执行此操作而不将缩略图临时保存在文件中。由于数据已经在RAM中可用,因此我不喜欢将其保存在文件夹中,然后将其添加到数据库中,最后从文件夹中删除它的想法。只是做这种事情是不对的。

EDIT 4结尾的解决方案

关于ObjectImage类的表,
我必须为此使用它!
这是必需的!与Python 2.7一样

column       type            attributes
----------------------------------------
id int PRIMARY KEY
object_id int REFERENCES Obeject(id) ON DELETE CASCADE
filename varchar(252)
image bytea
thumbnail bytea
preview boolean


以下是到PostgreSQL数据库的SQLAlchemy连接。
它作为“ session”存储在CherryPy会话中,并作为s1检索。
只是没有人将s1混淆为CherryPy对象。

pg = sqlalchemy.create_engine(
'postgresql://{}:{}@{}:{}/{}'.format(
user, password, server, port, data))
Session = sessionmaker(bind=pg)
cherrypy.session['session'] = Session


极简Python代码:

""" 
The variable "image_file"
comes directly from the POSTed dictionary.
image_file = kwargs['image_file']
"""

s1 = cherrypy.session.get('session')
image_entry = {}

img = StringIO.StringIO(image_file.file.read())
image = Image.open(img)
image_entry['image'] = image.copy()

thumb = image.copy()
thumb.thumbnail((30000, 300,), Image.ANTIALIAS)
image_entry['thumbnail'] = thumb.copy()

image_entry['object_id'] = chosen_one
image_entry['filename'] = image_file.filename
image_entry['preview'] = 't'

s1.add(ObjecteImage(**image_entry))
s1.commit() #line 1621


CherryPy追溯:

  File "image_upload.py", line 1621, in store_image
s1.commit()
File "/usr/local/lib/python2.7/dist-packages/SQLAlchemy-0.7.10-py2.7-linux-x86_64.egg/sqlalchemy/orm/session.py", line 710, in commit
self.transaction.commit()
File "/usr/local/lib/python2.7/dist-packages/SQLAlchemy-0.7.10-py2.7-linux-x86_64.egg/sqlalchemy/orm/session.py", line 368, in commit
self._prepare_impl()
File "/usr/local/lib/python2.7/dist-packages/SQLAlchemy-0.7.10-py2.7-linux-x86_64.egg/sqlalchemy/orm/session.py", line 347, in _prepare_impl
self.session.flush()
File "/usr/local/lib/python2.7/dist-packages/SQLAlchemy-0.7.10-py2.7-linux-x86_64.egg/sqlalchemy/orm/session.py", line 1734, in flush
self._flush(objects)
File "/usr/local/lib/python2.7/dist-packages/SQLAlchemy-0.7.10-py2.7-linux-x86_64.egg/sqlalchemy/orm/session.py", line 1805, in _flush
flush_context.execute()
File "/usr/local/lib/python2.7/dist-packages/SQLAlchemy-0.7.10-py2.7-linux-x86_64.egg/sqlalchemy/orm/unitofwork.py", line 331, in execute
rec.execute(self)
File "/usr/local/lib/python2.7/dist-packages/SQLAlchemy-0.7.10-py2.7-linux-x86_64.egg/sqlalchemy/orm/unitofwork.py", line 475, in execute
uow
File "/usr/local/lib/python2.7/dist-packages/SQLAlchemy-0.7.10-py2.7-linux-x86_64.egg/sqlalchemy/orm/persistence.py", line 64, in save_obj
table, insert)
File "/usr/local/lib/python2.7/dist-packages/SQLAlchemy-0.7.10-py2.7-linux-x86_64.egg/sqlalchemy/orm/persistence.py", line 558, in _emit_insert_statements
execute(statement, params)
File "/usr/local/lib/python2.7/dist-packages/SQLAlchemy-0.7.10-py2.7-linux-x86_64.egg/sqlalchemy/engine/base.py", line 1449, in execute
params)
File "/usr/local/lib/python2.7/dist-packages/SQLAlchemy-0.7.10-py2.7-linux-x86_64.egg/sqlalchemy/engine/base.py", line 1584, in _execute_clauseelement
compiled_sql, distilled_params
File "/usr/local/lib/python2.7/dist-packages/SQLAlchemy-0.7.10-py2.7-linux-x86_64.egg/sqlalchemy/engine/base.py", line 1691, in _execute_context
context)
File "/usr/local/lib/python2.7/dist-packages/SQLAlchemy-0.7.10-py2.7-linux-x86_64.egg/sqlalchemy/engine/default.py", line 331, in do_execute
cursor.execute(statement, parameters)
TypeError: can't escape instance to binary


在第二次尝试中,我尝试至少直接插入最初上传的文件,以检查是否有任何更改。

极简Python代码:

s1 = cherrypy.session.get('session')
image_entry = {}

img = StringIO.StringIO(image_file.file.read())
image = Image.open(img)
image_entry['image'] = image_file

[ ... the same as above ... ]

s1.add(ObjecteImage(**image_entry))
s1.commit() #line 1621


CherryPy追溯:

  File "image_upload.py", line 1621, in store_image
s1.commit()
File "/usr/local/lib/python2.7/dist-packages/SQLAlchemy-0.7.10-py2.7-linux-x86_64.egg/sqlalchemy/orm/session.py", line 710, in commit
self.transaction.commit()

[ ... the same as above ... ]

File "/usr/local/lib/python2.7/dist-packages/SQLAlchemy-0.7.10-py2.7-linux-x86_64.egg/sqlalchemy/engine/default.py", line 331, in do_execute
cursor.execute(statement, parameters)
TypeError: can't escape Part to binary


如何将PIL映像中的实例或PIL映像中的None实例转换为二进制文件?
或者也许是缓冲区,字节数组……我什至不知道我真正需要什么。

字节数组强制转换导致:

  File "image_upload.py", line 1611, in store_image
image_entry['thumbnail'] = bytearray(thumb.copy())
TypeError: iteration over non-sequence


缓冲区强制转换导致:

  File "image_upload.py", line 1611, in store_image
image_entry['thumbnail'] = buffer(thumb.copy())
TypeError: buffer object expected


在这里找不到答案:
- Python Imaging Library Handbookformer link
- CherryPy File Handling

也许有更好的工具/库吗?
仅创建缩略图的一个?

编辑1:

我对如何将Image对象保存到流中进行了一些研究。
但是首先我尝试了PIL.Image.tostring()函数:

thumb = image.copy()
thumb.thumbnail((30000, 300,), Image.ANTIALIAS)
thumb.tostring()
image_entry['thumbnail'] = thumb.copy()


然后,我尝试了BytesIO()模块。
它导致了UnsupportedOperation:fileno PIL
由于这是PIL中的一个已知错误,因此我用其Pillow叉替换了PIL,然后再次尝试:

thumb = image.copy()
thumb.thumbnail((30000, 300,), Image.ANTIALIAS)
stream = BytesIO()
thumb.save(stream, "JPEG")
image_entry['thumbnail'] = stream.getvalue()


都让我遇到了SQLAlchemy TypeError:无法将实例转义为二进制文件
当然,就像错误追溯到之前一样:

s1.add(ObjectImage(**image_entry))
s1.commit() #line 1621


最后,我用StringIO.StringIO()替换了BytesIO(),但是并没有改变任何事情。
我猜这更多是一个特殊的SQLAlchemy问题。

编辑2:

在我错误地提到未知的SQLAlchemy TypeError之前:无法将Part转换为二进制
在EDIT 1中进行了更正,它是SQLAlchemy TypeError:无法将实例转义为二进制
发生这种情况仅是因为尝试过将POSTed值保存在数据库中:

""" 
The variable "image_file"
comes directly from the POSTed dictionary.
image_file = kwargs['image_file']

Alternative first line:
img = StringIO.StringIO(image_file.file.read())
"""

img = BytesIO(image_file.file.read())
image = Image.open(img)
image_entry['image'] = image_file # the dict value was meant be image.copy()

s1.add(ObjectImage(**image_entry))
s1.commit() #line 1621


编辑3:

看来我犯了个错误,仍然尝试插入完整尺寸的图片作为实例,
而缩略图已经以正确的方式“格式化”。

"""
old version:
"""

img = BytesIO(image_file.file.read())
image = Image.open(img)
image_entry['image'] = image.copy()


"""
new version:
"""

img = BytesIO(image_file.file.read())
image = Image.open(img)

fullsize = image.copy()
stream = BytesIO()
fullsize.save(stream, "JPEG")
image_entry['image'] = stream.getvalue()


"""
from EDIT 1:
"""

thumb = image.copy()
thumb.thumbnail((30000, 300,), Image.ANTIALIAS)
stream = BytesIO()
thumb.save(stream, "JPEG")
image_entry['thumbnail'] = stream.getvalue()


现在至少有一个很长的十六进制代码插入到表中,也许我可以使用它。
但是,图像和缩略图列似乎包含相同的十六进制代码。

编辑4:

图像和缩略图不包含相同的十六进制代码,如稍后确认的SQL查询所示。
只有前1179个字符和后4个字符是相同的,而我刚开始检查过。
两者之间的内容不同,每个条目的长度也不同。
最后,将整个代码片段作为一个。

首先必要的进口:

from io import BytesIO
import base64
import cherrypy
import sqlalchemy
from sqlalchemy.orm import sessionmaker
from PIL import Image


第二个引擎和会话:

pg = sqlalchemy.create_engine(
'postgresql://{}:{}@{}:{}/{}'.format(
user, password, server, port, data))
Session = sessionmaker(bind=pg)
cherrypy.session['session'] = Session


第三张图片和缩略图上传代码:

s1 = cherrypy.session.get('session')
image_file = kwargs['image_file']

img = BytesIO(image_file.file.read())
image = Image.open(img)

fullsize = image.copy()
stream = BytesIO()
fullsize.save(stream, "JPEG")
image_entry['image'] = stream.getvalue()

thumb = image.copy()
thumb.thumbnail((30000, 300,), Image.ANTIALIAS)
stream = BytesIO()
thumb.save(stream, "JPEG")
image_entry['thumbnail'] = stream.getvalue()

image_entry['sample'] = chosen_one
image_entry['filename'] = image_file.filename
image_entry['preview'] = 't'

s1.add(ObjectImage(**image_entry))
s1.commit() #line 1621


最后是HTML的简短缩略图检索代码:

s1 = cherrypy.session.get('session')
qry = (s1.query(ObjectImage.id, ObjectImage.filename, ObjectImage.thumbnail).
filter(ObjectImage.preview == 't'))

for rowX in qry:
yield (u'<img src="data:image/jpeg; base64, {}" alt="thumbnail">'.
format(base64.b64encode(rowX.thumbnail)))


出于性能原因,我考虑编写一个额外的函数来替换数据URI方案。
但是现在,感谢NeaţuOvidiu Gabriel提到了“保存到流”选项,
感谢提供这些资源的人们:

- Python variables and files(简单的io.BytesIO()示例)
- python Image PIL to binary Hex(提及UnsupportedOperation:fileno)

最佳答案

我不知道Cherrypy,但我的猜测是您要向s1发送一个PIL.Image对象作为参数,而s1无法执行它必须做的事情,因为他无法识别这种对象。

关于python - PIL─Python Imaging Library─通过CherryPy将图像缩略图上传到SQLAlchemy数据库,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18022926/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com