Python SQLAlchemy:UnicodeEncodeError:“ascii”编解码器无法编码字符(忽略db引擎编码?)

Python SQLAlchemy:UnicodeEncodeError:“ascii”编解码器无法编码字符(忽略db引擎编码?),python,sqlalchemy,Python,Sqlalchemy,我目前正在为一个新项目评估SQLAlchemy。当尝试执行包含非ascii字符的查询时,会引发异常 用于执行评估的SQL语句: SELECT owner, table_name FROM all_tables WHERE owner LIKE 'äöüßÄÖÜ'; 在SQL*Plus中执行此语句,SQL Developer将按预期在空列表中生成结果 为了连接到Oracle数据库,正在使用以下代码: from sqlalchemy import create_engine, MetaData,

我目前正在为一个新项目评估SQLAlchemy。当尝试执行包含非ascii字符的查询时,会引发异常

用于执行评估的SQL语句:

SELECT owner, table_name FROM all_tables  WHERE owner LIKE 'äöüßÄÖÜ';
在SQL*Plus中执行此语句,SQL Developer将按预期在空列表中生成结果

为了连接到Oracle数据库,正在使用以下代码:

from sqlalchemy import create_engine, MetaData, Table, inspect, select
import pandas as pd
import keyring

dbtype = 'Oracle'
dbenv = 'LOCAL'
dbname = 'MYDB'
dbsys = '%s%s' % (dbtype, dbenv)
dbusr = 'myusr'
dbpwd = keyring.get_password(dbsys, dbusr)
dbhost = 'mydbhost'
dbport = 1521
dbconstr = 'oracle+cx_oracle://%s:%s@%s:%s/%s' % (dbusr, dbpwd, dbhost, dbport, dbname)
要评估数据库引擎编码,请执行以下操作:

dbencs = ['UTF8', 'UTF-8', 'utf8', 'utf-8', 'latin1', 'ascii', None]

for dbenc in dbencs:
    if dbenc is None:
        engine = create_engine(dbconstr)
    else:
        engine = create_engine(dbconstr, encoding=dbenc)
    con = engine.connect()

    try:
        df = pd.read_sql_query(u'SELECT owner, table_name FROM all_tables  WHERE owner LIKE \'äöüßÄÖÜ\'', con)
        print('SUCCESS: sql query with db encoding %s succeeded!' % dbenc)
    except Exception as e:
        print('ERROR: sql query with db encoding %s failed (%s)' % (dbenc, e))

    con.close()
    engine.dispose()
无论创建db引擎时指定的编码是什么,执行查询的每次尝试都会引发异常

ERROR: sql query with db encoding UTF8 failed ('ascii' codec can't encode characters in position 60-66: ordinal not in range(128))
ERROR: sql query with db encoding UTF-8 failed ('ascii' codec can't encode characters in position 60-66: ordinal not in range(128))
ERROR: sql query with db encoding utf8 failed ('ascii' codec can't encode characters in position 60-66: ordinal not in range(128))
ERROR: sql query with db encoding utf-8 failed ('ascii' codec can't encode characters in position 60-66: ordinal not in range(128))
ERROR: sql query with db encoding latin1 failed ('ascii' codec can't encode characters in position 60-66: ordinal not in range(128))
ERROR: sql query with db encoding ascii failed ('ascii' codec can't encode characters in position 60-66: ordinal not in range(128))
ERROR: sql query with db encoding None failed ('ascii' codec can't encode characters in position 60-66: ordinal not in range(128))
使用cx_Oracle直接连接到数据库时,不使用SQLAlchemy

import cx_Oracle
import pandas as pd
import keyring

dbtype = 'Oracle'
dbenv = 'LOCAL'
dbname = 'MYDB'
dbsys = '%s%s' % (dbtype, dbenv)
dbusr = 'myusr'
dbpwd = keyring.get_password(dbsys, dbusr)
dbhost = 'mydbhost'
dbport = 1521
dbconstr = '%s:%s/%s' % (dbhost, dbport, dbname)

dbencs = ['UTF8', 'UTF-8', 'utf8', 'utf-8', 'latin1', 'ascii', None]

for dbenc in dbencs:
    print('=' * 70)
    print('db encoding: %s' % dbenc)
    print('-' * 30)

    if dbenc is None:
        connection = cx_Oracle.connect(dbusr, dbpwd, dbconstr)
    else:
        connection = cx_Oracle.connect(dbusr, dbpwd, dbconstr, encoding=dbenc)
    cursor = connection.cursor()

    try:
        r = cursor.execute("SELECT owner, table_name FROM all_tables  WHERE owner LIKE 'äöüßÄÖÜ'")
        recs = list()
        for owner, table_name in cursor:
            recs.append({'owner': owner, 'table': table_name})
        df = pd.DataFrame(recs)
        print('SUCCESS: sql query with db encoding %s succeeded!' % dbenc)
    except Exception as e:
        print('ERROR: sql query with db encoding %s failed (%s)' % (dbenc, e))

    cursor.close()
    connection.close()
一切正常

SUCCESS: sql query with db encoding UTF8 succeeded!
SUCCESS: sql query with db encoding UTF-8 succeeded!
SUCCESS: sql query with db encoding utf8 succeeded!
SUCCESS: sql query with db encoding utf-8 succeeded!
SUCCESS: sql query with db encoding latin1 succeeded!
ERROR: sql query with db encoding ascii failed ('ascii' codec can't encode characters in position 60-66: ordinal not in range(128))
ERROR: sql query with db encoding None failed ('ascii' codec can't encode characters in position 60-66: ordinal not in range(128))
为了让SQLAlchemy方法能够像cx_Oracle方法一样呈现相同的结果,我必须采取哪些不同的措施

我的环境包括

Ubuntu linux 16.04LTS; Python 3.8; SQLAlchemy 1.3.16; cx_Oracle 7.3.0; psycopg2 2.8.5; 本地Oracle 18c即时客户端; 远程oracle19c数据库; 本地PostgreSQL 9.5数据库。 编辑

编辑2

引擎对象配置

convert\u unicode=False cx\u oracle\u ver=7,3,0 驱动程序=cx\U oracle 编码=UTF8 编码。。。属性不可用
将编码参数添加到连接字符串确实做到了这一点

from sqlalchemy import create_engine, MetaData, Table, inspect, select
import pandas as pd
import keyring

dbtype = 'Oracle'
dbenv = 'LOCAL'
dbname = 'MYDB'
dbsys = '%s%s' % (dbtype, dbenv)
dbusr = 'myusr'
dbpwd = keyring.get_password(dbsys, dbusr)
dbhost = 'mydbhost'
dbport = 1521
dbconstr = 'oracle+cx_oracle://%s:%s@%s:%s/%s?encoding=utf-8&nencoding=utf-8' % (dbusr, dbpwd, dbhost, dbport, dbname)
这样修改代码后,它现在会按预期呈现结果

SUCCESS: sql query with db encoding UTF8 succeeded!
SUCCESS: sql query with db encoding UTF-8 succeeded!
SUCCESS: sql query with db encoding utf8 succeeded!
SUCCESS: sql query with db encoding utf-8 succeeded!
SUCCESS: sql query with db encoding latin1 succeeded!
ERROR: sql query with db encoding ascii failed ('ascii' codec can't encode characters in position 60-66: ordinal not in range(128))
ERROR: sql query with db encoding None failed ('ascii' codec can't encode characters in position 60-66: ordinal not in range(128))