语言Python开发【第十一篇】:Python操作MySQL

本篇对于Python操作MySQL主要用简单种植办法:

协程

协程,又如微线程,纤程。英文名Coroutine。一句话说明什么是协程,协程是同等种用户态的轻量级线程。

协程拥有好之寄存器上下文和仓库。协程调度切换时,将寄存器上下文和栈保存到另外地方,在切换回来的早晚,恢复原先保存的寄存器上下文和库房。因此,协程能保存上亦然次调用的状态(即享片状态的一个一定组合),每次经过重入时,就一定给上及一致赖调用的状态,换种说法,进入及平等不好去时所处逻辑流的位置。

子程序,或者叫做函数,在享有语言中还是层级调用,比如A调用B,B在履过程被以调用了C,C执行完毕返回,B执行了返回,最后A执行完毕。

所以子程序调用时经过储藏室实现的,一个线程就是执行一个子序。子程序调用总是一个进口,一不好回到,调用顺序是显眼的。而协程的调用和子程序不同。

协程看上去也是子程序,但履过程被,在子程序中可暂停,然后转而实行别的子程序,在适宜的早晚再次回回来接着执行。

小心,在一个子顺序中暂停,去履行其他子程序,不是函数调用,有接触类似CPU的中断。比如子程序A、B:

  1. def a():

  2.     print(“1”)

  3.     print(“2”)

  4.     print(“3”)

  5.  

  6. def b():

  7.     print(“x”)

  8.     print(“y”)

  9.     print(“z”)

假定由程序执行,在执行A的长河遭到,可以天天刹车,去执行B,B也或在推行进程遭到间断再夺执行A,结果或者是:

  1. 1

  2. 2

  3. x

  4. y

  5. 3

  6. z

可于A中凡从未有过调用B的,所以协程的调用比函数调用理解起来要麻烦一些。看起来A、B的实行稍微像多线程,但协程的特性于凡一个线程执行,和多线程比协程有哪优势?

顶特别之优势就是是协程极高之行效率。因为子程序切换不是线程切换,而是有程序自身控制,因此,没有线程切换的开发,和多线程比,线程数量越来越多,协程的属性优势就是越发明白。

次生优势就是是免欲差不多线程的锁机制,因为只来一个线程,也非存以写变量冲突,在协程中控制共享资源不加锁,只需要判定状态就哼了,所以实行效率比多线程高多。

坐协程是一个线程执行,那么怎么利用基本上核CPU呢?最简易的法是多进程加协程,既充分利用多对,有充分发挥协程的胜效率,可抱无限高的属性。

协程的亮点:

无需线程上下文切换的出。

无须原子操作锁定和共同的开销。原子操作(atomic
operation)是匪待synchronized,所谓原子操作是依不会见叫线程调度机制打断的操作;这种操作而开,就直接运转及结束,中间不会见出另context
switch(切换到任何一个线程)。原子操作可以是一个步骤,也得以是大抵独操作步骤,但是其顺序是免得以给七手八脚,或者切割掉就实行有。视作整体是原子性的中心。

利切换控制流,简化编程模型。

高并发+高扩展性+低本钱。一个CPU支持上万的协程都不是问题,所以老抱用于高并发处理。

协程的先天不足:

无法使用基本上按资源。协程的原形是单单线程,它不能够同时以单个CPU的基本上独核用上,协程需要以及经过配合才能够运行于差不多CPU上。当然我们平常所修的多头采用都无这个必要,除非是CPU密集型应用。

进展围堵(Blocking)操作(如IO时)会阻塞掉所有程序。

应用yield实现协程操作。

  1. import time,queue

  2.  

  3. def consumer(name):

  4.     print(“–>starting eating xoxo”)

  5.     while True:

  6.         new_xo = yield

  7.         print(“%s is eating xoxo %s”%(name,new_xo))

  1.  

  2. def producer():

  3.     r = con.__next__()

  4.     r = con2.__next__()

  5.     n = 0

  6.     while n < 5:

  7.         n += 1

  8.         con.send(n)

  9.         con2.send(n)

  10.         print(“\033[32;1mproducer\033[0m is making xoxo
    %s”%n)

  11.  

  12. if
    __name__ == “__main__”:

  1.     con = consumer(“c1”)

  2.     con2 = consumer(“c2”)

  3.     p = producer()

  4. 输出:

  5. –>starting eating xoxo

  6. –>starting eating xoxo

  7. c1 is
    eating xoxo 1

  8. c2 is
    eating xoxo 1

  9. producer is making xoxo 1

  10. c1 is
    eating xoxo 2

  11. c2 is
    eating xoxo 2

  12. producer is making xoxo 2

  13. c1 is
    eating xoxo 3

  14. c2 is
    eating xoxo 3

  15. producer is making xoxo 3

  16. c1 is
    eating xoxo 4

  17. c2 is
    eating xoxo 4

  18. producer is making xoxo 4

  19. c1 is
    eating xoxo 5

  20. c2 is
    eating xoxo 5

  21. producer is making xoxo 5

协程的特色:

1、必须在只有出一个单线程里心想事成产出。

2、修改共享数据未需要加锁。

3、用户程序里团结维持多独控制流的光景文栈。

4、一个协程遇到IO操作自动切换至其它协程。

刚才yield实现的非可知算是合格的协程。

Python对协程的支撑是透过generator实现的。在generator中,我们不但可以通过for循环来迭代,还足以持续调用next()函数获取由yield语句返回到下一个价。但是python的yield不但可返回一个价值,它可以吸收调用者发出之参数。

1、原生模块pymsql。

Greenlet

greenlet是一个用C实现之协程模块,相比叫Python自带的yield,它好在任意函数之间自由切换,而不需将这函数声明也generator。

  1. from greenlet import greenlet

  2.  

  3. def f1():

  4.     print(11)

  5.     gr2.switch()

  6.     print(22)

  7.     gr2.switch()

  8.  

  9. def f2():

  10.     print(33)

  11.     gr1.switch()

  12.     print(44)

  13.  

  14. gr1 = greenlet(f1)

  15. gr2 = greenlet(f2)

  16. gr1.switch()

  17. 输出:

  18. 11

  19. 33

  20. 22

  21. 44

以上例子还有一个题目没有缓解,就是碰到IO操作自动切换。

2、ORM框架SQLAchemy。

Gevent

Gevent是一个叔方库,可以轻松提供gevent实现产出同步还是异步编程,在gevent中因故到的首要模式是Greenlet,它是盖C扩展模块式接入Python的轻量级协程。Greenlet全部运作在主程序操作系统进程的中,但它吃协作式地调度。

  1. import gevent

  2.  

  3. def foo():

  4.     print(“Running in foo”)

  5.     gevent.sleep()

  6.     print(“Explicit contenxt switch to foo agin”)

  1.  

  2. def bar():

  3.     print(“Explicit context to bar”)

  4.     gevent.sleep(1)

  5.     print(“Implict context switch back to bar”)

  1.  

  2. def func3():

  3.     print(“running func3”)

  4.     gevent.sleep(0)

  5.     print(“running func3 again”)

  6.  

  7. gevent.joinall([

  8.      gevent.spawn(foo),

  9.      gevent.spawn(bar),

  10.      gevent.spawn(func3),

  11.     ])

  12. 输出:

  13. Running in foo

  14. Explicit context to bar

  15. running func3

  16. Explicit contenxt switch to foo agin

  17. running func3 again

  18. Implict context switch back to bar

pymsql

pymsql是Python中操作MySQL的模块,其动办法以及MySQLdb几乎等同。

一路和异步的属性区别

  1. import gevent

  2.  

  3. def f1(pid):

  4.     gevent.sleep(0.5)

  5.     print(“F1 %s done”%pid)

  6.  

  7. def f2():

  8.     for i in
    range(10):

  9.         f1(i)

  10.  

  11. def f3():

  12.     threads = [gevent.spawn(f1,i)
    for i in range(10)]

  13.     gevent.joinall(threads)

  14.  

  15. print(“f2”)

  16. f2()

  17. print(“f3”)

  18. f3()

  19. 输出:

  20. f2

  21. F1 0 done

  22. F1 1 done

  23. F1 2 done

  24. F1 3 done

  25. F1 4 done

  26. F1 5 done

  27. F1 6 done

  28. F1 7 done

  29. F1 8 done

  30. F1 9 done

  31. f3

  32. F1 0 done

  33. F1 4 done

  34. F1 8 done

  35. F1 7 done

  36. F1 6 done

  37. F1 5 done

  38. F1 1 done

  39. F1 3 done

  40. F1 2 done

  41. F1 9 done

面程序的要紧组成部分是拿f1部数包到Greenlet内部线程的gevent.spawn。初始化的greenlet列表存放于数组threads中,此数组被污染给gevent.joinall函数,后者阻塞时流程,并履行有给定的greenlet。执行流程就见面当有着greenlet执行了晚才见面继续朝下活动。

windows下载安装

  1. pip3 install pymysql

IO阻塞自动切换任务

  1. from urllib import request

  2. import gevent,time

  3. from gevent import monkey

  4.  

  5. #
    把当前次的有着的id操作为单独的开上标记

  6. monkey.patch_all()

  7. def f(url):

  8.     print(“GET:%s”%url)

  9.     resp = request.urlopen(url)

  10.     data = resp.read()

  11.     f = open(“load.txt”,”wb”)

  12.     f.write(data)

  13.     f.close()

  14.     print(“%d bytes received from
    %s.”%(len(data),url))

  15.  

  16. urls = [‘https://www.python.org/’,

  17.         ‘http://www.cnblogs.com/yinshoucheng-golden/’,

  1.         ‘https://github.com/'\]

  2. time_start = time.time()

  3. for
    url in urls:

  4.     f(url)

  5. print(“同步cost”,time.time() – time_start)

  1.  

  2. async_time_start = time.time()

  1. gevent.joinall([

  2.     gevent.spawn(f,’https://www.python.org/’),

  3.     gevent.spawn(f,’http://www.cnblogs.com/yinshoucheng-golden/’),

  1.     gevent.spawn(f,’https://github.com/’),

  2. ])

  3. print(“异步cost”,time.time() –
    async_time_start)

采取操作

执行SQL

  1. __author__ = ‘Golden’

  2. #!/usr/bin/env python3

  3. # -*- coding:utf-8 -*-

  4. import pymysql

  5.  

  6. # 创建连接

  7. conn =
    pymysql.connect(host=’192.168.31.134′,port=3306,user=’root’,passwd=’123456′,db=’information_schema’)

  1. # 创建游标

  2. cursor = conn.cursor()

  3. # 执行SQL,并回到给影响行数

  4. effect_row = cursor.execute(“select * from tables”)

  5. print(effect_row)

  6. # 取出同长达数据

  7. print(cursor.fetchone())

  8. # 取出前n条数据

  9. print(“*********************************************************”)

  1. print(cursor.fetchmany(5))

  2. # 取出具有数据

  3. print(“*********************************************************”)

  1. print(cursor.fetchall())

  2. # 提交,不然无法保存新建或涂改的数额

  1. conn.commit()

  2. # 关闭游标

  3. cursor.close()

  4. # 关闭连接

  5. conn.close()

恐报错:pymysql.err.InternalError: (1130, “Host ‘192.168.31.1’ is not
allowed to connect to this MySQL server”)

唯恐是以若的账号不允许打远程登录,只能当localhost登录。只需要以localhost的那台电脑登录mysql,更改对承诺数据库里之”user”表里的”host”项,把”localhost”改也”%”。

解决办法:

1、改表法

  1. [root@lnmp ~]# mysql -uroot -p123456
  1. mysql> use test;

  2. Database changed

  3. mysql> update user set host = ‘%’ where user = ‘root’;

  1. mysql> select host,user from user;
  1. mysql> flush rivileges;

2、授权法

容用户user使用密码password从旁主机连接至mysql服务器。

  1. mysql> grant all privileges on *.*
    to ‘user’@’%’ identified by ‘password’ with grant option;

  2. mysql> flush privileges;

允许用户user从ip192.168.1.122之主机连接到mysql服务器,并运用password作为密码。

  1. mysql> grant all privileges on *.*
    to ‘user’@’192.168.1.122’ identified by ‘password’ with grant
    option;

  2. mysql> flush privileges;

许用户user从ip192.168.1.122底主机连接到mysql服务器的test_db数据库,并下password作为密码。

  1. mysql> grant all privileges on
    test_db.* to ‘user’@’192.168.1.122’ identified by ‘password’ with
    grant option;

  2. mysql> flush privileges;

栽数据

  1. # 插入数据

  2. effect_row = cursor.executemany(“inster into
    table_name(field_name1,field_name2)
    values(%s,%s)”,[(“value_1″,”value_2”),(“value_3″,”value_4”)])

通过gevent实现单线程下之多socket并作

server side

  1. import sys,socket,time,gevent

  2.  

  3. from gevent import socket,monkey

  1. monkey.patch_all()

  2.  

  3. def server(port):

  4.     s = socket.socket()

  5.     s.bind((“0.0.0.0”,port))

  6.     s.listen(500)

  7.     while True:

  8.         cli,addr = s.accept()

  9.         gevent.spawn(handle_request,cli)

  1.  

  2. def handle_request(conn):

  3.     try:

  4.         while True:

  5.             data = conn.recv(1024)

  1.             print(“recv:”,data)

  2.             if not data:

  3.                 conn.shutdown(socket.SHUT_WR)

  1.             conn.send(data)

  2.     except Exception as ex:

  3.         print(ex)

  4.     finally:

  5.         conn.close()

  6.  

  7. if
    __name__ == “__main__”:

  1.     server(6969)

client side

  1. import socket

  2.  

  3. HOST = “localhost”

  4. PORT = 6969

  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.     print(“Received”,repr(data))

  13.  

  14. s.close()

socket并发

  1. import socket,threading

  2.  

  3. def sock_conn():

  4.     client = socket.socket()

  5.     client.connect((“localhost”,6969))

  6.     count = 0

  7.  

  8.     while True:

  9.         client.send((“hello %s”%count).encode(“utf-8”))

  10.         data = client.recv(1024)

  1.         print(“%s from
    server:%s”%(threading.get_ident(),data.decode()))

  2.         count += 1

  3.     client.close()

  4.  

  5. for i
    in range(100):

  6.     t =
    threading.Thread(target=sock_conn)

  7.     t.start()

SQLAlchemy ORM

事件驱动与异步IO

形容服务器处理模型的次第时,有瞬间几乎种模型:

(1)每收到一个伸手,创建一个初的过程,来拍卖该要。

(2)每收到一个请,创建一个新的线程,来拍卖该要。

(3)每收到一个求,放入一个波列表,让主程序通过非阻塞I/O方式来处理要。

地方的几种方法,各有千秋。

第一种方式,由于创建新的进程,内存开销比较深。所以,会促成服务器性能比差,但实现比较简单。

老二栽办法,由于要涉及到线程的同步,有或会见面临死锁等题材。

老三种艺术,在形容应用程序代码时,逻辑比前两种植都复杂。

归结考虑各方面因素,一般普遍认为第三种方法是大部分网络服务器以的道。

在UI编程中,常常要对鼠标点击进行对应响应,首先如何获取鼠标点击呢?

道相同:创建一个线程,该线程一直循环检测是否有鼠标点击,那么这个点子来以下几单毛病。

1、CPU资源浪费,可能鼠标点击的效率十分小,但是扫描线程还是会直接循环检测,这会招广大的CPU资源浪费;如果扫描鼠标点击的接口是死的也?

2、如果是死的,又会油然而生下面这样的问题。如果我们不但使扫描鼠标点击,还要扫描键盘是否按下,由于扫描鼠标时被卡住了,那么可能永远不见面去扫描键盘。

3、如果一个巡回需要扫描的设施非常多,这又会引起响应时间的问题。

因此,这种艺术很坏。

计二:事件驱动模型

眼前大部分之UI编程都是事件驱动模型。如很多UI平台都见面供onClick()事件,这个事件便象征鼠标点击事件。事件驱动模型大体思路如下。

1、有一个轩然大波(消息)队列。

2、鼠标按下经常,往这队列中多一个点击事件(消息)。

3、有一个循环,不断自队列取出事件。根据不同之风波,调出不同的函数,如onClick()、onKeyDown()等。

4、事件(消息)一般还分别保存各自的处理函数指针,这样每个消息还来单独的处理函数。

语言 1

事件驱动编程是如出一辙种编程范式,这里先后的实践流由外部事件来决定。它的特性是含有一个轩然大波循环,当外部事件来时用回调机制来点相应的拍卖。另外两只常见的编程范式是并(单线程)以及多线程编程。

相对而言单线程、多线程以及事件驱动编程模型。下图表示随着年华之延迟,这三种模式下程序所做的干活。这个程序来3只任务要完成,每个任务还当等候I/O操作时打断自身。阻塞在I/O操作及所消费的时间所以灰色框表示。

语言 2

每当单线程同步模型中,任务论顺序执行。如果某个任务为I/O而阻塞,其他具有的任务要等,直到它好之后才能够挨个执行外操作。这种眼看的履行顺序与串行化处理的行事可以见到,如果各任务中并没相互依赖的干,但每任务尽还要相互等待,就让程序整体运行速度降了。

在差不多线程版本被,这3单任务分别在独立的线程中推行。这些线程由操作系统来治本,在多处理器系统上得以并行处理,或者当一味处理器系统上交替执行。这让当有线程阻塞在某个资源的同时另外线程得以继续执行。多线程程序更加不便判定,因为当时类程序不得不通过线程同步机制加锁、可重新称函数、线程局部存储或者其它机制来拍卖线程安全题材,如果实现不当就会见造成出现微妙且使得人痛定思痛之BUG。

于事件驱动版本的主次中,3个任务交错执行,但仍在一个单独的线程控制着。当处理I/O或其它等待操作时,注册一个回调到事件循环中,然后当I/O操作完成时继续执行。回调描述了拖欠怎么处理某个事件。事件循环轮询所有的波,当事件到时将它们分配为等处理事件之回调函数。这种措施叫程序尽可能的可实施要休待因此到额外的线程。事件驱动型程序于多线程程序还爱推断出作为,因为程序员不需要关爱线程安全题材。

ORM介绍

靶关联映射(Object Relational
Mapping,简称ORM),是一律种次技术,用于落实面向对象编程语言里不同种类系统的数量里的转换。从成效达到说,它实在是创立了一个不过在编程语言里以的——”虚拟对象数据库”。

面向对象是打软件工程基本条件(如耦合、聚合、封装)的底蕴及更上一层楼起的,而关系数据库则是自数学理论发展而来的,两效理论在明显的分。为了化解之不兼容的场景,对象关联映射技术出现。

对象关系映射(Object Relational
Mapping)提供了概念性的、易于掌握的模型化数据的方。ORM方法论基于三个为主标准。简单,以最核心的样式建模数据。传达性,数据库结构于任何人都能理解的语言文档化。精确性,基于数据模型创建是原则的组织。典型地,建模者通过收集来自那些熟悉应用程序但无在行数据建模者开发信息模型。建模者必须能够用无技术企业专家可以清楚的术语在概念层次上与数据结构进行报道。建模者也要能坐简单的单元分析信息,对样本数量进行拍卖。ORM专门叫设计吧改善这种联系。

语言 3

I/O多路复用

同步I/O和异步I/O,阻塞I/O和非阻塞I/O分别是呀,到底发生什么区别?本文讨论的背景是Linux环境下之network
I/O。

ORM的优点

1、隐藏了数量访问细节,”封闭”的通用数据库交互,ORM的主干。使得通用数据库的相变得简单易行,并且完全不用考虑SQL语句。

2、ORM使组织固化数据结构变得简单易行。

概念说明

用户空间和根本空间

今昔操作系统还是使用虚拟存储器,那么对32各类操作系统而言,它的寻址空间(虚拟存储空间)为4G(2的32次方)。操作系统的中坚是水源,独立于平常的应用程序,可以拜于保障之内存空间,也产生看根硬件设备的兼具权限。为了确保用户进程不可知一直操作内核(kernel),保证基本的平安,操作系统将虚拟空间划分为寡组成部分,一部分为基石空间,一部分也用户空间。针对Linux操作系统而言,将高的1G字节(从虚拟地址0xC0000000及0xFFFFFFFF),供内核使用,称为内核空间,而以比较逊色之3G字节(从虚拟地址0x00000000届0xBFFFFFFF),供各个进程使,称为用户空间。

进程切换

为控制过程的推行,内核必须来能力挂于在CPU上运行的长河,并恢复原先挂于底有进程的实践。这种表现为称呼进程切换。因此可以说,任何进程都是于操作系统内核的支持下运作的,是与根本紧密相关的。

自从一个经过的周转转至其它一个过程上运行,这个过程被经过下面过程:

1、保存处理机上下文,包括程序计数器和外寄存器。

2、更新PCB信息。

3、把经过的PCB移入相应的阵,如就绪、在某某波阻塞等行列。

4、选择其他一个过程执行,并创新其PCB。

5、更新内存管理之数据结构。

6、恢复处理机上下文。

过程控制块(Processing Control
Block),是操作系统核心中一样栽多少结构,主要代表经过状态。其用意是一旦一个以多道程序环境下不能够独立运转的次序(含数据),成为一个会独立运转的核心单位或者和另外进程并发执行之长河。或者说,操作系统OS是根据PCB来对出现执行的经过展开控制与管理之。PCB通常是系内存占用区中之一个连续存放区,它存放着操作系统用于描述进程情况及控制过程运行所用的全音讯。

进程的梗塞

方尽的进程,由于要的某些事件不生,如要系统资源失败、等待某种操作的落成、新数据尚未到或任新职责执行等,则是因为网自动执行阻塞(Block),使好是因为运行状态变为阻塞状态。可见,进程的短路是过程本身的如出一辙栽积极作为,也因而只有处于运行状态的进程(获得CPU),才能够拿该转为阻塞状态。当进程进入阻塞状态,是勿占用CPU资源的。

文件讲述符fd

文件讲述吻合(File
descriptor)是电脑对中的一个术语,是一个用以表述对文件的援的抽象化概念。

文本讲述符在形式达到是一个非负整数。实际上,它是一个索引值,指向内核为各一个进程所保障的该过程打开文件之记录表。当次打开一个共处文件要创造一个初文件时,内核向经过返回一个文件讲述吻合。在次设计被,一些企划底层的程序编制往往会围绕着公文讲述符展开。但是文件讲述称这等同定义往往只有适用于UNIX、Linux这样的操作系统。

缓存I/O

缓存I/O又于誉为标准I/O,大多数文件系统的默认I/O操作都是缓存I/O。在Linux的休养生息存I/O机制中,操作系统会将I/O的数据缓存在文件系统的页缓存(page
cache)中,也就是说,数据会先被拷贝到操作系统内核的缓冲区中,然后才见面从操作系统内核的缓冲区拷贝到应用程序的地方空间。

缓存I/O的缺点:

数码在传过程遭到得以应用程序地址空间及水源进行多次数据拷贝操作,这些数据拷贝操作所带动的CPU以及内存开销是很酷之。

ORM的缺点

1、自动化意味着映射和事关管理,代价是牺牲性能。现在各种ORM框架还在品味以各种方式(如LazyLoad、Cache)来减轻性能的熏陶,效果比较显著。

2、面向对象的询问语言(OQL)作为一如既往种植数据库和对象期间的接,虽然隐藏了数码层面的事体抽象,但连无克全的遮光掉数据库层的筹划,并且确实将多学习成本。

3、对于复杂查询,ORM仍然鞭长莫及。虽然可以实现,但是非值得。视图可以缓解大部分calculated
column、case、group、having、order by、exists,但是查询条件a and b and
not c and (d or e)不可知很好解决。

IO模式

对于同一潮IO访问(以read为例),数据会先被拷贝到操作系统内核的缓冲区中,然后才见面自操作系统内核的缓冲区拷贝到应用程序的地方空间。当一个read操作发生时,会更两只级次:

1、等待数准备(waiting for the data to be ready)。

2、将数据由根本拷贝到过程面临(Copying the data from the kernel to the
process)。

幸亏因为就点儿只级次,Linux系统产生了底五栽网络模式之方案。

阻塞I/O(blocking IO)。

非阻塞I/O(nonblocking IO)

I/O多路复用(IO multiplexing)

信号驱动I/O(signal driven IO)

异步I/O(asynchronous IO)

是因为信号驱动I/O(signal driven
IO)在实际上被连无常用,所以只有剩余四种IO模式。

阻塞I/O(blocking IO)

每当Linux中,默认情况下拥有的Socket都是blocking,一个卓越的读操作流程如下:

语言 4

当用户进程调用了recvfrom,kernel就起来了IO的首先单等级,准备数据。对于网IO来说,很多时光数据以同一上马还尚未到达。比如还并未收到一个完完全全的UDP包,这个时候kernel就要等足够的数量来临。这个过程要等,也就是说数据为拷贝到操作系统内核的缓冲区中是需要一个过程的。而于用户进程就边,整个过程会受打断。当kernel一直相当及数量准备好了,它就是见面拿数据由kernel中拷贝到用户内存,然后kernel返回结果,用户进程才散block的状态,重新运行起来。

故而,blocking IO的特色就是当IO执行的有数个阶段都受block了。

非阻塞I/O(nonblocking IO)

Linux下,可以经安装Socket使该变成non-blocking。当对一个non-blocking
socket执行读操作时,流程如下:

语言 5

当用户进程有read操作时,如果kernel中之数还不曾准备好,那么它们并无会见block用户进程,而是这回去一个error。从用户进程角度谈,它提倡一个read操作后,并不需要等待,而是立即就得到了一个结出。用户进程判断结果是一个error时,它就明白多少还从未备选好,于是它可以重新发送read操作。一旦kernel中的数量准备好了,并且又又收到了用户进程的system
call,那么它立刻以数据拷贝到了用户内存,然后回。

故而,nonblocking
IO的特征是用户进程要持续的能动询问kernel数据吓了无。

I/O多路复用(IO multiplexing)

IO
multiplexing就是平时所说之select、poll、epoll,有些地方吧称这种IO方式啊event
driven
IO。select/epoll的益处就在于单个process就可同时处理多独网络连接的IO。它的基本原理就是select、poll、epoll这个function会不断的轮询所承担之所有socket,当某个socket有数据到了,就通知用户进程。

语言 6

当用户进程调用了select,那么万事经过会叫block。而同时kernel会”监视”所有select负责之socket,当其他一个socket中之多少准备好了,select就会见回来。这个时段用户进程再调用read操作,将数据由kernel拷贝到用户进程。

因此,I/O多矣复用的特色是由此一致种植机制一个历程会而且等待多单文件描述符,而这些文件讲述吻合(套接字描述称)其中的肆意一个上读就绪状态,select()函数就得回去。

此图和blocking
IO的图其实并没有最好可怜之不比。事实上还又不比有,因为此需要用有限独system
call(select和recvfrom),而blocking IO只调用了一个system
call(recvfrom)。但是之所以select的优势在于其可又处理多个connection。

骨子里在IO multiplexing
Model中,对于每一个socket一般还安装成non-blocking。但是如上图所示整个用户之process其实是一直让block的。只不过process是让select这个函数block,而休是吃socket
IO给block。

异步I/O(asynchronous IO)

Linux下的asynchronous IO其实用得够呛少。

语言 7

用户进程发起read操作之后,离开就可初步失去开另外的转业。而任何一个方面,从kernel的角度,当她遭一个asynchronous
read之后,首先她会立马回去,所以无见面对用户进程来任何block。然后kernel会等待数准备就,然后将数据拷贝到用户内存,当这周都得之后,kernel会让用户进程发送一个signal,告诉它read操作完成了。

常用的ORM框架

1、Hibernate全自动需要hql语句。

2、iBatis半自动自己写sql语句,可操作性强,小巧。

3、EclipseLink一个可是扩大的支持JPA的ORM框架,提供强劲的休息存功能,缓存支持集群。

4、Apache OJB等等。

5、在Python中最闻名的ORM框架是SQLAlchemy。

总结

blocking和non-blocking的区别

调用blocking IO会一直block,直到对应之过程操作完。而non-blocking
IO在kernel还当备选数据的情下便会这回到。

synchronous IO和asynchronous IO的区别

在验证synchronous IO和asynchronous
IO的界别前,需要先让有彼此的概念。POSIX的概念:

synchronous IO会导致请求进程被堵塞,直到该输I/O操作完。

asynchronous IO不见面促成请求进程被卡住。

二者的分就在于synchronous IO做”IO
operation”的早晚会将process阻塞。按照这个定义之前所陈述之blocking
IO、non-blocking IO、IO multiplexing都属于synchronous IO。

有人以为non-blocking
IO并无被block,这里是非常容易误解的地方。定义着所倚的”IO
operation”是凭借真实的IO操作,就是例证中之recvfrom这个system
call。non-blocking IO以履recvfrom这个system
call的时段,如果kernel的数量没有备选好,这时候不见面block进程。但是当kernel中数据准备好的当儿,recvfrom会将数据由kernel拷贝到用户内存中,这个时段经过是被block了,这段时光内经过是被block的。

而asynchronous
IO则无等同,当进程发起IO操作之后,就一直回重新为不理睬了,直到kernel发送一个信号,告诉进程说IO完成。在马上所有经过遭到经过完全无被block。

各个IO model的比较而下图:

语言 8

经者的图片可以窥见non-blocking IO和asynchronous
IO的分还是很明白的。在non-blocking
IO中,虽然过程大部分时间都非会见叫block,但是其依旧要求进程积极的check,并且当数准备得后,也急需经过积极的再次调用recvfrom来讲数据拷贝到用户内存。而asynchronous
IO则统统两样,它就如是用户进程将通IO操作交给了别人(kernel)完成,然后kernel做截止后发信号通知。在此期间用户进程不待去检查IO操作的状态,也非需积极的失去拷贝数据。

SQLAlchemy安装

SQLAlchemy的意是,SQL数据库的量级和性重要于对象集合,而目标集合的空洞又要和表和行。

语言 9

Dialect用于与数据API进行交流,根据配置文件之不比调用不同的数据库API,从而实现对数据库的操作。

  1. MySQL-Python

  2.     mysql+mysqldb://<user>:<password>@<host>[:<port>]/<dbname>

  1.  

  2. pymysql

  3.     mysql+pymysql://<username>:<password>@<host>/<dbname>[?<options>]

  1.  

  2. MySQL-Connector

  3.     mysql+mysqlconnector://<user>:<password>@<host>[:<port>]/<dbname>

  1.  

  2. cx_Oracle

  3.     oracle+cx_oracle://user:pass@host:port/dbname[?key=value&key=value…]

  1.  

  2. 重新多详见:http://docs.sqlalchemy.org/en/latest/dialects/index.html

安装sqlalchemy

  1. pip3 install sqlalchemy

I/O多路复用select、poll、epoll详解

select、poll、epoll都是IO多路复用的体制。I/O多路复用就是经一样栽机制,一个经过可以监视多个描述符,一旦有描述符就绪(一般是朗诵就绪或者写就绪),能够通知顺序开展对应的读写操作。但select、poll、epoll本质上都是同步I/O,因为他俩还亟待在读写事件就是绪后自己承受进行读写,也就是说这个读写过程是死的,而异步I/O则无需好背进行读写,异步I/O的实现会晤承受把数量由根本拷贝到用户空间。

select

  1. select(rlist,wlist,xlist,timeout=None)

select函数监视的公文讲述符分3类,分别是writefds、readfds和execptfds。调用后select函数会阻塞,直到发生叙符就绪(有数量可读、可写或有except)或者逾期(timeout指定等待时,如果就回设为null即可)函数返回。当select函数返回后,可以由此遍历fdset,来找到就绪的讲述吻合。

select目前几乎在所有的平台上支持,其良好跨平台支撑啊是其的一个独到之处。select的一个毛病在于单个进程会监视的文书讲述称的多寡是不过可怜范围,在Linux上一般为1024,可以通过修改宏定义甚至还编译内核的艺术提升这同样限,但是这么吧会见造成效率的下挫。

poll

  1. int
    poll(struct pollfd
    *fds,unsigned,int nfds,int timeout)

select使用了三个各类图来表示三只fdset的主意,poll使用一个pollfd的指针实现。

  1. struct
    pollfd{

  2.     int fd; # 文件讲述符

  3.     short events; # 请求

  4.     short revents; # 响应

  5. }

pollfd结构包含了一旦监视的event和产生的event,不再利用select”参数-值”传递的方式。同时pollfd并没最老数目限制(但是多少过多后性能也是会见跌)。和select函数一样,poll返回后,需要轮询pollfd来收获就绪的描述称。

起点可以视,select和poll都亟需在返回后经过遍历文件讲述符来获取已经就绪的socket。事实上,同时连接的雅量客户端在平等随时或者不过出深少之处就绪状态,因此趁监视的叙述符数量的增进,其效率为会见线性下降。

epoll

epoll是当2.6基础中提出的,是事先的select和poll的增长版。相对于select和poll来说,epoll更加灵敏,没有描述符限制。epoll使用一个文件讲述符管理多只描述符,将用户关系的公文讲述称的事件存放到根本的一个风波表中,这样以用户空间以及水源空间的copy只需要一次于。

epoll操作过程需要三独接口。

  1. int
    epoll_create(int size); #
    创建一个epoll的句柄,size用来报告本监听的数目

  2. int
    epoll_ctl(int epfd,int op,int fd,struct epoll_event *event);

  3. int
    epoll_wait(int epfd,struct epoll_event * events,int maxevents,int timeout);

int epoll_create(int size);

缔造一个epoll的句柄,size用来喻本监听的数据,这个参数不同为select()中之第一只参数,给出尽可怜监听的fd+1的值,参数size并无是限量了epoll所能够监听的讲述称最特别个数,只是对内核初始分配内部数据结构的一个提议。

当创建好epoll句子柄后,它就是见面占一个fd值,在linux下要翻开/proc/进程id/fd/,是能见到这fd的,所以于用完epoll后,必须调用close()关闭,否则可能引致fd被耗尽。

int epoll_ctl(int epfd,int op,int fd,struct epoll_event *event);

函数是本着点名描述符fd执行op操作。

epfd:epoll_create()的回到值。

op:op操作,用三个宏来表示,添加EPOLL_CTL_ADD,删除EPOLL_CTL_DEL,修改EPOLL_CTL_MOD。分别长、删除和改动对fd的监听事件。

fd:需要监听的fd(文件讲述称)。

epoll_event:内核需要监听的对象。

int epoll_wait(int epfd,struct epoll_event * events,int maxevents,int
timeout);

等候epfd上之io事件,最多返回maxevents个事件。

参数events用来起基础得到事件的集结,maxevents告之本是events有多好,这个maxevents的价未克凌驾创建epoll_create()时之size,参数timeout是晚点时间(毫秒,0会立即赶回,-1以不确定)。该函数回需要处理的波数量,如归回0表示都过。

SQLAlchemy基本使用

开创一个发明。

SQL实现:

  1. CREATE TABLE USER(

  2.    ID INTEGER NOT NULL AUTO_INCREMENT,

  1.    NAME VARCHAR(32),

  2.    PASSWORD VARCHAR(64),

  3.    PRIMARY KET (ID)

  4. )

ORM实现:

  1. __author__ = ‘Golden’

  2. #!/usr/bin/env python3

  3. # -*- coding:utf-8 -*-

  4.  

  5. import sqlalchemy

  6.  

  7. from sqlalchemy import create_engine

  1. from sqlalchemy.ext.declarative import
    declarative_base

  2. from sqlalchemy import
    Column,Integer,String

  3.  

  4. # echo=True打印信息

  5. engine = create_engine(“mysql+pymysql://root:123456@192.168.31.134/test_db”,

  1.                        encoding=’utf-8′,echo=True)
  1.  

  2. # 生成orm基类

  3. Base = declarative_base()

  4.  

  5. class
    User(Base):

  6.     # 表名

  7.     __tablename__ = ‘USER’

  8.     # 定义字段ID,并设置也主键

  9.     ID =
    Column(Integer,primary_key=True)

  10.     NAME = Column(String(32))

  11.     PASSWORD = Column(String(64))

  1. # 创建表结构

  2. Base.metadata.create_all(engine)

除此之外上面的创建表之外,还有平等种创建表的计。

  1. __author__ = ‘Golden’

  2. #!/usr/bin/env python3

  3. # -*- coding:utf-8 -*-

  4.  

  5. import sqlalchemy

  6.  

  7. from sqlalchemy import
    create_engine,Table,MetaData,Column,Integer,String,ForeignKey

  1. from sqlalchemy.orm import mapper
  1.  

  2. engine = create_engine(“mysql+pymysql://root:123456@192.168.31.134/test_db”,

  1.                        encoding=’utf-8′,echo=True)
  1. metadata = MetaData()

  2.  

  3. user = Table(‘USER_TABLE’,metadata,

  1.              Column(‘ID’,Integer,primary_key=True),
  1.              Column(‘NAME’,String(50)),
  1.              Column(‘FULLNAME’,String(50)),
  1.              Column(‘PASSWORD’,String(12))
  1.              )

  2.  

  3.  

  4. class
    User(object):

  5.     def
    __init__(self,name,fullname,password):

  6.         self.name = name

  7.         self.fullname = fullname

  1.         self.password = password
  1.  

  2. mapper(User,user)

  3.  

  4. # 创建表结构

  5. metadata.create_all(engine)

率先种艺术开创的表是基于第二栽方式的重复封闭装。

采取ORM创建同长条数。

  1. __author__ = ‘Golden’

  2. #!/usr/bin/env python3

  3. # -*- coding:utf-8 -*-

  4.  

  5. import sqlalchemy

  6. from sqlalchemy import
    create_engine,Column,Integer,String

  7. from sqlalchemy.orm import sessionmaker

  1. from sqlalchemy.ext.declarative import
    declarative_base

  2.  

  3. engine = create_engine(“mysql+pymysql://root:123456@192.168.31.134/test_db”,

  1.                        encoding=’utf-8′,echo=True)
  1. Base = declarative_base()

  2.  

  3. class
    User(Base):

  4.     __tablename__ = ‘USER’

  5.     ID =
    Column(Integer,primary_key=True)

  6.     NAME = Column(String(32))

  7.     PASSWORD = Column(String(64))

  1.  

  2. Base.metadata.create_all(engine)

  1. # 创建和数据库的会话session class,注意这里归给session的凡一个class,不是实例
  1. Session_class =
    sessionmaker(bind=engine)

  2. # 生成session实例

  3. Session = Session_class()

  4. # 生成如创造的数据对象

  5. user_obj = User(NAME=”Golden”,PASSWORD=”123456″)

  6. # 此时还无创建对象

  7. print(user_obj.NAME,user_obj.ID)

  1. # 把用创造的数码对象上加到session
  1. Session.add(user_obj)

  2. # 此时还并未创建对象

  3. print(user_obj.NAME,user_obj.ID)

  1. # 创建数量,统一提交

  2. Session.commit()

select、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

以至于Linux
2.6才面世了是因为基本直接支持之实现方式,那就是是epoll,它几乎所有了事先所说之满贯优点,被公认为Linux
2.6下性能最好好之多路I/O就绪通知方法。

epoll可以又支持水平触发和边缘触发(Edge
Triggered,只告诉进程哪些文件讲述吻合刚刚成就绪状态,它只有说一样整整,如果我们没采取行动,那么她就无见面重新语,这种办法叫边缘触发),理论及边缘触发的习性要再次强有,但代码实现相当复杂。

epoll同只有报告那些就绪的文本描述符,而且当我们调用epoll_wait()获得妥善文件讲述符时,返回的无是实际的描述符,而是一个表示就绪描述符数量的价值,你仅仅需要去epoll指定的一个数组中各个获得相应数额之公文讲述符即可,这里呢动了内存映射(mmap)技术,这样便彻底省掉了这些文件讲述吻合在系统调用时复制的支出。

另外一个实质之改善在于epoll采用基于事件的妥善通知方式。在select/poll中,进程只有以调用一定之方法后,内核才对具有监视的公文讲述吻合进行描述,而epoll事先经过epoll_ctl()来注册一个文书描述符,一旦基于某个文件讲述符就绪时,内核会采用类似callback的回调机制,迅速激活这个文件描述符,当进程调用epoll_wait()时便抱通知。

查询、修改

  1. __author__ = ‘Golden’

  2. #!/usr/bin/env python3

  3. # -*- coding:utf-8 -*-

  4.  

  5. import sqlalchemy

  6. from sqlalchemy import
    create_engine,Column,Integer,String

  7. from sqlalchemy.ext.declarative import
    declarative_base

  8. from sqlalchemy.orm import sessionmaker

  1. engine = create_engine(“mysql+pymysql://root:123456@192.168.31.134/test_db”,
  1.                        encoding=’utf-8′,echo=False)
  1. Base = declarative_base()

  2. class
    User(Base):

  3.     __tablename__ = ‘USER’

  4.     ID =
    Column(Integer,primary_key=True)

  5.     NAME = Column(String(32))

  6.     PASSWORD = Column(String(64))

  1.  

  2.     def __repr__(self):

  3.         return “<NAME : %s | PASSWORD : %s>”
    %(self.NAME,self.PASSWORD)

  4.  

  5. Session_class =
    sessionmaker(bind=engine)

  6. Session = Session_class()

  7. # first 查出NAME=’Golden’的首先单

  1. my_user =
    Session.query(User).filter_by(NAME=’Golden’).first()

  2. print(my_user.NAME,my_user.PASSWORD)

  1. # NAME=’Golden’

  2. data =
    Session.query(User).filter_by(NAME=’Golden’).all()

  3. print(data[0].PASSWORD)

  4. #all 查出有

  5. data_2 =
    Session.query(User).filter_by().all()

  6. print(data_2)

  7. data_3 =
    Session.query(User).filter(User.ID == 1).all()

  8. print(data_3)

  9. data_4 =
    Session.query(User).filter_by(ID=1).all()

  10. print(data_4)

  11. # 多准查询

  12. data_5 =
    Session.query(User).filter(User.ID > 1).filter(User.ID <
    4).all()

  13. print(data_5)

  14. data_6 =
    Session.query(User).filter().first()

  15. print(data_6)

  16. # 修改

  17. data_6.NAME = ‘zhangsan’

  18. data_6.PASSWORD = ‘110’

  19. # 提交

  20. Session.commit()

Python select

Python的select()方法直接调用操作系统的IO接口,它监控sockets、open
files、pipes(所有带fileno()方法的文本句柄)何时变成readable和writeable或者通信错误,select()使得以监控多只连续变得简单,并且这正如写一个抬高循环来等待和监理多客户端连接要快,因为select直接通过操作系统提供的C的网络接口进行操作,而非是经过Python的解释器。

注意:Using Python’s file objects with select() works for Unix, but is
not supported under Windows.

select_socket_server

  1. __author__ = ‘Golden’

  2. #!/usr/bin/env python3

  3. # -*- coding:utf-8 -*-

  4.  

  5. import select,socket,sys,queue

  6.  

  7. server = socket.socket()

  8. server.setblocking(0)

  9. server_addr = (‘localhost’,6969)

  1. print(‘starting up on %s port
    %s’%server_addr)

  2. server.bind(server_addr)

  3. server.listen(5)

  4.  

  5. # 监测自己,因为server本身也是单fd

  1. inputs = [server,]

  2. outputs = []

  3. message_queues = {}

  4. while
    True:

  5.     print(‘waiting for next event…’)

  6.     #
    如果没有其余fd就绪,程序会一直不通在此间

  7.     readable,writeable,exeptional =
    select.select(inputs,outputs,inputs)

  8.     # 每个s就是一个socket

  9.     for s in
    readable:

  10.         #
    上面server自己呢作为一个fd放在了inputs列表里,传为了select,如果s是server代表server这个fd就绪了,即新的连上

  1.         if s is
    server:

  2.             # 接收这连接

  3.             conn,client_addr =
    s.accept()

  4.             print(‘new connection from’,client_addr)

  1.             conn.setblocking(0)

  2.             “””

  3.             为了不打断整个程序,不会见即刻在此开收客户端发来之数码,把它放inputs里,下同样坏loop时,

  1.             这个新连就会见叫交付select去监听,如果此连续的客户端发来了多少,那么是连续的fd在server端就见面化就绪的,
  1.             select就见面将这数额返回到readable列表里,然后便可loop
    readable列表,取出这连续,开始接收数据

  2.             “””

  3.             inputs.append(conn)

  4.             #
    接收及客户端的数据后,不立即返,暂存在排里,以后发送

  5.             message_queues[conn] =
    queue.Queue()

  6.         #
    s不是server那即便偏偏见面是一个同客户端起之连日的fd

  7.         else:

  8.             # 接收客户端的数据

  9.             data = s.recv(1024)

  10.             if data:

  11.                 print(‘收到来自【%s】的数目:’%s.getpeername()[0],data)

  1.                 #
    收到的数额先放入queue里,一会回去给客户端

  2.                 message_queues[s].put(data)

  1.                 if s not in outputs:

  2.                     #
    为了不影响处理和任何客户端的接连,这里不及时回去数据为客户端

  3.                     outputs.append(s)

  1.             #
    如果得了不至data,代表客户端都断开

  2.             else:

  3.                 print(‘客户端已断开…’,s)

  1.                 if s in
    outputs:

  2.                     # 清理都断开的连续

  1.                     outputs.remove(s)
  1.                 # 清理已断开的连
  1.                 inputs.remove(s)
  1.                 # 清理都断开的连日
  1.                 del
    message_queues[s]

  2.     for s in
    writeable:

  3.         try:

  4.             next_msg =
    message_queues[s].get_nowait()

  5.         except queue.Empty:

  6.             print(‘client
    [%s]’%s.getpeername()[0],’queue is empty…’)

  7.             outputs.remove(s)

  8.         else:

  9.             print(‘sending msg to
    [%s]’%s.getpeername()[0],next_msg)

  10.             s.send(next_msg.upper())

  1.     for s in
    exeptional:

  2.         print(‘handling exception for’,s.getpeername())

  3.         inputs.remove(s)

  4.         if s in
    outputs:

  5.             outputs.remove(s)

  6.         s.close()

  7.         del message_queues[s]

select_socket_client

  1. __author__ = ‘Golden’

  2. #!/usr/bin/env python3

  3. # -*- coding:utf-8 -*-

  4.  

  5. import socket,sys

  6.  

  7. messages = [b’This is the message.’,

  8.             b’It will be sent’,

  9.             b’in parts.’,

  10.             ]

  11.  

  12. server_address = (‘localhost’,6969)

  1. # 创建一个TCP/IP连接

  2. socks =
    [socket.socket(socket.AF_INET,socket.SOCK_STREAM),

  3.          socket.socket(socket.AF_INET,socket.SOCK_STREAM),

  1.          socket.socket(socket.AF_INET,socket.SOCK_STREAM),]
  1. print(‘connecting to %s port
    %s’%server_address)

  2. for s
    in socks:

  3.     s.connect(server_address)

  4.  

  5. for
    message in messages:

  6.     # 发送数据

  7.     for s in
    socks:

  8.         print(‘%s:sending “%s”‘%(s.getsockname(),message))

  1.         s.send(message)

  2.     # 接收数据

  3.     for s in
    socks:

  4.         data = s.recv(1024)

  5.         print(‘%s:received “%s”‘%(s.getsockname(),data))

  6.         if not data:

  7.             print(sys.stderr,’closing
    socket’,s.getsockname())

回滚

  1. __author__ = ‘Golden’

  2. #!/usr/bin/env python3

  3. # -*- coding:utf-8 -*-

  4.  

  5. import sqlalchemy

  6. from sqlalchemy import
    create_engine,Column,Integer,String

  7. from sqlalchemy.ext.declarative import
    declarative_base

  8. from sqlalchemy.orm import sessionmaker

  1.  

  2. engine = create_engine(“mysql+pymysql://root:123456@192.168.31.134/test_db”,

  1.                        encoding=’utf-8′,echo=False)
  1. Base = declarative_base()

  2.  

  3. class
    User(Base):

  4.     __tablename__ = ‘USER’

  5.     ID =
    Column(Integer,primary_key=True)

  6.     NAME = Column(String(32))

  7.     PASSWORD = Column(String(64))

  1.  

  2.     def __repr__(self):

  3.         return “<ID : %s | NAME : %s | PASSWORD :
    %s>” %(self.ID,self.NAME,self.PASSWORD)

  4.  

  5. Session_class =
    sessionmaker(bind=engine)

  6. Session = Session_class()

  7.  

  8. my_user =
    Session.query(User).filter_by(ID=1).first()

  9. my_user.NAME = ‘Mark’

  10.  

  11. fake_user =
    User(NAME=’Merry’,PASSWORD=’999999′)

  12. Session.add(fake_user)

  13. # 查看刚刚添加和改动的数据

  14. print(Session.query(User).filter(User.NAME.in_([‘Merry’,’Mark’])).all())

  1. # rollback

  2. Session.rollback()

  3. # 再次查询

  4. print(Session.query(User).filter(User.NAME.in_([‘Merry’,’Mark’])).all())

selectors

selectors模块可实现IO多路复用,它兼具根据平台选出最佳的IO多路机制,例如当windows上默认是select模式,而于linux上默认是epoll。常分为三栽模式select、poll和epoll。

selector_socket_server:

  1. __author__ = ‘Golden’

  2. #!/usr/bin/env python3

  3. # -*- coding:utf-8 -*-

  4.  

  5. import selectors,socket

  6.  

  7. sel = selectors.DefaultSelector()

  1.  

  2. def accept(sock,mask):

  3.     conn,addr = sock.accept()

  4.     print(‘accrpted’,conn,’form’,addr)

  1.     conn.setblocking(0)

  2.     sel.register(conn,selectors.EVENT_READ,read)

  1.  

  2. def read(conn,mask):

  3.     data = conn.recv(1024)

  4.     if
    data:

  5.         print(‘echoing’,repr(data),’to’,conn)

  1.         conn.send(data)

  2.     else:

  3.         print(‘closing’,conn)

  4.         sel.unregister(conn)

  5.         conn.close()

  6.  

  7. sock = socket.socket()

  8. sock.bind((‘localhost’,6969))

  9. sock.listen(100)

  10. sock.setblocking(0)

  11. sel.register(sock,selectors.EVENT_READ,accept)

  1.  

  2. while
    True:

  3.     events = sel.select()

  4.     for key,mask in events:

  5.         callback = key.data

  6.         callback(key.fileobj,mask)

 

 

 

统计和分组

  1. __author__ = ‘Golden’

  2. #!/usr/bin/env python3

  3. # -*- coding:utf-8 -*-

  4.  

  5. import sqlalchemy

  6. from sqlalchemy import
    create_engine,Column,Integer,String,func

  7. from sqlalchemy.ext.declarative import
    declarative_base

  8. from sqlalchemy.orm import sessionmaker

  1.  

  2. engine = create_engine(“mysql+pymysql://root:123456@192.168.31.134/test_db”,

  1.                        encoding=’utf-8′,echo=False)
  1.  

  2. Base = declarative_base()

  3.  

  4.  

  5. class
    User(Base):

  6.     __tablename__ = ‘USER’

  7.     ID =
    Column(Integer,primary_key=True)

  8.     NAME = Column(String(32))

  9.     PASSWORD = Column(String(64))

  1.  

  2.     def __repr__(self):

  3.         return “<ID : %s | NAME : %s | PASSWORD :
    %s>” %(self.ID,self.NAME,self.PASSWORD)

  4.  

  5. Session_class =
    sessionmaker(bind=engine)

  6. Session = Session_class()

  7. # 统计ha开头的NAME个数

  8. print(Session.query(User).filter(User.NAME.like(“ha%”)).count())

  9. # 分组

  10. print(Session.query(User.NAME,func.count(User.NAME)).group_by(User.NAME).all())

连表

  1. __author__ = ‘Golden’

  2. #!/usr/bin/env python3

  3. # -*- coding:utf-8 -*-

  4.  

  5. import sqlalchemy

  6. from sqlalchemy import
    create_engine,Column,Integer,String,DATE

  7. from sqlalchemy.orm import sessionmaker

  1. from sqlalchemy.ext.declarative import
    declarative_base

  2.  

  3. engine = create_engine(“mysql+pymysql://root:123456@192.168.31.134/test_db”,

  1.                        encoding=’utf-8′,echo=True)
  1. Base = declarative_base()

  2.  

  3. class
    User(Base):

  4.     __tablename__ = ‘USER’

  5.     ID =
    Column(Integer,primary_key=True)

  6.     NAME = Column(String(32))

  7.     PASSWORD = Column(String(64))

  1.  

  2.     def __repr__(self):

  3.         return “<ID :%s | NAME : %s | PASSWORD :
    %s>” %(self.ID,self.NAME,self.PASSWORD)

  4.  

  5.  

  6. class
    Student(Base):

  7.     __tablename__ = ‘STUDENT’

  1.     ID =
    Column(Integer,primary_key=True)

  2.     NAME =
    Column(String(32),nullable=False)

  3.     REGISTER_DATE =
    Column(DATE,nullable=False)

  4.     GENDER =
    Column(String(32),nullable=False)

  5.  

  6.     def __repr__(self):

  7.         return “<NAME : %s | PASSWORD : %s>”
    %(self.NAME,self.REGISTER_DATE)

  8.  

  9. Base.metadata.create_all(engine)

  1. Session_class =
    sessionmaker(bind=engine)

  2. Session = Session_class()

  3.  

  4. # 外联

  5. print(Session.query(User,Student).filter(User.ID
    == Student.ID).all())

  6. # 两独说明得有外键关联才会运用 Can’t
    find any foreign key relationships between ‘A’ and ‘B’

  7. print(Session.query(User).join(Student).all())

  1. print(Session.query(User).join(Student,isouter=True).all())
  1. Session.commit()

贯彻两只说明底外键关联

  1. __author__ = ‘Golden’

  2. #!/usr/bin/env python3

  3. # -*- coding:utf-8 -*-

  4. import sqlalchemy

  5. from sqlalchemy import
    create_engine,Column,Integer,String,DATE,ForeignKey

  6. from sqlalchemy.orm import
    sessionmaker,relationship

  7. from sqlalchemy.ext.declarative import
    declarative_base

  8.  

  9. engine = create_engine(“mysql+pymysql://root:123456@192.168.31.134/test_db”,

  1.                        encoding=’utf-8′,echo=False)
  1. Base = declarative_base()

  2.  

  3. class
    Student(Base):

  4.     __tablename__ = ‘student’

  1.     id =
    Column(Integer,primary_key=True)

  2.     name =
    Column(String(32),nullable=False)

  3.     register_date =
    Column(DATE,nullable=False)

  4.  

  5.     def __repr__(self):

  6.         return “<name : %s | register_date :
    %s>”%(self.name,self.register_date)

  7.  

  8.  

  9. class
    StudyRecord(Base):

  10.     __tablename__ = “study_record”

  11.     id =
    Column(Integer,primary_key=True)

  12.     day =
    Column(Integer,nullable=False)

  13.     status =
    Column(String(32),nullable=False)

  14.     # 创建外键

  15.     stu_id =
    Column(Integer,ForeignKey(“student.id”))

  16.     #

  17.     student = relationship(“Student”,backref=”my_study_record”)

  18.  

  19.     def __repr__(self):

  20.        return “<%s day :%s | status :
    %s>”%(self.student.name,self.day,self.status)

  21. # 创建表结构

  22. Base.metadata.create_all(engine)

  1. # 创建和数据库的会话session

  2. Session_class =
    sessionmaker(bind=engine)

  3. # 生成session实例

  4. session = Session_class()

  5.  

  6. “””添加数据

  7. s1 = Student(name=”Golden”,register_date=”2017-12-24″)

  8. s2 = Student(name=”Jack”,register_date=”2017-11-13″)

  9. s3 = Student(name=”Rain”,register_date=”2017-10-11″)

  10. s4 = Student(name=”Eric”,register_date=”2017-07-07″)

  11.  

  12. study_obj1 =
    StudyRecord(day=1,status=”Yes”,stu_id=1)

  13. study_obj2 =
    StudyRecord(day=2,status=”No”,stu_id=1)

  14. study_obj3 =
    StudyRecord(day=3,status=”Yes”,stu_id=1)

  15. study_obj4 =
    StudyRecord(day=1,status=”Yes”,stu_id=2)

  16.  

  17. # 一次性全部开立

  18. session.add_all([s1,s2,s3,s4,study_obj1,study_obj2,study_obj3,study_obj4])

  1. “””

  2. stu_obj =
    session.query(Student).filter(Student.name == “Golden”).first()

  3. print(stu_obj)

  4. print(stu_obj.my_study_record)

  1. # 提交

  2. session.commit()

差不多外键关联

创立包含多外键的申结构。

  1. __author__ = ‘Golden’

  2. #!/usr/bin/env python3

  3. # -*- coding:utf-8 -*-

  4.  

  5. from sqlalchemy.orm import relationship

  1. from sqlalchemy import
    create_engine,Column,Integer,String,DATE,ForeignKey

  2. from sqlalchemy.ext.declarative import
    declarative_base

  3.  

  4. Base = declarative_base()

  5.  

  6. class
    Customer(Base):

  7.     __tablename__ = ‘customer’

  1.     id =
    Column(Integer,primary_key=True)

  2.     name = Column(String(64))

  3.  

  4.     billing_address_id =
    Column(Integer,ForeignKey(“address.id”))

  5.     shipping_address_id =
    Column(Integer,ForeignKey(“address.id”))

  6.  

  7.     billing_address =
    relationship(“Address”,foreign_keys=[billing_address_id])

  1.     shipping_address =
    relationship(“Address”,foreign_keys=[shipping_address_id])
  1.  

  2. class
    Address(Base):

  3.     __tablename__ = ‘address’

  1.     id =
    Column(Integer,primary_key=True)

  2.     street = Column(String(64))

  3.     city = Column(String(64))

  4.     state = Column(String(64))

  5.  

  6.     def __repr__(self):

  7.         return self.street

  8.  

  9. engine = create_engine(“mysql+pymysql://root:123456@192.168.31.134/test_db”,

  1.                        encoding=’utf-8′,echo=False)
  1. # 创建表结构

  2. # Base.metadata.create_all(engine)

安插数据以及询问。

  1. __author__ = ‘Golden’

  2. #!/usr/bin/env python3

  3. # -*- coding:utf-8 -*-

  4.  

  5. import os,sys

  6. path =
    os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

  1. sys.path.append(path)

  2. from day11 import orm_many_fk

  3. from sqlalchemy.orm import sessionmaker

  1.  

  2. Session_class =
    sessionmaker(bind=orm_many_fk.engine)

  3. session = Session_class()

  4.  

  5. # 创建数据

  6. # addr1 =
    orm_many_fk.Address(street=”zhongshanroad”,city=”qiaokou”,state=’hankou’)

  7. # addr2 =
    orm_many_fk.Address(street=”dongyiroad”,city=”hongshan”,state=”wuchang”)

  8. # addr3 =
    orm_many_fk.Address(street=”guangshanroad”,city=”gaoxin”,state=”guanggu”)

  9. #

  10. #
    session.add_all([addr1,addr2,addr3])

  11. # c1 =
    orm_many_fk.Customer(name=”Golden”,billing_address=addr1,shipping_address=addr3)

  1. # c2 =
    orm_many_fk.Customer(name=”Jack”,billing_address=addr2,shipping_address=addr2)
  1. #

  2. # session.add_all([c1,c2])

  3.  

  4. # 查询数据

  5. obj =
    session.query(orm_many_fk.Customer).filter(orm_many_fk.Customer.name==”Golden”).first()

  6. print(obj.name,obj.billing_address,obj.shipping_address)

  1.  

  2. session.commit()

大多对大多涉及

始建多针对性多关联表

  1. __author__ = ‘Golden’

  2. #!/usr/bin/env python3

  3. # -*- coding:utf-8 -*-

  4.  

  5. from sqlalchemy import
    Table,Column,Integer,String,DATE,ForeignKey,create_engine

  6. from sqlalchemy.orm import
    relationship,sessionmaker

  7. from sqlalchemy.ext.declarative import
    declarative_base

  8.  

  9. engine = create_engine(“mysql+pymysql://root:123456@192.168.31.134/test_db”,

  1.                        encoding=’utf-8′,echo=False)
  1.  

  2. Base = declarative_base()

  3.  

  4. book_m2m_author =
    Table(‘book_m2m_author’,Base.metadata,

  5.                         Column(‘book_id’,Integer,ForeignKey(‘books.id’)),

  1.                         Column(‘author_id’,Integer,ForeignKey(‘authors.id’)))
  1.  

  2. class
    Book(Base):

  3.     __tablename__ = ‘books’

  4.     id =
    Column(Integer,primary_key=True)

  5.     name = Column(String(64))

  6.     pub_date = Column(DATE)

  7.     authors =
    relationship(‘Author’,secondary=book_m2m_author,backref=’books’)

  1.  

  2.     def __repr__(self):

  3.         return self.name

  4.  

  5.  

  6. class
    Author(Base):

  7.     __tablename__ = ‘authors’

  1.     id =
    Column(Integer,primary_key=True)

  2.     name = Column(String(32))

  3.  

  4.     def __repr__(self):

  5.         return self.name

  6.  

  7. Base.metadata.create_all(engine)

  1. Session_class =
    sessionmaker(bind=engine)

  2. session = Session_class()

 

插数据与询问

  1. __author__ = ‘Golden’

  2. #!/usr/bin/env python3

  3. # -*- coding:utf-8 -*-

  4.  

  5. import os,sys

  6. path =
    os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

  1. sys.path.append(path)

  2. from day11 import orm_m2m

  3. from sqlalchemy.orm import sessionmaker

  1.  

  2. Session_class =
    sessionmaker(bind=orm_m2m.engine)

  3. session = Session_class()

  4.  

  5. # 创建数据

  6. # b1 = orm_m2m.Book(name=”Python”)

  7. # b2 = orm_m2m.Book(name=”JAVA”)

  8. # b3 = orm_m2m.Book(name=”C++”)

  9. # b4 = orm_m2m.Book(name=”c#”)

  10. #

  11. # a1 = orm_m2m.Author(name=”Golden”)

  12. # a2 = orm_m2m.Author(name=”Jack”)

  13. # a3 = orm_m2m.Author(name=”Rain”)

  14. #

  15. # b1.authors = [a1,a2]

  16. # b2.authors = [a1,a2,a3]

  17. #

  18. #
    session.add_all([b1,b2,b3,b4,a1,a2,a3])

  19. # session.commit()

  20.  

  21. print(“通过书表查询关联的作者”.center(50,”*”))

  22. book_obj =
    session.query(orm_m2m.Book).filter_by(name=”JAVA”).first()

  23. print(book_obj.name,book_obj.authors)

  1. print(“通过作者表查询关联的修”.center(50,”*”))

  2. author_obj =
    session.query(orm_m2m.Author).filter_by(name=”Golden”).first()

  3. print(author_obj.name,author_obj.books)

  1.  

  2. #
    多对几近去,删除数据经常毫不管book_m2m_author,sqlalchemy会自动删除相应的多少

  1. # 通过写删除作者

  2. book_obj.authors.remove(author_obj)

  1.  

  2. # 直接去作者

  3. author_obj2 =
    session.query(orm_m2m.Author).filter_by(name=”Jack”).first()

  4. session.delete(author_obj2)

  5. session.commit()

 

支持中文

sqlalchemy设置编码字符集一定要是以数据库访问的URL上加charset=utf8,否则数据库的连日就非是utf8的编码格式。

  1. # 支持中文

  2. engine = create_engine(“mysql+pymysql://root:123456@192.168.31.134/test_db?charset=utf8”,echo=True)

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图