1

我读了很多类似的问题,但没有一个清楚地回答我的问题。

我在EncryptedTypemysql 表列上使用 sqlalchemy-utils。
表创建和插入都可以,但是当我尝试进行查询时,接收:

Traceback (most recent call last):
  File "workspace/bin/test.py", line 127, in <module>
    result = session.query(Tester).all()
  File "workspace\ERP\venv\lib\site-packages\sqlalchemy\orm\query.py", line 3244, in all
    return list(self)
  File "workspace\venv\lib\site-packages\sqlalchemy\orm\loading.py", line 101, in instances
    cursor.close()
  File "workspace\venv\lib\site-packages\sqlalchemy\util\langhelpers.py", line 69, in __exit__
    exc_value, with_traceback=exc_tb,
  File "workspace\venv\lib\site-packages\sqlalchemy\util\compat.py", line 178, in raise_
    raise exception
  File "workspace\venv\lib\site-packages\sqlalchemy\orm\loading.py", line 81, in instances
    rows = [proc(row) for row in fetch]
  File "workspace\venv\lib\site-packages\sqlalchemy\orm\loading.py", line 81, in <listcomp>
    rows = [proc(row) for row in fetch]
  File "workspace\venv\lib\site-packages\sqlalchemy\orm\loading.py", line 642, in _instance
    populators,
  File "workspace\venv\lib\site-packages\sqlalchemy\orm\loading.py", line 779, in _populate_partial
    dict_[key] = getter(row)
  File "workspace\venv\lib\site-packages\sqlalchemy\engine\result.py", line 107, in __getitem__
    return processor(self._row[index])
  File "workspace\venv\lib\site-packages\sqlalchemy\sql\sqltypes.py", line 944, in process
    value = bytes(value)
TypeError: string argument without an encoding

我发现这个错误只在使用 python 3 时发生,而不是使用 python 2。
而且问题出在 sqlalchemy类型上,因为我在、和列bynary上遇到了同样的错误。 由于在 python3 中需要对字符串进行编码,我将第944 行的代码更改为并且 al 运行良好,所以我的问题是:BinaryVarbinaryBlob
bytessqlalchemy\sql\sqltypes.pyvalue = bytes(value, 'utf-8)

为什么我需要更改 sqlalchemy 代码?sqlalchemy 完全可以与 python3 一起使用吗?更改包的代码是否安全?

这是一个尝试的代码示例:

from sqlalchemy import MetaData, Integer, Column, Table, Binary, create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker, scoped_session

DB_CONFIG = {
        'user': 'user_test',
        'password': 'PSW_test',
        'host': '127.0.0.1',
        'database': 'db_test',
        }

if __name__ == '__main__':
    Base = declarative_base()
    engine = create_engine("mysql+mysqlconnector://%(user)s:%(password)s@%(host)s/%(database)s" % DB_CONFIG,
                           echo=False)
    Base.metadata.bind = engine
    db_sessionmaker = sessionmaker(bind=engine)
    Session = scoped_session(db_sessionmaker)

    # create the table
    meta = MetaData()
    tests = Table(
        'test', meta,
        Column('id', Integer, primary_key=True),
        Column('attr', Binary)
    )
    meta.create_all(engine)


    class Test(Base):
        __tablename__ = 'test'
        id = Column(Integer, primary_key=True)
        attr = Column(Binary)

    new_test = Test(attr='try'.encode('utf-8'))
    session = Session()
    session.add(new_test)
    session.commit()
    result = session.query(Test).all()
    for a in result:
        print(a, a.id, a.attr)
    Session.remove()
4

3 回答 3

1

感谢 Ilja Everilä 提供的提示,我找到了解决方案。也许不是最好的解决方案,但现在正在工作。

我认为根本原因是我的 DB-API在查询期间自动转换bytes为。str所以我只是通过向以下添加参数来禁用此行为create_engine

engine = create_engine("mysql+mysqlconnector://%(user)s:%(password)s@%(host)s/%(database)s" % DB_CONFIG, connect_args={'use_unicode': False})

结果是,如果您有一String列,它将在查询中返回,而bytes不是“str”,您必须手动对其进行解码。

当然有更好的解决方案。

于 2020-04-21T17:59:34.453 回答
1

MySQL 连接器似乎确实有任何问题。只需切换mysql-connector-pythonmysqlclient. 我有同样的问题,它帮助了我。

于 2020-05-06T12:57:58.280 回答
1

而不是mysql+mysqlconnector://<user>:<password>@<host>[:<port>]/<dbname>你会有mysql+mysqldb://<user>:<password>@<host>[:<port>]/<dbname>

SQLAchemy文档建议在 MySQL-Connector 上使用 mysqlclient(MySQL-Python 的分支)¶

MySQL Connector/Python DBAPI 自发布以来存在许多问题,其中一些可能仍未解决,并且 mysqlconnector 方言未作为 SQLAlchemy 持续集成的一部分进行测试。推荐的 MySQL 方言是 mysqlclient 和 PyMySQL。

于 2022-01-20T14:23:12.767 回答