在做dataframe 导入oracle db时报的错
'ascii' codec can't encode characters in position 0-3: ordinal not in range(128),
网上找了很多资料都无效,
代码中的df是我自己的dataframe数据
conn_string = 'oracle+cx_oracle://username:password@ip:port/dbname?charset=utf8'
engine = sqlalchemy.create_engine(conn_string, echo=False)
df.to_sql(table_name, con=engine.connect(), if_exists='append', index=False,
dtype={'id': sqlalchemy.types.NVARCHAR(length=255),
'ddc_id': sqlalchemy.types.Integer(),
'tbl_name': sqlalchemy.types.NVARCHAR(length=255),
'tbl_comment': sqlalchemy.types.NVARCHAR(length=255),
'owner': sqlalchemy.types.NVARCHAR(length=255)
}
)
to_sql的参数说明可查看官网http://pandas.pydata.org/pandas-docs/version/0.18.1/generated/pandas.DataFrame.to_sql.html
这里只说一下比较常用的几个:
1.table_name : 字符串类型,表名(大小写均可)
2.con:数据库连接池,用来封装数据库连接的信息,像java中有odbc-driver连接oracle,jdbc-driver连接mysql,
python中也提供了多种连接包,我用的时oracle,所以import cx-oracle包。另外,engine数据库连接对象可以使用sqlalchemy,当然如果是传统模式DBAPI2 的话只有sqlite3 可支持。记得要同步编码格式charset
3.if_exists:有三个可选项: ①None(如果表已存在,则不做任何事) ② append(如果表存在,则往表后添加数据,如果表中有索引约束、外键之类的 一定要注意传入数据是否可行,无法从to_sql来控制数据库的约束级别) ③ replace(见文思意,在插入数据前,drop该表,根据表名重新create,insert数据)
4.index: 指的是dataframe中的索引列(从0开始的唯一指代dataframe的行号),这里代表是否将该索引列当做数据库表中的column,一般都是False,具体还是以需求为准
5.dtype:指定dataframe的列类型,哪怕df中的某列是int类型,也可以强制转换成string类型,
问题来了,在.py文件头部加上
# -*- coding: utf-8 -*-
在数据库连接engine 中也加上了charset=utf8的编码格式(库编码、表编码都是utf8)
run 后还是报:
'ascii' codec can't encode characters in position 0-3: ordinal not in range(128)
看到这个错误就能知道是编码问题,但是一时不知哪里编码出错,仔细看了下 position0-3,对应的是我dataframe df中的tbl_comment列,而这一列的数据均是 中文,尝试将该列全部改为英文,正常入库,
但是,文件头部,数据库引擎,数据库编码格式都统一了,哪里还有问题呢?
对了,就是 NLS_LANG:系统的环境变量,关于NLS_LANG的介绍https://www.cnblogs.com/justuntil/p/5636574.html
可以通过两种办法让你的程序跑起来
方法1. 在函数的开始
import os
os.environ['NLS_LANG'] = 'AMERICAN_AMERICA.AL32UTF8' # 或者(CHINESE_CHINA.AL32UTF8)
中文utf8和美式英语utf8我都试过可以,
方法2. 在你的系统环境变量中增加NLS_LANG的配置,同样两种value均可,但是在你执行程序前要重启一下电脑。。。
最后:
这个编码问题同样也会在数据库中捞数据出现。解决方法一致