python进阶
# 1. Python 操作数据库
Python操作数据库可以使用标准数据库接口Python DB-API,或者是使用第三方库,如mysql-connector,PyMySQL、SQLAlchemy等。
Python的DB-API,为大多数的数据库实现了接口,使用它连接各数据库后,就可以用相同的方式操作各数据库。
Python DB-API使用流程:
- 引入 API 模块。
- 获取与数据库的连接。
- 执行SQL语句和存储过程。
- 关闭数据库连接。
# 1.1 python操作MySQL
前提:安装MySQLdb,安装数据库
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import MySQLdb
# 打开数据库连接
db = MySQLdb.connect("localhost", "testuser", "test123", "TESTDB", charset='utf8' )
# 使用cursor()方法获取操作游标
cursor = db.cursor()
# 使用execute方法执行SQL语句
cursor.execute("SELECT VERSION()")
# 使用 fetchone() 方法获取一条数据
data = cursor.fetchone()
print "Database version : %s " % data
# 关闭数据库连接
db.close()
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 1.2 执行事务
- 原子性(atomicity): 一个事务是一个不可分割的工作单位,事务中包括的诸操作要么都做,要么都不做。
- 一致性(consistency): 事务必须是使数据库从一个一致性状态变到另一个一致性状态。一致性与原子性是密切相关的。
- 隔离性(isolation): 一个事务的执行不能被其他事务干扰。即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。
- 持久性(durability): 持续性也称永久性(permanence),指一个事务一旦提交,它对数据库中数据的改变就应该是永久性的。接下来的其他操作或故障不应该对其有任何影响。
# SQL删除记录语句
sql = "DELETE FROM EMPLOYEE WHERE AGE > %s" % (20)
try:
# 执行SQL语句
cursor.execute(sql)
# 向数据库提交
db.commit()
except:
# 发生错误时回滚
db.rollback()
2
3
4
5
6
7
8
9
10
11
# 1.3 python操作Mysql的其他方式
python连接mysql数据库的三种方式参考: https://www.voycn.com/article/pythonlianjiemysqlshujukudesanzhongfangshimysqlconnector-pymysql-mysqldb (opens new window)
# 2. Python 多进程
Python的multiprocessing模块支持多进程,multiprocessing模块提供了一个Process类来代表一个进程对象。 Process类的方法和Thread类的方法类似,例如,start()方法用于启动进程,join()方法可以等待子进程结束后再继续往下运行,terminate()方法用于终止子进程。Process类的构造方法如下:
class multiprocessing.Process(group=None, target=None, name=None, args=(), kwargs={})
- group: 线程组,目前还没有实现,传None即可
- target: 如果不为None,则子进程启动时将运行这个对象
- name: 子进程的名称
- args: 传递给target函数的位置参数,元组形式
- kwargs: 传递给target函数的字典参数
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import multiprocessing
import time
def worker(num):
print 'Worker:', num
time.sleep(2)
print 'end'
if __name__ == '__main__':
jobs = []
for i in range(5):
p = multiprocessing.Process(target=worker, args=(i,))
jobs.append(p)
p.start()
2
3
4
5
6
7
8
9
10
11
12
13
14
执行结果:
Worker: 0
Worker: 1
Worker: 2
Worker: 3
Worker: 4
end
end
end
end
end
2
3
4
5
6
7
8
9
10
# 3. Python 多线程
Python中使用线程有两种方式:函数或者用类来包装线程对象。
thread.start_new_thread ( function, args[, kwargs] )
2
- function - 线程函数。
- args - 传递给线程函数的参数,他必须是个tuple类型。
- kwargs - 可选参数。
# 3.1 线程模块
Python通过两个标准库thread和threading提供对线程的支持。thread提供了低级别的、原始的线程以及一个简单的锁。
threading 模块提供的其他方法:
threading.currentThread(): 返回当前的线程变量。
threading.enumerate(): 返回一个包含正在运行的线程的list。正在运行指线程启动后、结束前,不包括启动前和终止后的线程。
threading.activeCount(): 返回正在运行的线程数量,与len(threading.enumerate())有相同的结果。
除了使用方法外,线程模块同样提供了Thread类来处理线程,Thread类提供了以下方法:
run(): 用以表示线程活动的方法。
start():启动线程活动。
join([time]): 等待至线程中止。这阻塞调用线程直至线程的join() 方法被调用中止-正常退出或者抛出未处理的异常-或者是可选的超时发生。
isAlive(): 返回线程是否活动的。
getName(): 返回线程名。
setName(): 设置线程名。
# 3.1.1 使用Threading模块创建线程
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import threading
import time
# 新线程执行的函数
def loop():
print 'thread %s is running...' % threading.current_thread().name
n = 0
while n < 5:
n = n + 1
print 'thread %s >>> %s' % (threading.current_thread().name, n)
time.sleep(1)
print 'thread %s ended.' % threading.current_thread().name
print 'thread %s is running...' % threading.current_thread().name
t = threading.Thread(target=loop, name='LoopThread')
t.start()
t.join()
print 'thread %s ended.' % threading.current_thread().name
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
执行结果:
thread MainThread is running...
thread LoopThread is running...
thread LoopThread >>> 1
thread LoopThread >>> 2
thread LoopThread >>> 3
thread LoopThread >>> 4
thread LoopThread >>> 5
thread LoopThread ended.
thread MainThread ended.
2
3
4
5
6
7
8
9
# 3.2 线程同步
线程同步就是当有一个线程在对内存进行操作时,其他线程都不可以对这个内存地址进行操作,直到该线程完成操作,其他线程才能对该内存地址进行操作,而这段代码就是保证两个线程安全执行的关键。
# 3.2.1 Lock和RLock
- Lock(指令锁)是互斥锁的基本实现,互斥锁保证了某段关键代码在某一时刻只能被一个线程执行,不能被多个线程同时执行。互斥锁使用acquire方法来获得锁,release方法来释放锁。
- RLock(可重入锁)是Lock的子类,RLock内部维护着一个Lock和一个counter变量,counter记录了acquire,RLock的次数,没acquire一次,counter就加1,每次调用release将counter减1,直到counter为0,锁才被释放。RLock比Lock多了一个acquire和release方法,在同一个线程中,acquire和release可以嵌套使用,例如:
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import threading
lock = threading.RLock()
def func():
lock.acquire()
lock.acquire()
print threading.currentThread().getName() + ' get lock'
lock.release()
lock.release()
t1 = threading.Thread(target=func)
t2 = threading.Thread(target=func)
t3 = threading.Thread(target=func)
t1.start()
t2.start()
t3.start()
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
执行结果:
Thread-1 get lock
Thread-2 get lock
Thread-3 get lock
2
3
# 3.2.2 Condition
Condition和Lock类似,也支持acquire和release方法。Condition也支持wait和notify方法,但是Condition类中的这些方法比Lock类中的这些方法更复杂。
由于Condition类的这些方法涉及到线程间通信,所以比Lock类的这些方法更难理解。Condition的典型应用场景是生产者-消费者模型,生产者线程向队列中添加元素,消费者线程从队列中取出元素,如果队列为空,消费者线程等待,生产者线程添加元素后,唤醒消费者线程。
- acquire([timeout]): 获得Condition内部的Lock。
- release(): 释放Condition内部的Lock。
- wait([timeout]): 调用这个方法将使当前线程进入Condition的等待队列,并释放Condition内部的Lock。当前线程被唤醒(或超时)后,将重新竞争Condition内部的Lock。Condition支持使用notify方法唤醒等待队列中的一个线程(选择由线程调度器决定),或使用notifyAll方法唤醒等待队列中的所有线程。
- notify(): 唤醒等待队列中的一个线程。notifyAll(): 唤醒等待队列中的所有线程。
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import threading
import time
class MyThread(threading.Thread):
def __init__(self, cond, name):
threading.Thread.__init__(self)
self.cond = cond
self.name = name
def run(self):
self.cond.acquire()
print '%s acquire lock' % self.name
self.cond.wait()
print '%s release lock' % self.name
self.cond.release()
cond = threading.Condition()
t1 = MyThread(cond, 't1')
t2 = MyThread(cond, 't2')
t1.start()
t2.start()
time.sleep(1)
print 'Notify one'
cond.acquire()
cond.notify()
cond.release()
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
执行结果:
t1 acquire lock
t2 acquire lock
Notify one
t1 release lock
t2 wait
2
3
4
5
# 3.2.3 ThreadLocal
Python提供了ThreadLocal对象来实现线程间的数据隔离,ThreadLocal类表示线程本地数据,可以把TreadLocal类理解成全局变量,但是每个线程对该变量的操作(读写)都是线程隔离的,互相之间不会影响。
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import threading
# 创建全局ThreadLocal对象:
local_school = threading.local()
def process_student():
# 获取当前线程关联的student:
std = local_school.student
print 'Hello, %s (in %s)' % (std, threading.current_thread().name)
def process_thread(name):
# 绑定ThreadLocal的student:
local_school.student = name
process_student()
t1 = threading.Thread(target= process_thread, args=('Alice',), name='Thread-A')
t2 = threading.Thread(target= process_thread, args=('Bob',), name='Thread-B')
t1.start()
t2.start()
t1.join()
t2.join()
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
执行结果:
Hello, Alice (in Thread-A)
Hello, Bob (in Thread-B)
2
# 3.2.4 线程优先级队列
Python的Queue模块提供了同步的、线程安全的队列类,包括FIFO(先入先出)队列Queue,LIFO(后入先出)队列LifoQueue,和优先级队列PriorityQueue。这些队列都实现了锁原语,能够在多线程中直接使用。可以使用队列来实现线程间的同步。
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import threading
import queue
import time
class MyThread(threading.Thread):
def __init__(self, queue):
threading.Thread.__init__(self)
self.queue = queue
def run(self):
while True:
item = self.queue.get()
if item is None:
break
print threading.current_thread().name, item
self.queue.task_done()
q = queue.Queue()
threads = []
for i in range(5):
t = MyThread(q)
t.setDaemon(True)
t.start()
threads.append(t)
for item in range(10):
q.put(item)
q.join()
for i in range(5):
q.put(None)
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
执行结果:
Thread-1 0
Thread-2 1
Thread-3 2
Thread-4 3
Thread-5 4
Thread-1 5
Thread-2 6
Thread-3 7
Thread-4 8
Thread-5 9
2
3
4
5
6
7
8
9
10