0.

http://mysql-python.sourceforge.net/

  • Python and MySQL: This is a presentation I did a couple years ago for the 2005 MySQL User Conference. It was a 45-minute talk, so don't expect a lot of detail.

1.https://web.archive.org/web/20070104043701/http://dustman.net/andy/python/python-and-mysql

Andy Dustman
<adustman@terry.uga.edu>
Terry College of Business
http://www.terry.uga.edu/
University of Georgia
http://www.uga.edu/

Python for the PyCurious

  • interpreted (byte-code compiler)
  • interactive (easy to test ideas)
  • object-oriented (everything's an object)
  • rapid development (5-10x C++, Java)
  • fits your brain [Bruce Eckel]
  • fits your wallet: free (OSI and GPL)
  • fun!
Introductory Material on Python:
http://www.python.org/doc/Intros.html

Types

  Mutable Immutable
Sequence list tuple
str, unicode
Number   int, long, float
Mapping dict  
Other object  
The basic Python types and their mutability

Basic type examples

>>> i=1 # an int
>>> j=2**64-1 # a long integer
>>> print j
18446744073709551615
>>> f=3.14 # float (C double)
>>> c=1-1j # complex (1j is imaginary)
>>> print c
(1-1j)
>>> s="welcome to python!"
>>> s.capitalize().split() # returns a list
['Welcome', 'to', 'python!']
>>> [ word.capitalize() for word in s.split() ]
['Welcome', 'To', 'Python!']
>>> a, b = 1, 2
>>> print (a,b) # a tuple
(1, 2)
>>> a, b = b, a
>>> print (a,b)
(2, 1)

Strings

>>> "Normal string literal isn't very interesting."
"Normal string literal isn't very interesting."
>>> 'Single quotes work "same as double".'
'Single quotes work "same as double".'
>>> """Triple-quoted strings are good for long strings
... which span multiple lines."""
'Triple-quoted strings are good for long strings\nwhich span multiple lines.'
>>> r"Raw strings are useful for regexs, i.e. \w+ or \1"
'Raw strings are useful for regexs, i.e. \\w+ or \\1'
>>> u"Unicode strings work just like regular strings."
u'Unicode strings work just like regular strings.'
>>> u"\u72c2\n\u7009".encode('utf-8')
'\xe7\x8b\x82\n\xe7\x80\x89'
>>> print u"\u72c2\n\u7009".encode('utf-8')

Strings

Lots of string methods and operators:

>>> "Split words into a list.".split()
['Split', 'words', 'into', 'a', 'list.']
>>> ' '.join(['Join', 'a', 'list', 'of', 'strings'])
'Join a list of strings'
>>> "Concatenate" + " " + "strings"
'Concatenate strings'
>>> "Multiplicity! " * 3
'Multiplicity! Multiplicity! Multiplicity! '
>>> "Parameter %s" % "substitution"
'Parameter substitution'
>>> d = dict(first_name="Vee", last_name="McMillen",
... company="O'Reilly")
>>> "Hello, %(first_name)s. How are things at %(company)s?" % d
"Hello, Vee. How are things at O'Reilly?"

Dictionaries

Python dictionaries are like perl hashes:

>>> d1={}
>>> d1['a']=1
>>> d1['b']=2
>>> d1['c']=3
>>> d1
{'a': 1, 'c': 3, 'b': 2}
>>> d2={'a': 1, 'c': 3, 'b': 2}
>>> d3=dict([('a',1),('b',2),('c',3)])
>>> d4=dict(a=1, b=2, c=3)
>>> d1 == d2 == d3 == d4
True
>>> len(d1)
3

Values can be any type, but keys must be immutable.

Sequences

>>> l = ['a','b','c','d','e']
>>> print l[0]
a
>>> print l[-1]
e
>>> print l[2:4]
['c', 'd']
>>> s='abcde'
>>> print s[2:4]
cd
>>> print s[::2]
ace
>>> print s[::-1]
edcba
>>> l.append(s)
>>> print l
['a', 'b', 'c', 'd', 'e', 'abcde']

Iterators

  • iter(object) returns an iterator object
  • iterobj.next() returns the next object
  • StopIteration is raised when there are no more objects
    >>> # no normal person would do this
    >>> l = [1, 2, 3]
    >>> i = iter(l)
    >>> i.next()
    1
    >>> i.next()
    2
    >>> i.next()
    3
    >>> i.next()
    Traceback (most recent call last):
    File "", line 1, in ?
    StopIteration

Common iterator usage

>>> l = [1, 2, 3]
>>> for item in l:
... print item
...
1
2
3
>>> d = dict(a=1, b=2, c=3)
>>> for key in d:
... print key, d[key]
...
a 1
c 3
b 2

Exceptions

f = open("myfile", 'r')
try:
try:
for line in f:
try:
process(line)
except TypeError:
line = mangle(line)
try:
process(line)
except TypeError:
raise FoobarError, line
except IOError, message:
print "Error reading:", message
except FoobarError:
print "This file is totally munged."
except:
print "Something inexplicable happened:"
raise # re-raise original exception
finally:
f.close()

Odds and ends

  • Code blocks are delimited by indentation

    • You probably do this already
    • Space or tabs, your call; just be consistent
    • No need for curly braces
    • Less cluttered, easier to read
  • End-of-line is a statement separator (so is ;)
  • No type enforcement
    • Argument types are not checked
    • Function return types are not checked
    • Type checking makes your code less flexible
    • If you still want it, you can add it cleanly with decorators
  • Operator overloading for user-defined classes
  • Everything is a reference (pass by reference)
  • None object for null/missing values (equivalent to NULL)

Odds and ends

  • Member access with . operator

    • instance.method()
    • instance.attribute
    • instance.attribute.another
  • Functions/methods are not the only things that are callable
  • Decorators apply a callable to a function at creation time:
    @g
    def f(x):
    ...

    is equivalent to:

    def f(x):
    ...
    f = g(f)

The Python DB-API

  • Standard API for database access
  • PEP 249: http://www.python.org/peps/pep-0249.html
  • By convention, module name ends with "db", i.e. MySQLdb
    • Module Interface
    • Connection Objects
    • Cursor Objects
    • DBI Helper Objects
    • Type Objects and Constructors
    • Implementation Hints
    • Major Changes from 1.0 to 2.0

Module Interface

connect(...)
Constructor for creating a connection to the database. Returns a Connection Object.
apilevel
String constant stating the supported DB API level.
threadsafety
Integer constant stating the level of thread safety the interface supports.

SQL parameter placeholders

paramstyleString constant stating the type of parameter marker formatting expected by the interface.

'qmark'
Question mark style, e.g. '...WHERE name=?'
'numeric'
Numeric, positional style, e.g. '...WHERE name=:1'
'named'
Named style, e.g. '...WHERE name=:name'
'format'
ANSI C printf format codes, e.g. '...WHERE name=%s'
'pyformat'
Python extended format codes, e.g. '...WHERE name=%(name)s'

MySQLdb 1.0 and 1.2 uses format and pyformat; 2.0 may also support qmark.

Exceptions

  • StandardError

    • Warning
    • Error
      • InterfaceError
      • DatabaseError
      • DataError
      • OperationalError
      • IntegrityError
      • InternalError
      • ProgrammingError
      • NotSupportedError

Connection Object

.close()
Close the connection now
.commit()
Commit any pending transaction to the database. Auto-commit off by default.
.rollback()
Rollback any pending transaction.
.cursor()
Return a new Cursor Object using the connection.
exceptions
The standard exception classes; simplfies error handling in some cases
.messages
list of error/warning messages since last method call

Cursor Object

.description
A sequence of sequences, each of which describe a column of the result.
.rowcount
Number of rows affected by last query.
.callproc(procname[,parameters])
Call a stored database procedure with the given name.
.close()
Close the cursor now.
.execute(operation[,parameters])
Prepare and execute a database operation (query or command). Parameters: sequence or mapping.
.executemany(operation,seq_of_parameters)
Prepare a database operation (query or command) and then execute it against a sequence of parameters.

Cursor Object

.fetchone()
Fetch the next row of the result set as a sequence, or None if there are no more rows.
.fetchmany([size=cursor.arraysize])
Fetch a sequence of up to size rows; may be fewer. Zero length sequence indicates end of result set.
.fetchall()
Fetch all remaining rows as a sequence of rows.
.nextset()
Skip to the next result set. Returns a true value if there is another result set; None (false) if not.
.arraysize
Default number of rows to return with cursor.fetchmany(). Default: 1.

Cursor Object

.rownumber
Current index into result set
.connection
The Connection object for this cursor
.scroll(value[,mode='relative'])
Scroll to a new position in the result set (relative or absolute).
.messages
List containing warning/error messages since last method call (except the .fetchXXX() methods).
.next()
Fetches one row (like fetchone()) or raises StopIteration if no rows left. Iterator protocol
.lastrowid
Row id of the last affected row (i.e. inserting AUTO_INCREMENT columns)

MySQL for Python

  • MySQL-python project on SourceForge: http://sourceforge.net/projects/mysql-python
  • Current best version: 1.2.0
    • Python-2.3 and newer (and maybe 2.2)
    • MySQL-3.23, 4.0, and 4.1 (and maybe 5.0)
    • Prepared statements not supported yet
  • Older version: 1.0.1
    • Python-1.5.2 (very old) and newer
    • MySQL-3.22, 3.23, and 4.0 (not 4.1 or newer)
    • Don't use if you can use 1.2.0
  • Vaporware version: 2.0
    • Python-2.4 and newer
    • MySQL-4.0, 4.1, and 5.0
    • Prepared statements will be supported
    • Return all text columns as unicode by default

Architecture

_mysql

  • C extension module
  • transliteration of MySQL C API into Python objects
  • If you use the C API, this should be very familiar
  • Deprecated API calls not implemented
  • Not everything (particularly fields) is exposed
  • SQL column type to Python type conversions handled by a dictionary

MySQLdb

  • Adapts _mysql to DB-API
  • Many non-standard C API calls are exposed
  • Relatively light-weight wrapper
  • Implements cursors
  • Defines default type mappings; easily customizable

Opening a connection

connect() takes the same options as mysql_real_connect(), and then some.

import MySQLdb

# These are all equivalent, for the most part
db = MySQLdb.connect("myhost", "myuser", "mysecret", "mydb")
db = MySQLdb.connect(host="myhost", user="myuser",
passwd="mysecret", db="mydb")
auth = dict(user="myuser", passwd="mysecret")
db = MySQLdb.connect("myhost", db="mydb", **auth)
db = MySQLdb.connect(read_default_file="/etc/mysql/myapp.cnf")
  • compress=1 enables gzip compression
  • use_unicode=1 returns text-like columns as unicode objects
  • ssl=dict(...) negotiates SSL/TLS

Simple query example

import MySQLdb

db = MySQLdb.connect(read_default_file="/etc/mysql/myapp.cnf")
c = db.cursor()
c.execute("""SELECT * FROM users WHERE userid=%s""", ('monty',))
print c.fetchone()

Notes

  • ('monty',) is a 1-tuple; comma required to distinquish from algebraic grouping
  • Good reasons not to use *
    • How many columns are being returned?
    • What is the order of the columns?
  • Good reasons to use *
    • Table/database browser
    • Lazy

Multi-row query example

c = db.cursor()
c.execute("""SELECT userid, first_name, last_name, company
FROM users WHERE status=%s and expire>%s""",
(status, today))
users = c.fetchall()

Notes

  • We know what the columns are
  • Could use some object abstraction

A simple User class

class User(object):

    """A simple User class"""

    def __init__(self, userid,
first_name=None, last_name=None,
company=None):
self.userid = userid
self.first_name = first_name
self.last_name = last_name
self.company = company def announce(self):
"""Announce User to the world."""
name = "%s %s" % (self.first_name, self.last_name)
if self.company:
return "%s of %s" % (name, self.company)
else:
return name def __str__(self):
return self.announce()

Multi-row query with User object

users = []
c = db.cursor()
c.execute("""SELECT userid, first_name, last_name, company
FROM users WHERE status=%s and expire>%s""",
(status, today)) for userid, first_name, last_name, company in c.fetchall():
u = User(userid, first_name, last_name, company)
print u
users.append(u)

might produce output like:

Tim O'Reilly of O'Reilly Media, Inc.
Monty Widenius of MySQL AB
Carleton Fiorina
Guido van Rossum of Elemental Security

Cursors are iterators

Not necessary to use c.fetchall()

users = []
c = db.cursor()
c.execute("""SELECT userid, first_name, last_name, company
FROM users WHERE status=%s and expire>%s""",
(status, today)) for userid, first_name, last_name, company in c:
u = User(userid, first_name, last_name, company)
print u
users.append(u)

Under certain conditions, this is more efficient than fetchall(), and no worse.

Dictionaries as parameters

Python classes typically store attributes in __dict__, so you can get away with this:

u = User(...)
c = db.cursor()
c.execute("""INSERT INTO users
(userid, first_name, last_name, company)
VALUES (%(userid)s, %(first_name)s,
%(last_name)s, %(company)s)""", u.__dict__)
db.commit()

Multi-row INSERT

# users is a list of (userid, first_name, last_name, company)
c = db.cursor()
c.executemany("""INSERT INTO users
(userid, first_name, last_name, company)
VALUES (%s, %s, %s, %s)""", users)
db.commit()

In MySQLdb, this is converted internally to a multi-row INSERT, which is reported to be 2-3 orders of magnitude faster. Also works for REPLACE.

Multi-row INSERT with dictionaries

# users is a list of Users
c = db.cursor()
c.executemany("""INSERT INTO users
(userid, first_name, last_name, company)
VALUES (%(userid)s, %(first_name)s,
%(last_names, %(company)s)""",
[ u.__dict__ for u in users ])
db.commit()

This builds the parameter list with a list comprehension.

Never do this

Biggest MySQLdb newbie mistake of all time: Seeing %s and thinking, "I should use the % operator here."

users = []
c = db.cursor()
c.execute("""SELECT userid, first_name, last_name, company
FROM users WHERE status='%s' and expire>'%s'""" %
(status, today)) for userid, first_name, last_name, company in c:
u = User(userid, first_name, last_name, company)
print u
users.append(u)

Note use of % operator to insert parameter values. This does not provide proper quoting (escaping of 'NULL/None, or \0). Passing them separately (as the second parameter) ensures they are quoted correctly. However, % is necessary if you have to insert arbitrary SQL such as column or table names or WHERE clauses.

To buffer, or not to buffer...

mysql_store_result()

  • Stores all rows of result set in client
  • Large result sets can chew up a lot of memory
  • Size of result set known immediately
  • Result set is seekable
  • Can issue another query immediately
  • Used for standard MySQLdb cursor

mysql_use_result()

  • Sends result set row by row
  • Consumes resources on server
  • Must fetch all rows before issuing any other queries
  • Size of result set unknown until finished
  • Not seekable
  • Can be used with MySQLdb's SSCursor

Optional cursor classes

DictCursor causes fetchXXX() methods to return mappings instead of sequences, with column names for keys.

users = []
c = db.cursor(MySQLdb.cursors.DictCursor)
c.execute("""SELECT userid, first_name, last_name, company
FROM users WHERE status=%s and expire>%s""",
(status, today)) for row in c:
u = User(**row)
print u
users.append(u)

Note that column names happen to match User member names in this case.

Type objects and constructors

  • Constructors

    • Date(year,month,day)
    • Time(hour,minute,second)
    • DateFromTicks(ticks)
    • TimeFromTicks(ticks)
    • TimestampFromTicks(ticks)
    • Binary(string)
  • Types
    • STRING
    • BINARY
    • NUMBER
    • DATETIME
    • ROWID

These are not often used with MySQLdb.

Embedded server

  1. Build with embedded server support:

    $ export mysqlclient=mysqld
    $ python setup.py build
    # python setup.py install
  2. _mysql.server_start()
  3. Use normally
  4. _mysql.server_end()

Questions?

  • http://sourceforge.net/projects/mysql-python
  • http://www.terry.uga.edu/
  • http://www.uga.edu/

【转载】Python and Mysql Andy Dustman的更多相关文章

  1. 转载 Python 操作 MySQL 的正确姿势 - 琉璃块

    Python 操作 MySQL 的正确姿势 收录待用,修改转载已取得腾讯云授权 作者 |邵建永 编辑 | 顾乡 使用Python进行MySQL的库主要有三个,Python-MySQL(更熟悉的名字可能 ...

  2. Python 操作 MySQL 之 pysql 与 ORM(转载)

    本文针对 Python 操作 MySQL 主要使用的两种方式讲解: 原生模块 pymsql ORM框架 SQLAchemy 本章内容: pymsql 执行 sql 增\删\改\查 语句 pymsql ...

  3. python 调用mysql存储过程返回结果集

    存储过程: delimiter | ),)) begin select * from tb_test where mid = imid and user = iuser; end; | delimit ...

  4. python数据库(mysql)操作

    一.软件环境 python环境默认安装了sqlite3,如果需要使用sqlite3我们直接可以在python代码模块的顶部使用import sqlite3来导入该模块.本篇文章我是记录了python操 ...

  5. Python 操作 MySQL 的正确姿势

    欢迎大家关注腾讯云技术社区-博客园官方主页,我们将持续在博客园为大家推荐技术精品文章哦~ 作者:邵建永 使用Python进行MySQL的库主要有三个,Python-MySQL(更熟悉的名字可能是MyS ...

  6. Python操作MySQL案例

    最近都在学习Python代码,希望学会Python后,能给我带来更高的工作效率,所以每天坚持学习和拷代码,下面是一个Python操作MySQL的一个实例,该实例可以让更多的人更好了解MySQLdb模块 ...

  7. Python和Mysql、Nginx

    链接: python入门和基础: Python 中文学习大本营 你是如何自学 Python 的? 简明 Python 教程 给伸手党的福利:Python 新手入门引导 <Python爬虫学习系列 ...

  8. Python与Mysql交互

    #转载请联系 在写内容之前,先放一张图,bling- 这张图算是比较详细的表达出了web开发都需要什么.用户访问网页,就是访问服务器的网页文件.这些网页文件由前端工程师编写的.服务器通常用nginx/ ...

  9. Python+Flask+MysqL的web技术建站过程

    1.个人学期总结 时间过得飞快,转眼间2017年就要过去.这一年,我学习JSP和Python,哪一门都像一样新的东西,之前从来没有学习过. 这里我就用我学习过的Python和大家分享一下,我是怎么从一 ...

随机推荐

  1. u3d人物控制

    //https://blog.csdn.net/Htlas/article/details/79188008 //人物移动 http://gad.qq.com/article/detail/28921 ...

  2. VS2015 代码片段整理

    1.什么是代码段? 将一段代码行提取出来,可以多次重复的使用.VS IDE提供对代码段的完整支持.使代码编写更快.更容易.更可靠. 2.系统默认代码段 对于开发人员的例行任务,Visual Studi ...

  3. VIsual Studio编译OpenCV:无法打开python27_d.lib(python36_d.lib)的问题

    原文地址:http://blog.csdn.net/Chris_zhangrx/article/details/78947526 在用 VS2015 编译 Debug 版的 openCV 源码时,最后 ...

  4. hibernate映射关系(多对多)

    Student与Teacher关系多对多(只建了2个实体类) public class Student { private int id; private String name; private S ...

  5. MSSQL—行转列

    行转列,是SQL中经常会遇到的一个问题,并且分为静态转换和动态转换,所谓静态转换即在转换的行数已知或固定:动态转换则为转换的行数不固定. 转换的方法一般采用case when语句或pivot(MSSQ ...

  6. 重新配置ocr voting

    由于存储空间不足,下线的数据库需要把存储空间腾出来,关闭集群资源,主机工程师收回lun需要(包括ocr 和 voting data 磁盘组),新的应用需要上线需要新的数据库,新的hitach存储到位需 ...

  7. Spring Boot (一): Spring Boot starter自定义

    前些日子在公司接触了spring boot和spring cloud,有感于其大大简化了spring的配置过程,十分方便使用者快速构建项目,而且拥有丰富的starter供开发者使用.但是由于其自动化配 ...

  8. 自定义session,cookie

    第一种情况:没有设置缓存:执行相对应的setitem等方法进行,保存到字典里面 cookies_dic={}print(cookies_dic)class Session(): def __init_ ...

  9. 图解Metrics, tracing, and logging

    Logging,Metrics 和 Tracing   最近在看Gophercon大会PPT的时候无意中看到了关于Metrics,Tracing和Logging相关的一篇文章,凑巧这些我基本都接触过, ...

  10. easyui combogrid下拉表格的分页/按键/动态搜索

    作者:xfl4629712  <  easyui combogrid下拉表格的分页/按键/动态搜索  > 需求: 1.下拉框下拉时出现表格: 2.表格带分页功能: 3.可以使用向上键.向下 ...