Python连接MySQL并使用fetchall()方法过滤特殊字符


Posted in Python onMarch 13, 2016

来一个简单的例子,看Python如何操作数据库,相比Java的JDBC来说,确实非常简单,省去了很多复杂的重复工作,只关心数据的获取与操作。
准备工作
需要有相应的环境和模块:

  • Ubuntu 14.04 64bit
  • Python 2.7.6
  • MySQLdb

注意:Ubuntu 自带安装了Python,但是要使用Python连接数据库,还需要安装MySQLdb模块,安装方法也很简单:

sudo apt-get install MySQLdb

然后进入Python环境,import这个包,如果没有报错,则安装成功了:

python
Python 2.7.6 (default, Jun 22 2015, 17:58:13) 
[GCC 4.8.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import MySQLdb
>>>

Python标准的数据库接口的Python DB-API(包括Python操作MySQL)。大多数Python数据库接口坚持这个标准。不同的数据库也就需要不同额模块,由于我本机装的是MySQL,所以使用了MySQLdb模块,对不同的数据库而言,只需要更改底层实现了接口的模块,代码不需要改,这就是模块的作用。
Python数据库操作
首先我们需要一个测试表
建表语句:

CREATE DATABASE study;
use study;
DROP TABLE IF EXISTS python_demo;
CREATE TABLE python_demo (
 id int NOT NULL AUTO_INCREMENT COMMENT '主键,自增',
 user_no int NOT NULL COMMENT '用户编号',
 user_name VARBINARY(50) NOT NULL COMMENT '用户名',
 password VARBINARY(50) NOT NULL COMMENT '用户密码',
 remark VARBINARY(255) NOT NULL COMMENT '用户备注',
 PRIMARY KEY (id,user_no)
)ENGINE =innodb DEFAULT CHARSET = utf8 COMMENT '用户测试表';

INSERT INTO python_demo(user_no, user_name, password, remark) VALUES
 (1001,'张三01','admin','我是张三');
INSERT INTO python_demo(user_no, user_name, password, remark) VALUES
 (1002,'张三02','admin','我是张三');
INSERT INTO python_demo(user_no, user_name, password, remark) VALUES
 (1003,'张三03','admin','我是张三');
INSERT INTO python_demo(user_no, user_name, password, remark) VALUES
 (1004,'张三04','admin','我是张三');
INSERT INTO python_demo(user_no, user_name, password, remark) VALUES
 (1005,'张三05','admin','我是张三');
INSERT INTO python_demo(user_no, user_name, password, remark) VALUES
 (1006,'张三06','admin','我是张三');
INSERT INTO python_demo(user_no, user_name, password, remark) VALUES
 (1007,'张三07','admin','我是张三');
INSERT INTO python_demo(user_no, user_name, password, remark) VALUES
 (1008,'张三08','admin','我是张三');

Python代码

# --coding=utf8--
import ConfigParser

import sys
import MySQLdb

def init_db():
  try:
    conn = MySQLdb.connect(host=conf.get('Database', 'host'),
                user=conf.get('Database', 'user'),
                passwd=conf.get('Database', 'passwd'),
                db=conf.get('Database', 'db'),
                charset='utf8')
    return conn
  except:
    print "Error:数据库连接错误"
    return None

def select_demo(conn, sql):
  try:
    cursor = conn.cursor()
    cursor.execute(sql)
    return cursor.fetchall()
  except:
    print "Error:数据库连接错误"
    return None

def update_demo():
  pass

def delete_demo():
  pass

def insert_demo():
  pass

if __name__ == '__main__':
  conf = ConfigParser.ConfigParser()
  conf.read('mysql.conf')
  conn = init_db()
  sql = "select * from %s" % conf.get('Database', 'table')
  data = select_demo(conn, sql)
  pass

fetchall()字段特殊字符过滤处理
最近在做数据仓库的迁移工作,之前数据仓库的数据都是用的shell脚本来抽取,后来换了python脚本.
但是在把数据抽取存放到hadoop时,出现了一个问题:
由于数据库字段很多,提前也不知道数据库字段会存储什么内容,hive建表是以\t\n做分隔,这就导致了一个问题,如果mysql字段内容里面本身含有\t\n,那么就会出现字段错位情况,并且很头疼的是mysql有100多个字段,也不知道哪个字段会出现这个问题.
shell脚本里的做法是在需要抽取的字段上用mysql的replace函数对字段进行替换,例如,假设mysql里的字段是column1 varchar(2000),那么很可能就会出现有特殊字符的情况,在查询的sql语句里加上

select replace(replace(replace(column1,'\r',''),'\n',''),'\t','')

之前一直是这么干的,但是这样写sql特别长,特别是有100多个字段,也不知道哪个有特殊字符,只要都加上.
所以在python中对字段不加处理,最终导致hive表字段对应出现偏差,所以在python里从mysql查询到的字段在写到文件之前需要对每个字段进行过滤处理
看个例子,我就以mysql测试为例,首先建一张测试表

CREATE TABLE `filter_fields` (
 `field1` varchar(50) DEFAULT NULL,
 `field2` varchar(50) DEFAULT NULL,
 `field3` varchar(50) DEFAULT NULL,
 `field4` varchar(50) DEFAULT NULL,
 `field5` varchar(50) DEFAULT NULL,
 `field6` varchar(50) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

有六个字段,都是varchar类型,插入新数据可以在里面插入特殊字符.简单插入条数据测试看看:

insert into filter_fields(field1,field2,field3,field4,field5,field6) VALUES
('test01','test02','test03','test04','test05','test06');
insert into filter_fields(field1,field2,field3,field4,field5,field6) VALUES
('test11\ntest11','test12\n\n','test13','test14','test15','test16');
insert into filter_fields(field1,field2,field3,field4,field5,field6) VALUES
('test21\ttest21','test22\ttest22\ttest22','test23\t\t\t','test4','test5','test6');
insert into filter_fields(field1,field2,field3,field4,field5,field6) VALUES
('test21\rest21','test22\r\rest22\r\rest22','test23\r\r\r','test4','test5','test6');

其中数据里插入的特殊字符,可能连在一起,也有不连在一起的.
python测试代码:

# coding=utf-8

import MySQLdb
import sys

db_host = '127.0.0.1'  # 数据库地址
db_port = 3306     # 数据库端口
db_user = 'root'    # mysql用户名
db_pwd = 'yourpassword' # mysql用户密码,换成你的密码
db_name = 'test'    # 数据库名
db_table = 'filter_fields' # 数据库表

# 过滤sql字段结果中的\t\n
def extract_data(table_name):
  try:
    conn = MySQLdb.connect(host=db_host, port = db_port, user=db_user,
                passwd = db_pwd, db = db_name, charset = "utf8")
    cursor = conn.cursor()
  except MySQLdb.Error, e:
    print '数据库连接异常'
    sys.exit(1)

  try:
    sql = 'select * from %s;'%(table_name)
    cursor.execute(sql)
    rows = cursor.fetchall()

    print '====字段未过滤查询结果===='
    for row in rows:
      print row

    print '====字段过滤之后结果===='
    rows_list = []
    for row in rows:
      row_list = []
      for column in row:
        row_list.append(column.replace('\t', '').replace('\n', '').replace('\r', ''))
      rows_list.append(row_list)
      print rows_list[-1] # [-1]表示列表最后一个元素
    return rows_list
  except MySQLdb.Error, e:
    print '执行sql语句失败'
    cursor.close()
    conn.close()
    sys.exit(1)

if __name__ == '__main__':
  print 'begin:'
  rows = extract_data(db_table)
  pass

看看输出结果:

字段未过滤查询结果

(u'test01', u'test02', u'test03', u'test04', u'test05', u'test06')
(u'test11\ntest11', u'test12\n\n', u'test13', u'test14', u'test15', u'test16')
(u'test21\ttest21', u'test22\ttest22\ttest22', u'test23\t\t\t', u'test4', u'test5', u'test6')
(u'test21\rest21', u'test22\r\rest22\r\rest22', u'test23\r\r\r', u'test4', u'test5', u'test6')

字段过滤之后结果

[u'test01', u'test02', u'test03', u'test04', u'test05', u'test06']
[u'test11test11', u'test12', u'test13', u'test14', u'test15', u'test16']
[u'test21test21', u'test22test22test22', u'test23', u'test4', u'test5', u'test6']
[u'test21est21', u'test22est22est22', u'test23', u'test4', u'test5', u'test6']

可以看到,制表符,换行符,回车都被过滤了.
建议:最后说点题外话,不要小视\r,回车符.很多人以为回车符就是换行符,其实不是的,\r表示回车符,\n表示新行.之前代码里其实是过滤掉了\t\n的,但是抽取的数据还是不对,后来看了源码之后才发现,原来是没有过滤\r,就这个不同导致了很多数据抽取不对.

Python 相关文章推荐
python实现class对象转换成json/字典的方法
Mar 11 Python
Python探索之实现一个简单的HTTP服务器
Oct 28 Python
pandas带有重复索引操作方法
Jun 08 Python
把csv文件转化为数组及数组的切片方法
Jul 04 Python
详解Python3中ceil()函数用法
Feb 19 Python
Python面向对象程序设计之类的定义与继承简单示例
Mar 18 Python
python gensim使用word2vec词向量处理中文语料的方法
Jul 05 Python
python打印9宫格、25宫格等奇数格 满足横竖斜相加和相等
Jul 19 Python
python爬虫之爬取百度音乐的实现方法
Aug 24 Python
Python3内置函数chr和ord实现进制转换
Jun 05 Python
详解pyinstaller生成exe的闪退问题解决方案
Jun 19 Python
Python建造者模式案例运行原理解析
Jun 29 Python
深入讲解Python函数中参数的使用及默认参数的陷阱
Mar 13 #Python
编写Python小程序来统计测试脚本的关键字
Mar 12 #Python
使用Python内置的模块与函数进行不同进制的数的转换
Mar 12 #Python
Python语言的面相对象编程方式初步学习
Mar 12 #Python
举例讲解Python中的list列表数据结构用法
Mar 12 #Python
Python中的if、else、elif语句用法简明讲解
Mar 11 #Python
使用Python读写文本文件及编写简单的文本编辑器
Mar 11 #Python
You might like
星际中一些鲜为人知的详细资料
2020/03/04 星际争霸
PHP使用正则表达式实现过滤非法字符串功能示例
2018/06/04 PHP
用JavaScript页面不刷新时全选择,全删除(GridView)
2009/04/14 Javascript
jQuery each()方法的使用方法
2010/03/18 Javascript
javascript 函数参数限制说明
2010/11/19 Javascript
基于jquery的3d效果实现代码
2011/03/23 Javascript
js与jquery中获取当前鼠标的x、y坐标位置的代码
2011/05/23 Javascript
js中将URL中的参数提取出来作为对象的实现代码
2011/08/16 Javascript
让图片旋转任意角度及JQuery插件使用介绍
2013/03/20 Javascript
javascript实现表格增删改操作实例详解
2015/05/15 Javascript
在Node.js中使用HTTP上传文件的方法
2015/06/23 Javascript
JavaScript中利用jQuery绑定事件的几种方式小结
2016/03/06 Javascript
js+flash实现的5图变换效果广告代码(附演示与demo源码下载)
2016/04/01 Javascript
easyUI实现类似搜索框关键词自动提示功能示例代码
2016/12/27 Javascript
移动端Ionic App 资讯上下循环滚动的实现代码(跑马灯效果)
2017/08/29 Javascript
JavaScript html5 canvas实现图片上画超链接
2017/10/20 Javascript
jQuery实现点击自身以外区域关闭弹出层功能完整示例【改进版】
2018/07/31 jQuery
Vue源码探究之虚拟节点的实现
2019/04/17 Javascript
Vue初始化中的选项合并之initInternalComponent详解
2020/06/11 Javascript
js实现盒子移动动画效果
2020/08/09 Javascript
精确查找PHP WEBSHELL木马的方法(1)
2011/04/12 Python
python使用urllib模块和pyquery实现阿里巴巴排名查询
2014/01/16 Python
使用Python判断质数(素数)的简单方法讲解
2016/05/05 Python
解决PySide+Python子线程更新UI线程的问题
2019/01/11 Python
python开发准备工作之配置虚拟环境(非常重要)
2019/02/11 Python
详解Python Matplotlib解决绘图X轴值不按数组排序问题
2019/08/05 Python
Flask框架学习笔记之路由和反向路由详解【图文与实例】
2019/08/12 Python
从零开始的TensorFlow+VScode开发环境搭建的步骤(图文)
2020/08/31 Python
html5版canvas自由拼图实例
2014/10/15 HTML / CSS
什么是数据抽象
2016/11/26 面试题
小学生春游活动方案
2014/08/20 职场文书
餐厅保洁员岗位职责
2015/04/10 职场文书
求职信:会计求职的写作技巧
2019/04/24 职场文书
2019年国庆祝福语(70句)
2019/09/19 职场文书
WINDOWS下安装mysql 8.x 的方法图文教程
2022/04/19 MySQL
Nginx的gzip相关介绍
2022/05/11 Servers