生产者-消费者模型:
看下面的例子哦:
1 import threading,queue 2 import time 3 def consumer(n): 4 while True: 5 print("\033[32;1mconsumer [%s]\033[0m get task: %s"%(n,q.get())) 6 time.sleep(1) 7 q.task_done() 8 def producer(n): 9 count=1 10 while True: 11 print('producer [%s] produced a new task: %s'%(n,count)) 12 q.put(count) 13 count += 1 14 q.join()#queue is emtpy 15 print('all tasks has been cosumed by consumers...') 16 q=queue.Queue() 17 c1=threading.Thread(target=consumer,args=[1,]) 18 c2=threading.Thread(target=consumer,args=[2,]) 19 c3=threading.Thread(target=consumer,args=[3,]) 20 21 p=threading.Thread(target=producer,args=['xiaoyu',]) 22 p2=threading.Thread(target=producer,args=['xiaoXiao',]) 23 c1.start() 24 c2.start() 25 c3.start() 26 p.start() 27 p2.start()
队列q盛放生产者的成果,并且用来在队列为空的时候提醒生产者开始生产。
看一下这里用到的队列,
1 import queue 2 class Foo(object): 3 def __init__(self,n): 4 self.n = n 5 6 q = queue.Queue(maxsize=30) 7 #q = queue.LifoQueue(maxsize=30) 8 #q = queue.PriorityQueue(maxsize=30) 9 q.put((2,[1,2,3])) 10 #q.put(Foo(1)) 11 q.put((10,1)) 12 q.put((3,1)) 13 q.put((5,30)) 14 q.task_done() 15 q.join() 16 print(q.get()) 17 print(q.get()) 18 print(q.get()) 19 print(q.get())
协程
协程,又称微线程,纤程。英文名Coroutine。一句话说明什么是协程:协程是一种用户态的轻量级线程。
协程拥有自己的寄存器上下文和栈。协程调度切换时,将寄存器上下文和栈保存到其他地方,在切回来的时候,恢复先前保存的寄存器上下文和栈。因此:
协程能保留上一次调用时的状态(即所有局部状态的一个特定组合),每次过程重入时,就相当于进入上一次调用的状态,换种说法:进入上一次离开时所处逻辑流的位置。
协程的好处:
- 无需线程上下文切换的开销
- 无需原子操作锁定及同步的开销
- 方便切换控制流,简化编程模型
- 高并发+高扩展性+低成本:一个CPU支持上万的协程都不是问题。所以很适合用于高并发处理。
缺点:
- 无法利用多核资源:协程的本质是个单线程,它不能同时将 单个CPU 的多个核用上,协程需要和进程配合才能运行在多CPU上。当然我们日常所编写的绝大部分应用都没有这个必要,除非是cpu密集型应用。
- 进行阻塞(Blocking)操作(如IO时)会阻塞掉整个程序
使用yield实现协程操作例子
1 import time 2 import queue 3 def consumer(name): 4 print("--->starting eating baozi...") 5 while True: 6 new_baozi = yield 7 print("[%s] is eating baozi %s" % (name,new_baozi)) 8 #time.sleep(1) 9 10 def producer(): 11 12 r = con.__next__() 13 r = con2.__next__() 14 n = 0 15 while n < 5: 16 n +=1 17 con.send(n) 18 con2.send(n) 19 print("\033[32;1m[producer]\033[0m is making baozi %s" %n ) 20 21 22 if __name__ == '__main__': 23 con = consumer("c1") 24 con2 = consumer("c2") 25 p = producer()
Greenlet
1 from greenlet import greenlet 2 def test1(): 3 print (12) 4 gr2.switch() 5 print (34) 6 gr2.switch() 7 def test2(): 8 print(56) 9 gr1.switch() 10 print (78) 11 12 gr1 = greenlet(test1) 13 gr2 = greenlet(test2) 14 gr1.switch()
Gevent 是一个第三方库,可以轻松通过gevent实现并发同步或异步编程,在gevent中用到的主要模式是Greenlet, 它是以C扩展模块形式接入Python的轻量级协程。 Greenlet全部运行在主程序操作系统进程的内部,但它们被协作式地调度。
1 import gevent 2 3 def foo(): 4 print('Running in foo') 5 gevent.sleep(0) 6 print('Explicit context switch to foo again') 7 8 def bar(): 9 print('Explicit context to bar') 10 gevent.sleep(0) 11 print('Implicit context switch back to bar') 12 13 gevent.joinall([ 14 gevent.spawn(foo), 15 gevent.spawn(bar), 16 ])
1 输出: 2 3 Running in foo 4 Explicit context to bar 5 Explicit context switch to foo again 6 Implicit context switch back to bar
同步与异步的性能区别
1 import gevent 2 3 def task(pid): 4 """ 5 Some non-deterministic task 6 """ 7 gevent.sleep(0.5) 8 print('Task %s done' % pid) 9 10 def synchronous(): 11 for i in range(1,10): 12 task(i) 13 14 def asynchronous(): 15 threads = [gevent.spawn(task, i) for i in range(10)] 16 gevent.joinall(threads) 17 18 print('Synchronous:') 19 synchronous() 20 21 print('Asynchronous:') 22 asynchronous()
上面程序的重要部分是将task函数封装到Greenlet内部线程的gevent.spawn
。 初始化的greenlet列表存放在数组threads
中,此数组被传给gevent.joinall
函数,后者阻塞当前流程,并执行所有给定的greenlet。执行流程只会在 所有greenlet执行完后才会继续向下走。
遇到IO阻塞时会自动切换任务
1 from gevent import monkey; monkey.patch_all() 2 import gevent 3 from urllib2 import urlopen 4 #from urllib.request import urlopen 5 6 def f(url): 7 print('GET: %s' % url) 8 resp = urlopen(url) 9 data = resp.read() 10 print('%d bytes received from %s.' % (len(data), url)) 11 12 gevent.joinall([ 13 gevent.spawn(f, 'https://www.python.org/'), 14 gevent.spawn(f, 'https://www.yahoo.com/'), 15 gevent.spawn(f, 'https://github.com/'), 16 ])
通过gevent实现单线程下的多socket并发
1 import socket 2 3 from gevent import socket,monkey 4 monkey.patch_all() 5 6 def server(port): 7 s = socket.socket() 8 s.bind(('0.0.0.0', port)) 9 s.listen(5000) 10 while True: 11 cli, addr = s.accept() 12 gevent.spawn(handle_request, cli,addr) 13 def handle_request(s,addr): 14 try: 15 while True: 16 data = s.recv(1024) 17 print("recv from[%s]:%s"%(addr,data) ) 18 s.send(data) 19 if not data: 20 s.shutdown(socket.SHUT_WR) 21 22 except Exception as ex: 23 pass #print(ex) 24 finally: 25 s.close() 26 if __name__ == '__main__': 27 server(8001)
1 import socket 2 3 HOST = 'localhost' # The remote host 4 PORT = 8001 # The same port as used by the server 5 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 6 s.connect((HOST, PORT)) 7 while True: 8 msg = bytes(input(">>:"),encoding="utf8") 9 s.sendall(msg) 10 data = s.recv(1024) 11 #print(data) 12 13 print('Received', repr(data)) 14 s.close()
论事件驱动与异步IO
事件驱动编程是一种编程范式,这里程序的执行流由外部事件来决定。它的特点是包含一个事件循环,当外部事件发生时使用回调机制来触发相应的处理。另外两种常见的编程范式是(单线程)同步以及多线程编程。
让我们用例子来比较和对比一下单线程、多线程以及事件驱动编程模型。下图展示了随着时间的推移,这三种模式下程序所做的工作。这个程序有3个任务需要完成,每个任务都在等待I/O操作时阻塞自身。阻塞在I/O操作上所花费的时间已经用灰色框标示出来了。
(1)在单线程同步模型中,任务按照顺序执行。如果某个任务因为I/O而阻塞,其他所有的任务都必须等待,直到它完成之后它们才能依次执行。这种明确的执行顺序和串行化处理的行为是很容易推断得出的。如果任务之间并没有互相依赖的关系,但仍然需要互相等待的话这就使得程序不必要的降低了运行速度。
(2)在多线程版本中,这3个任务分别在独立的线程中执行。这些线程由操作系统来管理,在多处理器系统上可以并行处理,或者在单处理器系统上交错执行。这使得当某个线程阻塞在某个资源的同时其他线程得以继续执行。与完成类似功能的同步程序相比,这种方式更有效率,但程序员必须写代码来保护共享资源,防止其被多个线程同时访问。多线程程序更加难以推断,因为这类程序不得不通过线程同步机制如锁、可重入函数、线程局部存储或者其他机制来处理线程安全问题,如果实现不当就会导致出现微妙且令人痛不欲生的bug。
(3)在事件驱动版本的程序中,3个任务交错执行,但仍然在一个单独的线程控制中。当处理I/O或者其他昂贵的操作时,注册一个回调到事件循环中,然后当I/O操作完成时继续执行。回调描述了该如何处理某个事件。事件循环轮询所有的事件,当事件到来时将它们分配给等待处理事件的回调函数。这种方式让程序尽可能的得以执行而不需要用到额外的线程。事件驱动型程序比多线程程序更容易推断出行为,因为程序员不需要关心线程安全问题。
当我们面对如下的环境时,事件驱动模型通常是一个好的选择:
- 程序中有许多任务,而且…
- 任务之间高度独立(因此它们不需要互相通信,或者等待彼此)而且…
- 在等待事件到来时,某些任务会阻塞。
当应用程序需要在任务间共享可变的数据时,这也是一个不错的选择,因为这里不需要采用同步处理。
网络应用程序通常都有上述这些特点,这使得它们能够很好的契合事件驱动编程模型。
Select\Poll\Epoll异步IO
首先列一下,sellect、poll、epoll三者的区别
select
select最早于1983年出现在4.2BSD中,它通过一个select()系统调用来监视多个文件描述符的数组,当select()返回后,该数组中就绪的文件描述符便会被内核修改标志位,使得进程可以获得这些文件描述符从而进行后续的读写操作。
select目前几乎在所有的平台上支持,其良好跨平台支持也是它的一个优点,事实上从现在看来,这也是它所剩不多的优点之一。
select的一个缺点在于单个进程能够监视的文件描述符的数量存在最大限制,在Linux上一般为1024,不过可以通过修改宏定义甚至重新编译内核的方式提升这一限制。
另外,select()所维护的存储大量文件描述符的数据结构,随着文件描述符数量的增大,其复制的开销也线性增长。同时,由于网络响应时间的延迟使得大量TCP连接处于非活跃状态,但调用select()会对所有socket进行一次线性扫描,所以这也浪费了一定的开销。
poll
poll在1986年诞生于System V Release 3,它和select在本质上没有多大差别,但是poll没有最大文件描述符数量的限制。
poll和select同样存在一个缺点就是,包含大量文件描述符的数组被整体复制于用户态和内核的地址空间之间,而不论这些文件描述符是否就绪,它的开销随着文件描述符数量的增加而线性增大。
另外,select()和poll()将就绪的文件描述符告诉进程后,如果进程没有对其进行IO操作,那么下次调用select()和poll()的时候将再次报告这些文件描述符,所以它们一般不会丢失就绪的消息,这种方式称为水平触发(Level Triggered)。
epoll
直到Linux2.6才出现了由内核直接支持的实现方法,那就是epoll,它几乎具备了之前所说的一切优点,被公认为Linux2.6下性能最好的多路I/O就绪通知方法。
epoll可以同时支持水平触发和边缘触发(Edge Triggered,只告诉进程哪些文件描述符刚刚变为就绪状态,它只说一遍,如果我们没有采取行动,那么它将不会再次告知,这种方式称为边缘触发),理论上边缘触发的性能要更高一些,但是代码实现相当复杂。
epoll同样只告知那些就绪的文件描述符,而且当我们调用epoll_wait()获得就绪文件描述符时,返回的不是实际的描述符,而是一个代表就绪描述符数量的值,你只需要去epoll指定的一个数组中依次取得相应数量的文件描述符即可,这里也使用了内存映射(mmap)技术,这样便彻底省掉了这些文件描述符在系统调用时复制的开销。
另一个本质的改进在于epoll采用基于事件的就绪通知方式。在select/poll中,进程只有在调用一定的方法后,内核才对所有监视的文件描述符进行扫描,而epoll事先通过epoll_ctl()来注册一个文件描述符,一旦基于某个文件描述符就绪时,内核会采用类似callback的回调机制,迅速激活这个文件描述符,当进程调用epoll_wait()时便得到通知。
请看下面的例子:
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 #_*_coding:utf-8_*_ 4 __author__ = 'Alex Li' 5 6 import select 7 import socket 8 import sys 9 import queue 10 11 # Create a TCP/IP socket 12 server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 13 server.setblocking(False) 14 15 # Bind the socket to the port 16 server_address = ('localhost', 10000) 17 print(sys.stderr, 'starting up on %s port %s' % server_address) 18 server.bind(server_address) 19 20 # Listen for incoming connections 21 server.listen(5) 22 23 # Sockets from which we expect to read 24 inputs = [ server ] 25 26 # Sockets to which we expect to write 27 outputs = [ ] 28 29 message_queues = {} 30 while inputs: 31 32 # Wait for at least one of the sockets to be ready for processing 33 print( '\nwaiting for the next event') 34 readable, writable, exceptional = select.select(inputs, outputs, inputs,2) 35 # Handle inputs 36 for s in readable: 37 38 if s is server: #new connection 39 # A "readable" server socket is ready to accept a connection 40 connection, client_address = s.accept() 41 print('new connection from', client_address) 42 connection.setblocking(False) 43 inputs.append(connection) 44 45 # Give the connection a queue for data we want to send 46 message_queues[connection] = queue.Queue() 47 else: 48 data = s.recv(1024) 49 if data: 50 # A readable client socket has data 51 print(sys.stderr, 'received "%s" from %s' % (data, s.getpeername()) ) 52 message_queues[s].put(data) 53 # Add output channel for response 54 if s not in outputs: 55 outputs.append(s) 56 else: 57 # Interpret empty result as closed connection 58 print('closing', client_address, 'after reading no data') 59 # Stop listening for input on the connection 60 if s in outputs: 61 outputs.remove(s) #既然客户端都断开了,我就不用再给它返回数据了,所以这时候如果这个客户端的连接对象还在outputs列表中,就把它删掉 62 inputs.remove(s) #inputs中也删除掉 63 s.close() #把这个连接关闭掉 64 65 # Remove message queue 66 del message_queues[s] 67 # Handle outputs 68 for s in writable: 69 try: 70 next_msg = message_queues[s].get_nowait() 71 except queue.Empty: 72 # No messages waiting so stop checking for writability. 73 print('output queue for', s.getpeername(), 'is empty') 74 outputs.remove(s) 75 else: 76 print( 'sending "%s" to %s' % (next_msg, s.getpeername())) 77 s.send(next_msg) 78 # Handle "exceptional conditions" 79 for s in exceptional: 80 print('handling exceptional condition for', s.getpeername() ) 81 # Stop listening for input on the connection 82 inputs.remove(s) 83 if s in outputs: 84 outputs.remove(s) 85 s.close() 86 87 # Remove message queue 88 del message_queues[s]
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 import socket 4 import sys 5 6 messages = [ 'This is the message. ', 7 'It will be sent ', 8 'in parts.', 9 ] 10 server_address = ('localhost', 10000) 11 12 # Create a TCP/IP socket 13 socks = [ socket.socket(socket.AF_INET, socket.SOCK_STREAM), 14 socket.socket(socket.AF_INET, socket.SOCK_STREAM), 15 socket.socket(socket.AF_INET, socket.SOCK_STREAM), 16 socket.socket(socket.AF_INET, socket.SOCK_STREAM), 17 ] 18 19 # Connect the socket to the port where the server is listening 20 print >>sys.stderr, 'connecting to %s port %s' % server_address 21 for s in socks: 22 s.connect(server_address) 23 24 for message in messages: 25 26 # Send messages on both sockets 27 for s in socks: 28 print >>sys.stderr, '%s: sending "%s"' % (s.getsockname(), message) 29 s.send(message) 30 31 # Read responses on both sockets 32 for s in socks: 33 data = s.recv(1024) 34 print >>sys.stderr, '%s: received "%s"' % (s.getsockname(), data) 35 if not data: 36 print >>sys.stderr, 'closing socket', s.getsockname() 37 s.close()
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 import socket, select 4 EOL1 = b'\n\n' 5 EOL2 = b'\n\r\n' 6 response = b'HTTP/1.0 200 OK\r\nDate: Mon, 1 Jan 1996 01:01:01 GMT\r\n' 7 response += b'Content-Type: text/plain\r\nContent-Length: 13\r\n\r\n' 8 response += b'Hello, world!' 9 serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 10 serversocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 11 serversocket.bind(('0.0.0.0', 8080)) 12 serversocket.listen(1) 13 serversocket.setblocking(0) 14 epoll = select.epoll() 15 epoll.register(serversocket.fileno(), select.EPOLLIN) 16 try: 17 connections = {}; requests = {}; responses = {} 18 while True: 19 events = epoll.poll(1) 20 for fileno, event in events: 21 if fileno == serversocket.fileno(): 22 connection, address = serversocket.accept() 23 connection.setblocking(0) 24 epoll.register(connection.fileno(), select.EPOLLIN) 25 connections[connection.fileno()] = connection 26 requests[connection.fileno()] = b'' 27 responses[connection.fileno()] = response 28 elif event & select.EPOLLIN: 29 requests[fileno] += connections[fileno].recv(1024) 30 if EOL1 in requests[fileno] or EOL2 in requests[fileno]: 31 epoll.modify(fileno, select.EPOLLOUT) 32 connections[fileno].setsockopt(socket.IPPROTO_TCP, socket.TCP_CORK, 1) 33 print('-'*40 + '\n' + requests[fileno].decode()[:-2]) 34 elif event & select.EPOLLOUT: 35 byteswritten = connections[fileno].send(responses[fileno]) 36 responses[fileno] = responses[fileno][byteswritten:] 37 if len(responses[fileno]) == 0: 38 connections[fileno].setsockopt(socket.IPPROTO_TCP, socket.TCP_CORK, 0) 39 epoll.modify(fileno, 0) 40 connections[fileno].shutdown(socket.SHUT_RDWR) 41 elif event & select.EPOLLHUP: 42 epoll.unregister(fileno) 43 connections[fileno].close() 44 del connections[fileno] 45 finally: 46 epoll.unregister(serversocket.fileno())
selectors:
1 import selectors 2 import socket 3 4 sel = selectors.DefaultSelector() 5 6 def accept(sock, mask): 7 conn, addr = sock.accept() # Should be ready 8 print('accepted', conn, 'from', addr) 9 conn.setblocking(False) 10 sel.register(conn, selectors.EVENT_READ, read) 11 12 def read(conn, mask): 13 data = conn.recv(1000) # Should be ready 14 if data: 15 print('echoing', repr(data), 'to', conn) 16 conn.send(data) # Hope it won't block 17 else: 18 print('closing', conn) 19 sel.unregister(conn) 20 conn.close() 21 22 sock = socket.socket() 23 sock.bind(('localhost', 10000)) 24 sock.listen(100) 25 sock.setblocking(False) 26 sel.register(sock, selectors.EVENT_READ, accept) 27 28 while True: 29 events = sel.select() 30 for key, mask in events: 31 callback = key.data 32 callback(key.fileobj, mask)
Paramiko
该模块基于SSH用于连接远程服务器并执行相关操作
SSHClient
用于连接远程服务器并执行基本命令
基于用户名密码连接:
import paramiko # 创建SSH对象 ssh = paramiko.SSHClient() # 允许连接不在know_hosts文件中的主机 ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) # 连接服务器 ssh.connect(hostname='c1.salt.com', port=22, username='wupeiqi', password='123') # 执行命令 stdin, stdout, stderr = ssh.exec_command('df') # 获取命令结果 result = filter(lambda x: x is not None,[stdout.read(),stderr.read()])[0] # 关闭连接 ssh.close()
1 import paramiko 2 3 transport = paramiko.Transport(('hostname', 22)) 4 transport.connect(username='wupeiqi', password='123') 5 6 ssh = paramiko.SSHClient() 7 ssh._transport = transport 8 9 stdin, stdout, stderr = ssh.exec_command('df') 10 print stdout.read() 11 12 transport.close() 13 14 SSHClient 封装 Transport
基于公钥密钥连接:
1 import paramiko 2 3 private_key = paramiko.RSAKey.from_private_key_file('/home/auto/.ssh/id_rsa') 4 5 # 创建SSH对象 6 ssh = paramiko.SSHClient() 7 # 允许连接不在know_hosts文件中的主机 8 ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) 9 # 连接服务器 10 ssh.connect(hostname='c1.salt.com', port=22, username='wupeiqi', key=private_key) 11 12 # 执行命令 13 stdin, stdout, stderr = ssh.exec_command('df') 14 # 获取命令结果 15 result = stdout.read() 16 17 # 关闭连接 18 ssh.close()
1 import paramiko 2 3 private_key = paramiko.RSAKey.from_private_key_file('/home/auto/.ssh/id_rsa') 4 5 transport = paramiko.Transport(('hostname', 22)) 6 transport.connect(username='wupeiqi', pkey=private_key) 7 8 ssh = paramiko.SSHClient() 9 ssh._transport = transport 10 11 stdin, stdout, stderr = ssh.exec_command('df') 12 13 transport.close()
SFTPClient
用于连接远程服务器并执行上传下载
基于用户名密码上传下载
1 import paramiko 2 3 transport = paramiko.Transport(('hostname',22)) 4 transport.connect(username='wupeiqi',password='123') 5 6 sftp = paramiko.SFTPClient.from_transport(transport) 7 # 将location.py 上传至服务器 /tmp/test.py 8 sftp.put('/tmp/location.py', '/tmp/test.py') 9 # 将remove_path 下载到本地 local_path 10 sftp.get('remove_path', 'local_path') 11 12 transport.close()
基于公钥密钥上传下载
1 import paramiko 2 3 private_key = paramiko.RSAKey.from_private_key_file('/home/auto/.ssh/id_rsa') 4 5 transport = paramiko.Transport(('hostname', 22)) 6 transport.connect(username='wupeiqi', pkey=private_key ) 7 8 sftp = paramiko.SFTPClient.from_transport(transport) 9 # 将location.py 上传至服务器 /tmp/test.py 10 sftp.put('/tmp/location.py', '/tmp/test.py') 11 # 将remove_path 下载到本地 local_path 12 sftp.get('remove_path', 'local_path') 13 14 transport.close()
数据库操作
SQL基本使用
1、数据库操作
1 show databases; 2 use [databasename]; 3 create database [name];
2、数据表操作
1 show tables; 2 3 create table students 4 ( 5 id int not null auto_increment primary key, 6 name char(8) not null, 7 sex char(4) not null, 8 age tinyint unsigned not null, 9 tel char(13) null default "-" 10 );
1 CREATE TABLE `wb_blog` ( 2 `id` smallint(8) unsigned NOT NULL, 3 `catid` smallint(5) unsigned NOT NULL DEFAULT '0', 4 `title` varchar(80) NOT NULL DEFAULT '', 5 `content` text NOT NULL, 6 PRIMARY KEY (`id`), 7 UNIQUE KEY `catename` (`catid`) 8 ) ;
3、数据操作
1 insert into students(name,sex,age,tel) values('alex','man',18,'151515151') 2 3 delete from students where id =2; 4 5 update students set name = 'sb' where id =1; 6 7 select * from students
4、其他
1 主键 2 外键 3 左右连接
Python MySQL API
一、插入数据
1 import MySQLdb 2 3 conn = MySQLdb.connect(host='127.0.0.1',user='root',passwd='1234',db='mydb') 4 5 cur = conn.cursor() 6 7 reCount = cur.execute('insert into UserInfo(Name,Address) values(%s,%s)',('peony','usa')) 8 # reCount = cur.execute('insert into UserInfo(Name,Address) values(%(id)s, %(name)s)',{'id':12345,'name':'wupeiqi'}) 9 10 conn.commit() 11 12 cur.close() 13 conn.close() 14 15 print reCount
1 import MySQLdb 2 3 conn = MySQLdb.connect(host='127.0.0.1',user='root',passwd='1234',db='mydb') 4 5 cur = conn.cursor() 6 7 li =[ 8 ('peony','usa'), 9 ('jeff','usa'), 10 ] 11 reCount = cur.executemany('insert into UserInfo(Name,Address) values(%s,%s)',li) 12 13 conn.commit() 14 cur.close() 15 conn.close() 16 17 print (reCount)
注意:cur.lastrowid
二、删除数据
import MySQLdb conn = MySQLdb.connect(host='127.0.0.1',user='root',passwd='1234',db='mydb') cur = conn.cursor() reCount = cur.execute('delete from UserInfo') conn.commit() cur.close() conn.close() print (reCount)
三、修改数据
1 import MySQLdb 2 3 conn = MySQLdb.connect(host='127.0.0.1',user='root',passwd='1234',db='mydb') 4 5 cur = conn.cursor() 6 7 reCount = cur.execute('update UserInfo set Name = %s',('alin',)) 8 9 conn.commit() 10 cur.close() 11 conn.close() 12 13 print (reCount)
四、查数据
1 # ############################## fetchone/fetchmany(num) ############################## 2 3 import MySQLdb 4 5 conn = MySQLdb.connect(host='127.0.0.1',user='root',passwd='1234',db='mydb') 6 cur = conn.cursor() 7 8 reCount = cur.execute('select * from UserInfo') 9 10 print cur.fetchone() 11 print cur.fetchone() 12 cur.scroll(-1,mode='relative') 13 print cur.fetchone() 14 print cur.fetchone() 15 cur.scroll(0,mode='absolute') 16 print cur.fetchone() 17 print cur.fetchone() 18 19 cur.close() 20 conn.close() 21 22 print reCount 23 24 25 26 # ############################## fetchall ############################## 27 28 import MySQLdb 29 30 conn = MySQLdb.connect(host='127.0.0.1',user='root',passwd='1234',db='mydb') 31 #cur = conn.cursor(cursorclass = MySQLdb.cursors.DictCursor) 32 cur = conn.cursor() 33 34 reCount = cur.execute('select Name,Address from UserInfo') 35 36 nRet = cur.fetchall() 37 38 cur.close() 39 conn.close() 40 41 print reCount 42 print nRet 43 for i in nRet: 44 print i[0],i[1]
来源:https://www.cnblogs.com/Peony-Y/p/5308859.html