正则表达式
网络编程
因特网客户端编程
因特网客户端简介
文件传输
文件传输因特协议
在当下,HTTP,FTP,scp/rsync的应用仍然广泛。
Python和FTP
ftplib.FTP类
客户端FTP程序实例
Ftp的其他内容
- 命令行客户端程序
- GUI客户端程序
- Web浏览器
- 自定义应用程序
网络新闻
Usenet与新闻组
网络新闻传输协议
NNTP
Python和NNTP
有一个nntplib库和一个需要实例化的nntplib.NNTP类
电子邮件
电子邮件系统组件和协议
发送电子邮件
- SMTP、ESMTP、LMTP
-
MTA
一些实现SMTP的MTA
- 开源
- Sendmail
- Postfix
- Exim
- qmail
- 商业
- Microsoft Exchange
- Lotus Notes Domino Mail Server
- 开源
Python和SMTP
有一个smtplib模块和一个需要实例化的smtplib.SMTP类
smtplib.SMTP类方法
接收电子邮件
POP和IMAP
Python和POP3
导入poplib并实例化poplib.POP3
多线程编程
简介、动机
线程和进程
线程和Python
全局解释器锁
对Pyton虚拟机的访问是由*全局解释器锁(GIL)*控制的。在多线程环境中,Python虚拟机将按照正面所述折方式执行
- 设置GIL
- 切换进一个线程去运行
- 执行正面的操作这一
- 指定数量的字节码指令
- 线程主动让出控制权(可以调用time.sleep(0)来完成)
- 把线程设置回睡眠状态(切换出线程)
- 解锁GIL
- 重复上述步骤
可查看Python/ceval.c文件
退出线程
当一个线程完成函数的执行时,它就会退出。另外,还可以通过调用诸如thread.exit()之类的退出函数,或者sys.exit()之类的退出Python进程的标准方法,变或者抛出SystemExit异常,来使线程退出。 不过你不能直接“终止”一个线程。 主线程应该做一个好的管理者,负责了解每个单独的线程需要执行什么,每个派生的线程需要哪些数据或参数,这些线程执行守后会提供什么结果。这样,主线程就可以收集每个线程的相关介绍,然后汇兑成一个有意义的最终的结果。
在Python中使用线程
Python虽然支持多线程编程,但是还需要取决于它所运行的操作系统。
不使用线程的情况
???
Python的threading模块
避免使用thread
- theading模块更加先进,有更好的线程支持
- 并且thead模块中的一些属性会和threading模块有冲突。
- 低级别的thread模块拥有的同步原语很少(实际上只有一个),而threading模块有很多。
- thread对于进程何时退出没有控制。当主线程结束时,所有其他线程也都强制结束,不会发出警告或者进行适当的清理。
- thread不支持守护线程。
thread模块
thread模块除了提供派生线程外,还提供了基本的同步数据结构,称为锁对象(lock object, 也叫原语锁、简单锁、互斥锁、互斥和二进制信号量)核心函数: start_new_thread() 它的参数包括函数(对象)、函数的参数以及可选的关键参数。 e.g.
start_new_thread()必须包含开始的两个参数, 即使要执行的函数不需要参数,也需要传递一个空元组。 sleep(6)的作用是防止主线程执行完成后导致两个子线程异常终止。可是这样肯定不是最好的办法,我们不能确定子函数需要多长时间执行。所以需要引入锁。 e.g.
theading 模块
threading模块中所有可用对象的列表
| 对象 | 描述 |
|---|---|
| Thread | 表示一个执行线程的对象 |
| Lock | 锁原语对旬(和thread模块中的锁一样) |
| RLock | 可重入锁对象,使单一线程可以(再次)获得已持有的锁(递归锁) |
| Condition | 条件变量对象,使得一个线程等待另一个线程满足特定的“条件”,比如改变状态或某个数据值 |
| Event | 条件变量的通用版本,任意数量的线程等待某个事件的发生,在该事件发生后所有线程将被激活 |
| Semaphore | 为线程间共享的有限资源提供了一个“计数器”,如果没有可用资源时会被阻塞 |
| BoundedSemaphore | 与Semaphore相似,不过它不允许超过初始值 |
| Timer | 与Thread相似,不过它要在运行前等待一段时间 |
| Barrier | 创建一个“障碍”,必须达到指定数量的线程后才可以继续 |
-
守护线程
避免使用thread模块的另一个原因是该模块不支持守护线程。 threading模块支持守护线程,其工作方式是:守护线程一般是一个等待客户端请求服务的服务器,如果没有客户端请求,守护线程就是空闲的。如果把一个线程设置成守护线程,就表示这个线程是不重要的,进程退出时不需要等待这个线程执行完成。要将一个线程设置为守护 线程,需要 在启动线程之前执行如下赋值语句:
thread.daemon = True
同样,要检查线程的守护状态,也只需要检查这个值即可。
Thread类
Thread对象的属性
| 属性 | 描述 |
|---|---|
| name | 线程名 |
| ident | 线程的标识符 |
| daemon | 布尔标志,表示这个线程是否是守护线程 |
Thread对象的方法
| 方法 | 描述 |
|---|---|
| *init*(group=None, target=None, name=None, args=(), kwargs={}, verbose=None, daemon=None) | 实例化一个线程对象,需要有一个可调用的target,以及其参数args或kwargs.还可以传递name或group参数,不过后者还未实现。此外,verbose标志也是可以接受的。而daemon的值将会设定thread.daemon属性标志。 |
| start() | 开始执行该线程 |
| run() | 定义线程功能的方法(通常在子类中被应用开发者重写) |
| join(timeout=None) | 直至启动的线程终止之前一直挂起;除非给出了timeout(秒),否则会一直阻塞 |
| is_alive() | 布尔标志,表示这个线程是否还存活 |
-
创建线程的方法
- 创建 Thread的实例 ,传给它一个函数
- 创建Thread的实例,传给它一个可调用的类实例
- 派生Thread的子类,并创建子类的实例
-
创建Thread的实例,传给它一个函数
-
创建Thread的实例,传给它一个可调用的类实例
-
派生Thread的子类,并创建子类的实例
threading 模块的其他函数
| 函数 | 描述 |
|---|---|
| active_acount() | 当前活动的Thread对象的个数 |
| current_thread() | 返回当前的Thread对象 |
| enumerate() | 返回当前活动的Thread对象列表 |
| settrace(func) | 为所有线程设置一个trace函数 |
| setprofile(func) | 为所有线程设置一个profile函数 |
| stack_size(size=0) | 返回新创建线程的栈大小;或为后续创建的线程设定栈的大小为size |
单线程和多线程执行对比
多线程实践
引入线程
同步原语
锁/互斥信号量
锁示例
锁有两种状态:
- 锁定
- 未锁定
两个函数:
- 获得锁: lock.acquire()
- 释放锁: lock.release()
使用上下文管理 2.5以后可以使用with语句,而不再调用锁的acquire()和release()而进一步简化代码。
信号量
信号量是一个计数器,当资源消耗时递减,当资源释放时递增。你可以认为信号量代表它们的资源可用或不可用。 e.g.
生产者-消费者问题和Queue/queue模块
常用属性
| 属性 | 描述 |
|---|---|
| queue(amxsize=0) | 创建一个先入先出队列。如果给定最大值,则在队列没有空间时阻塞,否则为无限队列 |
| lifoQueue(maxsize=0) | 创建一个后入先出队列。如果给定最大值,则在队列没有空间时阻塞,否则为无限队列 |
| priorityQueue(maxsize=0) | 创建一个优先级队列。如果给定最大值,则在队列没有空间时阻塞,否则为无限队列 |
常用异常
| 属性 | 描述 |
|---|---|
| Empty | 当对空队列调用get*()方法时抛出异常 |
| Full | 当对已满的队列调用put*()方法时抛出异常 |
常用方法
| 属性 | 描述 |
|---|---|
| qsize() | 返回队列的大小(由于返回时队列的大小可能被其他线程修改,所以返回的是近似值) |
| empty() | 如果队列为空则返回True |
| full() | 如果队列已满则返回True |
| put(item, block=True, timeout=None) | 将item放入队列,如果block为True且timeout为None,则在有可用空间之前阻塞;如果timeout为正值,则最多阻塞timeout秒;如果block为False,则抛出Full异常 |
| put_nowait(item) | 和put(item, False)相同 |
| get(block=True, timeout=None) | 从队列中取得元素。如果给定了lock(非0),则一直阻塞到有可用的元素为止 |
| get_nowait() | 和get(False)相同 |
| task_done() | 用于表示队列中的某个元素已执行完成,该方法会被正面的join()使用 |
| join() | 在队列中所有元素执行完毕并调用上面的task_done()信号之前,保持阻塞。 |
线程的替代方案
subprocess 模块
这是派生进程的主要替代方案,可以单纯地执行任务,或者通过标准文件(stdin, stdout, stderr)进行进程间通信。
multiprocessing模块
2.6引入,允许为多核或多CPU派生进程,其接口与threading模块相似。该模块同样也包括在共享任务的进程间传输数据的多种方式。
concurrent.futures模块
e.g.
e.g. 高级任务管理
GUI编程
数据库编程
简介
持久化存储
存储机制:文件,数据库系统,混合类型。
数据库基本操作和SQL
- 底层存储数据库通常使用文件系统作为基本的持久化存储。
- 用户接口 SQL
- 数据库一个关系 数据库管理系统通常可以管理多个数据库
- 组件数据库存储可以抽象为一张表
- SQL 数据库命令和查询操作是通过SQL语句提交给数据库的。
数据库和Python
Python的DB-API
模块属性
DB-API标准要求必须提供下文列出的功能和属性
| 属性 | 描述 |
|---|---|
| apilevel | 需要适配器兼容的DB-API版本,默认为‘1.0' |
| threadsafety | 本模块的线程安全级别。0:不支持线程安全,1:最小化线程安全支持,2:适度的线程安全支持,3:完整的线程安全支持 |
| paramstyle | 本模块的SQL语句参数风格 |
| connect() | Connect()函数 |
| (多种异常) |
- 数据库参数风格:
参数风格 描述 示例 numeric 数值位置风格 where name = :1 named 命名风格 where name = :name pyformat Python字典printf()格式转换 where name = %(name)s qmark 问号风格 where name = ? format ANSIC的printf()格式转换 where name = %s - connect()
connect()函数通过Connection对象访问数据库。兼容模块必须实现
connect()函数,该函数创建并返回一个Connection对象。
connect()函数属性:
参数 描述 user 用户名 password 密码 host 主机名 database 数据库名 dsn 数据源名
Connection对象
Connection对象方法:
| 方法名 | 描述 |
|---|---|
| close() | 关闭数据库连接 |
| commit() | 提交当前事务 |
| rollback() | 取消当前事务 |
| cursor() | 使用该 连接创建(并返回)一个游标或类游标的对象 |
| errorhandler(cxn, cur, errcls, errval) | 作为给定连接的游标处理程序 |
Cursor对象
游标可以让用户提交数据库命令,并获得查询的结果行。 Cursor对象属性
| 对象属性 | 描述 |
|---|---|
| arraysize | 使用fetchmany方法时,一次取出的结果行数,默认为1 |
| connection | 创建此游标的连接(可选) |
| description | 返回游标活动状态(7项无组):(name, type_code, display_size, internal_size, precision, scale, null_ok),只有name和type_code是必需的 |
| lastrowid | 上次修改行的行ID |
| callproc(func [, args]) | 调用存储过程 |
| close() | 关闭游标 |
| execute(op [, args]) | 执行数据库查询命令 |
| executemany(op, args) | 类似execute()和map()的结合 ,为给定的所有参数准备并执行数据库查询或命令 |
| fetchone() | 获取查询结果的下一行 |
| fetchmany([size=cursor, arraysize]) | 获取查询结果的下面size行 |
| fetchall() | 获取查询结果的所有行 |
| *iter*() | 为游标创建迭代器对象 |
| messages | 游标执行后从数据库中获得的消息列表(元组集合,可选) |
| next() | 被迭代器用于获取查询结果的下一行 |
| nextset() | 移动到下一个结果集 |
| rownumber | 当前结果集中游标 的索引 |
| setinputsize(size) | 设置允许的最大输入 大小 |
| setoutputsize(size ) | 设置大列获取的最大缓冲区大小 |
| rowcount | 上次execute*()方法处理或影响的行数 |
ORM
考虑对象而不是SQL 目前最知名的Python ORM是SQLAlchemy和SQLObject。
SQLAlchemy常用方法:
- filter_by():将指定列的什作为关键字参数以获取查询结果。
- filter():与fliter_by()类似,不过更加灵活,还可以使用表达式。比如:query.filter_by(userid=1)与query.filter(User.userid ==1)相同
- order_by()
- limit()
- offset()
- all()
- one()
- first()
- join()
- update()
- delete()
非关系数据库
Web客户端和服务器
Python Web客户端工具
urllib模块/包
-
urllib.request.urlopen() 打开一个给定的URL字符串表示的Web连接
urlopen (urlstr, postQueryData=None)
一旦连接成功,urlopen将会返回一个文件类型对象。 urlopen()文件类型对象的方法:
| 方法 | 描述 |
|---|---|
| f.read([bytes]) | 从f中读出所有或bytes个字节 |
| f.readline() | 从f中读取一行 |
| f.readlines() | 从f中读出所有行,作为列表返回 |
| f.close() | 关闭f的URL连接 |
| f.fileno() | 返回f的文件句柄 |
| f.info() | 获得f的MIME头文件 |
| f.geturl() | 返回f的真正 |
-
urllib.request.urlretrieve() 用于下载完整的HTML,或对象文件。
urlretrieve(url, filename=None, reporthook=None, data=None)
-
quote()
-
unquote()
-
urlencode()
-
…
Web编程:CGI和WSGI
CGI:Common Gateway Interface 通用网关掊 WSGI:Web Server Gateway Interface Web服务器网关接口
Web框架:Django
-
安装
pip install django
-
创建项目
django-admin.exe startproject project_name
-
创建应用
python ./manage.py startapp app_name
-
创建POJO对象
-
创建表
python ./manage.py migrate
python 应用shell
在Django中使用Python shell
python ./manage.py shell
安装应用
在settings.py的INSTALLED_APPS中添加app_name
Python2与Python3的区别
- print
- 在python2中它是一条语句 print …
- 在python3中它成为了一个内置函数:print(’…')
- input
- python2中使用raw_input()
- python3中使用input()
- exception
- python2:except Exception, instance
- python3:except Exception as instance