设为首页 收藏本站
查看: 567|回复: 0

[经验分享] 对于python mysqldb 的一个简单的封装

[复制链接]

尚未签到

发表于 2015-4-27 06:26:54 | 显示全部楼层 |阅读模式
  
  这是对mysqldb的一个简单封装,隐藏了cursor ,在小型的项目中可以使用,比较轻量,好定制,我再用scrapy爬取网页的时候就是使用这个 mysql 类的
  




  1 #!/usr/bin/env python
  2 #
  3 # Copyright 2009 Facebook
  4 #
  5 # Licensed under the Apache License, Version 2.0 (the "License"); you may
  6 # not use this file except in compliance with the License. You may obtain
  7 # a copy of the License at
  8 #
  9 #     http://www.apache.org/licenses/LICENSE-2.0
10 #
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14 # License for the specific language governing permissions and limitations
15 # under the License.
16
17 """A lightweight wrapper around MySQLdb."""
18
19 import copy
20 import MySQLdb.constants
21 import MySQLdb.converters
22 import MySQLdb.cursors
23 import itertools
24 import logging
25 import time
26
27 class Connection(object):
28     """A lightweight wrapper around MySQLdb DB-API connections.
29
30     The main value we provide is wrapping rows in a dict/object so that
31     columns can be accessed by name. Typical usage::
32
33         db = database.Connection("localhost", "mydatabase")
34         for article in db.query("SELECT * FROM articles"):
35             print article.title
36
37     Cursors are hidden by the implementation, but other than that, the methods
38     are very similar to the DB-API.
39
40     We explicitly set the timezone to UTC and the character encoding to
41     UTF-8 on all connections to avoid time zone and encoding errors.
42     """
43     def __init__(self, host, database, user=None, password=None,
44                  max_idle_time=7*3600):
45         self.host = host
46         self.database = database
47         self.max_idle_time = max_idle_time
48
49         args = dict(conv=CONVERSIONS, use_unicode=True, charset="utf8",
50                     db=database, init_command='SET time_zone = "+8:00"',
51                     sql_mode="TRADITIONAL")
52         if user is not None:
53             args["user"] = user
54         if password is not None:
55             args["passwd"] = password
56
57         # We accept a path to a MySQL socket file or a host(:port) string
58         if "/" in host:
59             args["unix_socket"] = host
60         else:
61             self.socket = None
62             pair = host.split(":")
63             if len(pair) == 2:
64                 args["host"] = pair[0]
65                 args["port"] = int(pair[1])
66             else:
67                 args["host"] = host
68                 args["port"] = 3306
69
70         self._db = None
71         self._db_args = args
72         self._last_use_time = time.time()
73         try:
74             self.reconnect()
75         except Exception:
76             logging.error("Cannot connect to MySQL on %s", self.host,
77                           exc_info=True)
78
79     def __del__(self):
80         self.close()
81
82     def close(self):
83         """Closes this database connection."""
84         if getattr(self, "_db", None) is not None:
85             self._db.close()
86             self._db = None
87
88     def reconnect(self):
89         """Closes the existing database connection and re-opens it."""
90         self.close()
91         try:
92            from DBUtils import PooledDB
93
94            pool_con = PooledDB.PooledDB(creator=MySQLdb, mincached=1, maxcached=10, maxshared=10,
95     maxconnections=20, blocking=False, maxusage=100, **self._db_args)
96            self._db = pool_con.connection()
97            self._db.cursor().connection.autocommit(True)
98         except:
99            self._db = MySQLdb.connect(**self._db_args)
100            self._db.autocommit(True)
101
102     def iter(self, query, *parameters):
103         """Returns an iterator for the given query and parameters."""
104         self._ensure_connected()
105         cursor = MySQLdb.cursors.SSCursor(self._db)
106         try:
107             self._execute(cursor, query, parameters)
108             column_names = [d[0] for d in cursor.description]
109             for row in cursor:
110                 yield Row(zip(column_names, row))
111         finally:
112             cursor.close()
113
114     def query(self, query, *parameters):
115         """Returns a row list for the given query and parameters."""
116         cursor = self._cursor()
117         try:
118             self._execute(cursor, query, parameters)
119             column_names = [d[0] for d in cursor.description]
120             return [Row(itertools.izip(column_names, row)) for row in cursor]
121         finally:
122             cursor.close()
123
124     def get(self, query, *parameters):
125         """Returns the first row returned for the given query."""
126         rows = self.query(query, *parameters)
127         if not rows:
128             return None
129         elif len(rows) > 1:
130             raise Exception("Multiple rows returned for Database.get() query")
131         else:
132             return rows[0]
133
134     # rowcount is a more reasonable default return value than lastrowid,
135     # but for historical compatibility execute() must return lastrowid.
136     def execute(self, query, *parameters):
137         """Executes the given query, returning the lastrowid from the query."""
138         return self.execute_lastrowid(query, *parameters)
139
140     def execute_lastrowid(self, query, *parameters):
141         """Executes the given query, returning the lastrowid from the query."""
142         cursor = self._cursor()
143
144         try:
145             self._execute(cursor, query, parameters)
146             return cursor.lastrowid
147         finally:
148             cursor.close()
149
150     def execute_rowcount(self, query, *parameters):
151         """Executes the given query, returning the rowcount from the query."""
152         cursor = self._cursor()
153         try:
154             self._execute(cursor, query, parameters)
155             return cursor.rowcount
156         finally:
157             cursor.close()
158
159     def executemany(self, query, parameters):
160         """Executes the given query against all the given param sequences.
161
162         We return the lastrowid from the query.
163         """
164         return self.executemany_lastrowid(query, parameters)
165
166     def executemany_lastrowid(self, query, parameters):
167         """Executes the given query against all the given param sequences.
168
169         We return the lastrowid from the query.
170         """
171         cursor = self._cursor()
172         try:
173             cursor.executemany(query, parameters)
174             return cursor.lastrowid
175         finally:
176             cursor.close()
177
178     def executemany_rowcount(self, query, parameters):
179         """Executes the given query against all the given param sequences.
180
181         We return the rowcount from the query.
182         """
183         cursor = self._cursor()
184         try:
185             cursor.executemany(query, parameters)
186             return cursor.rowcount
187         finally:
188             cursor.close()
189
190     def _ensure_connected(self):
191         # Mysql by default closes client connections that are idle for
192         # 8 hours, but the client library does not report this fact until
193         # you try to perform a query and it fails.  Protect against this
194         # case by preemptively closing and reopening the connection
195         # if it has been idle for too long (7 hours by default).
196         if (self._db is None or
197             (time.time() - self._last_use_time > self.max_idle_time)):
198             self.reconnect()
199         self._last_use_time = time.time()
200
201     def _cursor(self):
202         self._ensure_connected()
203         return self._db.cursor()
204
205     def _execute(self, cursor, query, parameters):
206         try:
207             return cursor.execute(query, parameters)
208         except OperationalError:
209             logging.error("Error connecting to MySQL on %s", self.host)
210             self.close()
211             raise
212         finally:
213             cursor.close()
214
215
216 class Row(dict):
217     """A dict that allows for object-like property access syntax."""
218     def __getattr__(self, name):
219         try:
220             return self[name]
221         except KeyError:
222             raise AttributeError(name)
223
224
225 # Fix the access conversions to properly recognize unicode/binary
226 FIELD_TYPE = MySQLdb.constants.FIELD_TYPE
227 FLAG = MySQLdb.constants.FLAG
228 CONVERSIONS = copy.copy(MySQLdb.converters.conversions)
229
230 field_types = [FIELD_TYPE.BLOB, FIELD_TYPE.STRING, FIELD_TYPE.VAR_STRING]
231 if 'VARCHAR' in vars(FIELD_TYPE):
232     field_types.append(FIELD_TYPE.VARCHAR)
233
234 for field_type in field_types:
235     CONVERSIONS[field_type] = [(FLAG.BINARY, str)] + CONVERSIONS[field_type]
236
237
238 # Alias some common MySQL exceptions
239 IntegrityError = MySQLdb.IntegrityError
240 OperationalError = MySQLdb.OperationalError
  使用的时候可以像下面这样



def db():
return database.Connection(host=MYSQL_HOST, database=MYSQL_DB, user=MYSQL_USER, password=MYSQL_PASSWORD)
db = db()
  这样就可以直接调用查询了
  插入数据的时候使用



db.execute("insert into `picdownload` (`hash`) values(%s)",hash)
  返回受影响的行数,
  查询的时候使用:



db.query("select `id` from `picdownload` where hash = %s",pichash)
  
  返回一个列表,其中包含 查询结果的一个字典集
  
  
  

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-60897-1-1.html 上篇帖子: 编译原理----词法分析程序----python语言版 下篇帖子: Python for .net脚本调用dotnet框架(ref和out参数问题)
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表