第四章:python2.0的模块的内置对象和内置方法
一、数字
math和cmath的所有方法
# math
>>> import math
>>> dir(math)
['__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'acos', 'acosh', 'asin', 'asinh', 'atan', 'atan2', 'atanh', 'ceil', 'copysign', 'cos', 'cosh', 'degrees', 'e', 'erf', 'erfc', 'exp', 'expm1', 'fabs', 'factorial', 'floor', 'fmod', 'frexp', 'fsum', 'gamma', 'gcd', 'hypot', 'inf', 'isclose', 'isfinite', 'isinf', 'isnan', 'ldexp', 'lgamma', 'log', 'log10', 'log1p', 'log2', 'modf', 'nan', 'pi', 'pow', 'radians', 'sin', 'sinh', 'sqrt', 'tan', 'tanh', 'tau', 'trunc']
>>>
# cmath
>>> import cmath
>>> dir(cmath)
['__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'acos', 'acosh', 'asin', 'asinh', 'atan', 'atanh', 'cos', 'cosh', 'e', 'exp', 'inf', 'infj', 'isclose', 'isfinite', 'isinf', 'isnan', 'log', 'log10', 'nan', 'nanj', 'phase', 'pi', 'polar', 'rect', 'sin', 'sinh', 'sqrt', 'tan', 'tanh', 'tau']
>>>
二、日期与时间
Python 提供了一个 time 和 calendar 模块可以用于格式化日期和时间。
时间间隔:以秒为单位的浮点小数。
时间戳:从1970年1月1日午夜(历元)经过了多长时间来表示。
1、time模块
时间元组
序号 | 字段 | 值 |
---|---|---|
0 | 4位数年 | 2008 |
1 | 月 | 1 到 12 |
2 | 日 | 1到31 |
3 | 小时 | 0到23 |
4 | 分钟 | 0到59 |
5 | 秒 | 0到61 (60或61 是闰秒) |
6 | 一周的第几日 | 0到6 (0是周一) |
7 | 一年的第几日 | 1到366 (儒略历) |
8 | 夏令时 | -1, 0, 1, -1是决定是否为夏令时的旗帜 |
时间元组的属性
字段 | 值 |
---|---|
tm_year | 2008 |
tm_mon | 1 到 12 |
tm_mday | 1 到 31 |
tm_hour | 0 到 23 |
tm_min | 0 到 59 |
tm_sec | 0 到 61 (60或61 是闰秒) |
tm_wday | 0到6 (0是周一) |
tm_yday | 1 到 366(儒略历) |
tm_isdst | -1, 0, 1, -1是决定是否为夏令时的旗帜 |
日期格式化符号的介绍
格式化符号 | 说明 |
---|---|
%y | 两位数的年份表示(00-99) |
%Y | 四位数的年份表示(000-9999) |
%m | 月份(01-12) |
%d | 月内中的一天(0-31) |
%H | 24小时制小时数(0-23) |
%I | 12小时制小时数(01-12) |
%M | 分钟数(00-59) |
%S | 秒(00-59) |
%a | 本地简化星期名称 |
%A | 本地完整星期名称 |
%b | 本地简化的月份名称 |
%B | 本地完整的月份名称 |
%c | 本地相应的日期表示和时间表示 |
%j | 年内的一天(001-366) |
%p | 本地A.M.或P.M.的等价符 |
%U | 一年中的星期数(00-53)星期天为星期的开始 |
%w | 星期(0-6),星期天为星期的开始 |
%W | 一年中的星期数(00-53)星期一为星期的开始 |
%x | 本地相应的日期表示 |
%X | 本地相应的时间表示 |
%Z | 当前时区的名称 |
%% | %号本身 |
Time的内置函数 | |
函数 | 说明 |
:– | :– |
time.altzone | 返回格林威治西部的夏令时地区的偏移秒数。如果该地区在格林威治东部会返回负值(如西欧,包括英国)。对夏令时启用地区才能使用。 |
time.asctime([tupletime]) | 接受时间元组并返回一个可读的形式为"Tue Dec 11 18:07:14 2008"(2008年12月11日 周二18时07分14秒)的24个字符的字符串。 |
time.clock( ) | 用以浮点数计算的秒数返回当前的CPU时间。用来衡量不同程序的耗时,比time.time()更有用。 |
time.ctime([secs]) | 作用相当于asctime(localtime(secs)),未给参数相当于asctime() |
time.gmtime([secs]) | 接收时间戳(1970纪元后经过的浮点秒数)并返回格林威治天文时间下的时间元组t。注:t.tm_isdst始终为0 |
time.localtime([secs]) | 接收时间戳(1970纪元后经过的浮点秒数)并返回当地时间下的时间元组t(t.tm_isdst可取0或1,取决于当地当时是不是夏令时)。 |
time.mktime(tupletime) | 接受时间元组并返回时间戳(1970纪元后经过的浮点秒数)。 |
time.sleep(secs) | 推迟调用线程的运行,secs指秒数。 |
time.strftime(fmt[,tupletime]) | 接收以时间元组,并返回以可读字符串表示的当地时间,格式由fmt决定。 |
time.strptime(str,fmt=‘%a %b %d %H:%M:%S %Y’) | 根据fmt的格式把一个时间字符串解析为时间元组。 |
time.time( ) | 返回当前时间的时间戳(1970纪元后经过的浮点秒数)。 |
time.tzset() | 根据环境变量TZ重新初始化时间相关设置。 |
内置属性
属性 | 说明 |
---|---|
time.timezone | 属性 time.timezone 是当地时区(未启动夏令时)距离格林威治的偏移秒数(>0,美洲<=0大部分欧洲,亚洲,非洲)。 |
time.tzname | 属性time.tzname包含一对根据情况的不同而不同的字符串,分别是带夏令时的本地时区名称,和不带的。 |
import time # 引入time模块
# 获取当前时间
localtime = time.localtime(time.time()) # 得到的是一个时间元组
# 获取格式化的时间
localtime = time.asctime( time.localtime(time.time()) )
# 格式化时间
print time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) # 格式化成2016-03-20 11:45:39形式
print time.strftime("%a %b %d %H:%M:%S %Y", time.localtime()) # 格式化成Sat Mar 28 22:24:24 2016形式
print time.mktime(time.strptime(a,"%a %b %d %H:%M:%S %Y"))# 将格式字符串转换为时间戳
2、Calendar模块
函数 | 说明 |
---|---|
calendar.calendar(year,w=2,l=1,c=6) | 返回一个多行字符串格式的year年年历,3个月一行,间隔距离为c。 每日宽度间隔为w字符。每行长度为21* W+18+2* C。l是每星期行数。 |
calendar.firstweekday( ) | 返回当前每周起始日期的设置。默认情况下,首次载入 calendar 模块时返回 0,即星期一。 |
calendar.isleap(year) | 是闰年返回 True,否则为 False。 |
calendar.leapdays(y1,y2) | 返回在Y1,Y2两年之间的闰年总数。 |
calendar.month(year,month,w=2,l=1) | 返回一个多行字符串格式的year年month月日历,两行标题,一周一行。每日宽度间隔为w字符。每行的长度为7* w+6。l是每星期的行数。 |
calendar.monthcalendar(year,month) | 返回一个整数的单层嵌套列表。每个子列表装载代表一个星期的整数。Year年month月外的日期都设为0;范围内的日子都由该月第几日表示,从1开始。 |
calendar.monthrange(year,month) | 返回两个整数。第一个是该月的星期几的日期码,第二个是该月的日期码。日从0(星期一)到6(星期日);月从1到12。 |
calendar.prcal(year,w=2,l=1,c=6) | 相当于 print calendar.calendar(year,w=2,l=1,c=6)。 |
calendar.prmonth(year,month,w=2,l=1) | 相当于 print calendar.month(year,month,w=2,l=1) 。 |
calendar.setfirstweekday(weekday) | 设置每周的起始日期码。0(星期一)到6(星期日)。 |
calendar.timegm(tupletime) | 和time.gmtime相反:接受一个时间元组形式,返回该时刻的时间戳(1970纪元后经过的浮点秒数)。 |
calendar.weekday(year,month,day) | 返回给定日期的日期码。0(星期一)到6(星期日)。月份为 1(一月) 到 12(12月)。 |
import calendar
datetime模块,pytz模块,dateutil模块 其他模块。
三、io流
1、os模块
未完成!!!
import os
方法 | 说明 |
---|---|
os.mkdir() | 在当前目录下创建新的目录们 |
os.chdir() | 来改变当前的目录 |
os.getcwd() | 显示当前的工作目录 |
os.rmdir() | 删除目录 |
os.access(path, mode) | 检验权限模式 |
四、re模块(正则表达式)——python1.5版本
String是比较内容进行判断是否匹配,但是正则表达式是按照类型进行数据验证。
提供 Perl 风格的正则表达式模式。
1、方法
函数 | 说明 | 参数 |
---|---|---|
re.match(pattern, string, flags=0) | 从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话,match()就返回none,是则返回一个匹配的对象。 | 1、pattern:匹配的正则表达式。2、string:要匹配的字符串。3、flags:标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。参见:正则表达式修饰符 - 可选标志。 |
group(num) | 获取匹配表达式,匹配的整个表达式的字符串,group() 可以一次输入多个组号,在这种情况下它将返回一个包含那些组所对应值的元组。 | |
groups() | 返回一个包含所有小组字符串的元组,从 1 到 所含的小组号。 | |
re.search(pattern, string, flags=0) | 扫描整个字符串并返回第一个成功的匹配。 | 1、pattern 匹配的正则表达式。2、string 要匹配的字符串。3、flags 标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。 |
re.sub(pattern, repl, string, count=0, flags=0) | 提供了re.sub用于替换字符串中的匹配项。 | 1、pattern : 正则中的模式字符串。2、repl : 替换的字符串,也可为一个函数。3、string : 要被查找替换的原始字符串。4、count : 模式匹配后替换的最大次数,默认 0 表示替换所有的匹配。 |
re.compile(pattern[, flags]) | 用于编译正则表达式,生成一个正则表达式( Pattern )对象 | 1、pattern : 一个字符串形式的正则表达式。2、flags : 可选,表示匹配模式,比如忽略大小写,多行模式等,具体参数为: |
findall(string[, pos[, endpos]]) | 找到正则表达式所匹配的所有子串,并返回一个列表,如果没有找到匹配的,则返回空列表。 | 1、string : 待匹配的字符串。2、pos : 可选参数,指定字符串的起始位置,默认为 0。3、endpos : 可选参数,指定字符串的结束位置,默认为字符串的长度。 |
re.finditer(pattern, string, flags=0) | 在字符串中找到正则表达式所匹配的所有子串,并把它们作为一个迭代器返回。 | 1、pattern 匹配的正则表达式。2、string 要匹配的字符串。3、flags标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。参见:正则表达式修饰符 - 可选标志 |
re.split(pattern, string[, maxsplit=0, flags=0]) | 按照能够匹配的子串将字符串分割后返回列表 | 1、pattern 匹配的正则表达式。2、string 要匹配的字符串。3、maxsplit 分隔次数,maxsplit=1 分隔一次,默认为 0,不限制次数。4、flags 标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。参见:正则表达式修饰符 - 可选标志 |
# 例一
#!/usr/bin/python
import re
line = "Cats are smarter than dogs"
matchObj = re.match( r'(.*) are (.*?) .*', line, re.M|re.I)
if matchObj:
print "matchObj.group() : ", matchObj.group()
print "matchObj.group(1) : ", matchObj.group(1)
print "matchObj.group(2) : ", matchObj.group(2)
else:
print "No match!!"
# 例二
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import re
# 将匹配的数字乘以 2
def double(matched):
value = int(matched.group('value'))
return str(value * 2)
s = 'A23G4HFD567'
print(re.sub('(?P<value>\d+)', double, s))
2、对象
re.RegexObject
re.compile() 返回 RegexObject 对象。
# -*- coding:UTF8 -*-
#基本使用
import re
pattern = re.compile(r'\d+') # 查找数字
result1 = pattern.findall('runoob 123 google 456')
result2 = pattern.findall('run88oob123google456', 0, 10)
print(result1)
print(result2)
# 从匹配的字符串再获取字符串
#1、使用()
#2、group(第几个括号)
# 贪婪匹配——.*
# 非贪婪匹配——.*?
# 转移符——\
用于字符串中包含$或者.等等字符串。
# re.S匹配包括换行符在内的字符。
# re.strip() 去除/n
**re.MatchObject **
group()|返回被 RE 匹配的字符串(MatchObject)。
函数 | 说明 |
---|---|
start() | 返回匹配开始的位置 |
end() | 返回匹配结束的位置 |
span() | 返回一个元组包含匹配 (开始,结束) 的位置 |
注意:
1、match和search的区别
match:如果字符串开始不符合正则表达式,则匹配失败,函数返回None;
search:整个字符串,直到找到一个匹配。
2、flags参数可选项
参数名 | 作用 |
---|---|
re.I | 忽略大小写 |
re.L | 表示特殊字符集 \w, \W, \b, \B, \s, \S 依赖于当前环境, 做本地化识别(locale-aware)匹配。 |
re.M | 多行模式,影响 ^ 和 $ |
re.S | 即为 . 并且包括换行符在内的任意字符(. 不包括换行符) |
re.U | 表示特殊字符集 \w, \W, \b, \B, \d, \D, \s, \S 依赖于 Unicode 字符属性数据库 |
re.X | 为了增加可读性,忽略空格和 # 后面的注释 |
3、正则表达式
模式 | 描述 |
---|---|
^ | 匹配字符串的开头 |
$ | 匹配字符串的末尾。 |
. | 匹配任意字符,除了换行符,当re.DOTALL标记被指定时,则可以匹配包括换行符的任意字符。 |
[…] | 用来表示一组字符,单独列出:[amk] 匹配 ‘a’,‘m’或’k’ |
[^…] | 不在[]中的字符:[^abc] 匹配除了a,b,c之外的字符。 |
re* | 匹配0个或多个的表达式。 |
re+ | 匹配1个或多个的表达式。 |
re? | 匹配0个或1个由前面的正则表达式定义的片段,非贪婪方式 |
re{ n} | 精确匹配 n 个前面表达式。例如, o{2} 不能匹配 “Bob” 中的 “o”,但是能匹配 “food” 中的两个 o。 |
re{ n,} | 匹配 n 个前面表达式。例如, o{2,} 不能匹配"Bob"中的"o",但能匹配 "foooood"中的所有 o。“o{1,}” 等价于 “o+”。“o{0,}” 则等价于 “o*”。 |
re{ n, m} | 匹配 n 到 m 次由前面的正则表达式定义的片段,贪婪方式 |
a | b 匹配a或b |
(re) | 对正则表达式分组并记住匹配的文本 |
(?imx) | 正则表达式包含三种可选标志:i, m, 或 x 。只影响括号中的区域。 |
(?-imx) | 正则表达式关闭 i, m, 或 x 可选标志。只影响括号中的区域。 |
(?: re) | 类似 (…), 但是不表示一个组 |
(?imx: re) | 在括号中使用i, m, 或 x 可选标志 |
(?-imx: re) | 在括号中不使用i, m, 或 x 可选标志 |
(?#…) | 注释. |
(?= re) | 前向肯定界定符。如果所含正则表达式,以 … 表示,在当前位置成功匹配时成功,否则失败。但一旦所含表达式已经尝试,匹配引擎根本没有提高;模式的剩余部分还要尝试界定符的右边。 |
(?! re) | 前向否定界定符。与肯定界定符相反;当所含表达式不能在字符串当前位置匹配时成功 |
(?> re) | 匹配的独立模式,省去回溯。 |
\w | 匹配字母数字及下划线 |
\W | 匹配非字母数字及下划线 |
\s | 匹配任意空白字符,等价于 [ \t\n\r\f]。 |
\S | 匹配任意非空字符 |
\d | 匹配任意数字,等价于 [0-9]. |
\D | 匹配任意非数字 |
\A | 匹配字符串开始 |
\Z | 匹配字符串结束,如果是存在换行,只匹配到换行前的结束字符串。 |
\z | 匹配字符串结束 |
\G | 匹配最后匹配完成的位置。 |
\b | 匹配一个单词边界,也就是指单词和空格间的位置。例如, ‘er\b’ 可以匹配"never" 中的 ‘er’,但不能匹配 “verb” 中的 ‘er’。 |
\B | 匹配非单词边界。‘er\B’ 能匹配 “verb” 中的 ‘er’,但不能匹配 “never” 中的 ‘er’。 |
\n, \t, 等. | 匹配一个换行符。匹配一个制表符。等 |
\1…\9 | 匹配第n个分组的内容。 |
\10 | 匹配第n个分组的内容,如果它经匹配。否则指的是八进制字符码的表达式。 |
五、CGI(公共网关接口)
CGI(Common Gateway Interface),通用网关接口,它是一段程序,运行在服务器上如:HTTP 服务器,提供同客户端 HTML 页面的接口(由 NCSA 维护)。
CGI 是如何工作?
1、使用你的浏览器访问 URL 并连接到 HTTP web 服务器。
2、Web 服务器接收到请求信息后会解析 URL,并查找访问的文件在服务器上是否存在,如果存在返回文件的内容,否则返回错误信息。
3、浏览器从服务器上接收信息,并显示接收的文件或者错误信息。
CGI 程序可以是 Python 脚本,PERL 脚本,SHELL 脚本,C 或者 C++ 程序等。
CGI架构图
在你进行 CGI 编程前,确保您的 Web 服务器支持 CGI 及已经配置了 CGI 的处理程序。
#Apache 支持 CGI 配置:
#设置好CGI目录:
ScriptAlias /cgi-bin/ /var/www/cgi-bin/
# CGI 目录:所有的HTTP服务器执行 CGI 程序都保存在一个预先配置的目录(它被命名为 /var/www/cgi-bin 目录。)。
# CGI 文件的扩展名为 .cgi,python 也可以使用 .py 扩展名。
# 默认情况下,Linux 服务器配置运行的 cgi-bin 目录中为 /var/www。
# 如果你想指定其他运行 CGI 脚本的目录,可以修改 httpd.conf 配置文件
<Directory "/var/www/cgi-bin">
AllowOverride None
Options +ExecCGI
Order allow,deny
Allow from all
</Directory>
#在 AddHandler 中添加 .py 后缀,这样我们就可以访问 .py 结尾的 python 脚本文件:
AddHandler cgi-script .cgi .pl .py
1、使用
(1) 创建CGI程序,文件名为hello.py,文件放于 /var/www/cgi-bin。
#!/usr/bin/python
# -*- coding: UTF-8 -*-
print "Content-type:text/html"
print # 空行,告诉服务器结束头部
print '<html>'
print '<head>'
print '<meta charset="utf-8">'
print '<title>Hello World - 我的第一个 CGI 程序!</title>'
print '</head>'
print '<body>'
print '<h2>Hello World! 我是来自菜鸟教程的第一CGI程序</h2>'
print '</body>'
print '</html>'
(2) 修改权限
chmod 755 hello.py
(3) 结果
# 在浏览器访问 http://localhost/cgi-bin/hello.py 显示结果
Hello World! 我是来自菜鸟教程的第一CGI程序
2、程序结构
程序内结构——HTTP头部
# 作用:发送给浏览器告诉浏览器文件的内容类型。
# 格式:HTTP 字段名: 字段内容
Content-type: text/html # 例子
其他头部
头 | 描述 |
---|---|
Content-type: | 请求的与实体对应的MIME信息。例如: Content-type:text/html |
Expires: Date | 响应过期的日期和时间 |
Location: URL | 用来重定向接收方到非请求URL的位置来完成请求或标识新的资源 |
Last-modified: Date | 请求资源的最后修改时间 |
Content-length: N | 请求的内容长度 |
Set-Cookie: String | 设置Http Cookie |
程序运行时结构——CGI环境变量
# (1) 简单的CGI脚本输出CGI的环境变量
#!/usr/bin/python
# -*- coding: UTF-8 -*-
# filename:test.py
import os
print "Content-type: text/html"
print
print "<meta charset=\"utf-8\">"
print "<b>环境变量</b><br>";
print "<ul>"
for key in os.environ.keys():
print "<li><span style='color:green'>%30s </span> : %s </li>" % (key,os.environ[key])
print "</ul>"
# (2) 点保存为 test.py ,并修改文件权限为 755
# 在网页输入网页:localhost/cgi-bin/test.py
环境变量
变量名 | 描述 |
---|---|
CONTENT_TYPE | 这个环境变量的值指示所传递来的信息的MIME类型。目前,环境变量CONTENT_TYPE一般都是:application/x-www-form-urlencoded,他表示数据来自于HTML表单。 |
CONTENT_LENGTH | 如果服务器与CGI程序信息的传递方式是POST,这个环境变量即使从标准输入STDIN中可以读到的有效数据的字节数。这个环境变量在读取所输入的数据时必须使用。 |
HTTP_COOKIE | 客户机内的 COOKIE 内容。 |
HTTP_USER_AGENT | 提供包含了版本数或其他专有数据的客户浏览器信息。 |
PATH_INFO | 这个环境变量的值表示紧接在CGI程序名之后的其他路径信息。它常常作为CGI程序的参数出现。 |
QUERY_STRING | 如果服务器与CGI程序信息的传递方式是GET,这个环境变量的值即使所传递的信息。这个信息经跟在CGI程序名的后面,两者中间用一个问号’?'分隔。 |
REMOTE_ADDR | 这个环境变量的值是发送请求的客户机的IP地址,例如上面的192.168.1.67。这个值总是存在的。而且它是Web客户机需要提供给Web服务器的唯一标识,可以在CGI程序中用它来区分不同的Web客户机。 |
REMOTE_HOST | 这个环境变量的值包含发送CGI请求的客户机的主机名。如果不支持你想查询,则无需定义此环境变量。 |
REQUEST_METHOD | 提供脚本被调用的方法。对于使用 HTTP/1.0 协议的脚本,仅 GET 和 POST 有意义。 |
SCRIPT_FILENAME | CGI脚本的完整路径 |
SCRIPT_NAME | CGI脚本的的名称 |
SERVER_NAME | 这是你的 WEB 服务器的主机名、别名或IP地址。 |
SERVER_SOFTWARE | 这个环境变量的值包含了调用CGI程序的HTTP服务器的名称和版本号。例如,上面的值为Apache/2.2.14(Unix) |
程序内结构——GET和POST方法
# get的说明
(1) 请求可被缓存
(2) 请求保留在浏览器历史记录中
(3) 请求可被收藏为书签
(4) 请求不应在处理敏感数据时使用
(5) 请求有长度限制
(6) 请求只应当用于取回数据
get代码案例
#!/usr/bin/python
# -*- coding: UTF-8 -*-
# filename:test.py
# CGI处理模块
import cgi, cgitb
# 创建 FieldStorage 的实例化
form = cgi.FieldStorage()
# 获取数据
site_name = form.getvalue('name')
site_url = form.getvalue('url')
print "Content-type:text/html"
print
print "<html>"
print "<head>"
print "<meta charset=\"utf-8\">"
print "<title>菜鸟教程 CGI 测试实例</title>"
print "</head>"
print "<body>"
print "<h2>%s官网:%s</h2>" % (site_name, site_url)
print "</body>"
print "</html>"
# 文件保存后修改 hello_get.py,修改文件权限为 755:
# chmod 755 hello_get.py
post代码案例
#!/usr/bin/python
# -*- coding: UTF-8 -*-
# CGI处理模块
import cgi, cgitb
# 创建 FieldStorage 的实例化
form = cgi.FieldStorage()
# 获取数据
site_name = form.getvalue('name')
site_url = form.getvalue('url')
print "Content-type:text/html"
print
print "<html>"
print "<head>"
print "<meta charset=\"utf-8\">"
print "<title>菜鸟教程 CGI 测试实例</title>"
print "</head>"
print "<body>"
print "<h2>%s官网:%s</h2>" % (site_name, site_url)
print "</body>"
print "</html>"
其他:checkbox,Radio,Textarea ,下拉数据
程序内结构——使用Cookie
cookie作用:cookie 就是在客户访问脚本的同时,通过客户的浏览器,在客户硬盘上写入纪录数据 ,当下次客户访问脚本时取回数据信息,从而达到身份判别的功能,cookie 常用在身份校验中。
# 语法
# http cookie的发送是通过http头部来实现的,他早于文件的传递
Set-cookie:name=name;expires=date;path=path;domain=domain;secure
# 例子
#!/usr/bin/python
# -*- coding: UTF-8 -*-
#
print 'Content-Type: text/html'
print 'Set-Cookie: name="菜鸟教程";expires=Wed, 28 Aug 2016 18:30:00 GMT'
print
print """
<html>
<head>
<meta charset="utf-8">
<title>菜鸟教程(runoob.com)</title>
</head>
<body>
<h1>Cookie set OK!</h1>
</body>
</html>
"""
cookie语法参数解释
参数名 | 说明 |
---|---|
name=name | 需要设置cookie的值(name不能使用";“和”,"号),有多个name值时用 “;” 分隔,例如:name1=name1;name2=name2;name3=name3。 |
expires=date | cookie的有效期限,格式: expires=“Wdy,DD-Mon-YYYY HH:MM:SS” |
path=path | 设置cookie支持的路径,如果path是一个路径,则cookie对这个目录下的所有文件及子目录生效,例如: path=“/cgi-bin/”,如果path是一个文件,则cookie指对这个文件生效,例如:path=“/cgi-bin/cookie.cgi”。 |
domain=domain | 对cookie生效的域名,例如:domain=“www.runoob.com” |
secure | 如果给出此标志,表示cookie只能通过SSL协议的https服务器来传递。 |
检索Cookie信息
# Cookie信息存储在CGI的环境变量HTTP_COOKIE
# 存储格式:
key1=value1;key2=value2;key3=value3....
# 例子
#!/usr/bin/python
# -*- coding: UTF-8 -*-
# 导入模块
import os
import Cookie
print "Content-type: text/html"
print
print """
<html>
<head>
<meta charset="utf-8">
<title>菜鸟教程(runoob.com)</title>
</head>
<body>
<h1>读取cookie信息</h1>
"""
if 'HTTP_COOKIE' in os.environ:
cookie_string=os.environ.get('HTTP_COOKIE')
c=Cookie.SimpleCookie()
c.load(cookie_string)
try:
data=c['name'].value
print "cookie data: "+data+"<br>"
except KeyError:
print "cookie 没有设置或者已过期<br>"
print """
</body>
</html>
"""
文件上传实例
# 1、HTML设置上传文件的表单需要设置 enctype 属性为 multipart/form-data
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>菜鸟教程(runoob.com)</title>
</head>
<body>
<form enctype="multipart/form-data"
action="/cgi-bin/save_file.py" method="post">
<p>选中文件: <input type="file" name="filename" /></p>
<p><input type="submit" value="上传" /></p>
</form>
</body>
</html>
# 2、save_file.py脚本
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import cgi, os
import cgitb; cgitb.enable()
form = cgi.FieldStorage()
# 获取文件名
fileitem = form['filename']
# 检测文件是否上传
if fileitem.filename:
# 设置文件路径
fn = os.path.basename(fileitem.filename)
open('/tmp/' + fn, 'wb').write(fileitem.file.read())
message = '文件 "' + fn + '" 上传成功'
else:
message = '文件没有上传'
print """\
Content-Type: text/html\n
<html>
<head>
<meta charset="utf-8">
<title>菜鸟教程(runoob.com)</title>
</head>
<body>
<p>%s</p>
</body>
</html>
""" % (message,)
文件下载对话框
# 创建 foo.txt 文件,用于程序的下载
#!/usr/bin/python
# -*- coding: UTF-8 -*-
# HTTP 头部
print "Content-Disposition: attachment; filename=\"foo.txt\"";
print
# 打开文件
fo = open("foo.txt", "rb")
str = fo.read();
print str
# 关闭文件
fo.close()
六、MySQL数据库
标准数据库接口为 Python DB-API,Python DB-API为开发人员提供了数据库应用编程接口。
数据库接口支持的数据库
GadFly、mSQL、MySQL、PostgreSQL、Microsoft SQL Server 2000、Informix
Interbase、Oracle、Sybase
官网:支持的数据库
DB-API
是一个规范. 它定义了一系列必须的对象和数据库存取方式, 以便为各种各样的底层数据库系统和多种多样的数据库接口程序提供一致的访问接口 。
连接不同的数据库你需要下载不同的DB API模块
DB-API使用流程
(1) 引入 API 模块。
(2) 获取与数据库的连接。
(3) 执行SQL语句和存储过程。
(4) 关闭数据库连接。
1、MySQLdb
作用:用于Python链接Mysql数据库的接口。
它实现了 Python 数据库 API 规范 V2.0,基于 MySQL C API 上建立的。
# 1、安装MySQLdb
https://sourceforge.net/projects/mysql-python/
Linux平台:https://pypi.python.org/pypi/MySQL-python
Linux有两种安装,二进制或源代码安装包。
源代码安装:
$ gunzip MySQL-python-1.2.2.tar.gz
$ tar -xvf MySQL-python-1.2.2.tar
$ cd MySQL-python-1.2.2
$ python setup.py build
$ python setup.py install
# 2、导入或者验证
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import MySQLdb
# 安装失败的提示:
# Traceback (most recent call last):
# File "test.py", line 3, in <module>
# import MySQLdb
# ImportError: No module named MySQLdb
# 3、数据库连接
# 打开数据库连接
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()
# 4、创建数据库表
# 使用cursor()方法获取操作游标
cursor = db.cursor()
# 如果数据表已经存在使用 execute() 方法删除表。
cursor.execute("DROP TABLE IF EXISTS EMPLOYEE")
# 创建数据表SQL语句
sql = """CREATE TABLE EMPLOYEE (
FIRST_NAME CHAR(20) NOT NULL,
LAST_NAME CHAR(20),
AGE INT,
SEX CHAR(1),
INCOME FLOAT )"""
cursor.execute(sql)
# 关闭数据库连接
db.close()
# 5、数据库插入操作
# SQL 插入语句
sql = """INSERT INTO EMPLOYEE(FIRST_NAME,
LAST_NAME, AGE, SEX, INCOME)
VALUES ('Mac', 'Mohan', 20, 'M', 2000)"""
或
sql = "INSERT INTO EMPLOYEE(FIRST_NAME, \
LAST_NAME, AGE, SEX, INCOME) \
VALUES (%s, %s, %s, %s, %s )" % \
('Mac', 'Mohan', 20, 'M', 2000)
try:
# 执行sql语句
cursor.execute(sql)
# 提交到数据库执行
db.commit()
except:
# Rollback in case there is any error
db.rollback()
# 关闭数据库连接
db.close()
# 6、数据库查询操作
#fetchone(): 该方法获取下一个查询结果集。结果集是一个对象
#fetchall():接收全部的返回结果行.
#rowcount: 这是一个只读属性,并返回执行execute()方法后影响的行数。
# SQL 查询语句
sql = "SELECT * FROM EMPLOYEE \
WHERE INCOME > %s" % (1000)
try:
# 执行SQL语句
cursor.execute(sql)
# 获取所有记录列表
results = cursor.fetchall()
for row in results:
fname = row[0]
lname = row[1]
age = row[2]
sex = row[3]
income = row[4]
# 打印结果
print "fname=%s,lname=%s,age=%s,sex=%s,income=%s" % \
(fname, lname, age, sex, income )
except:
print "Error: unable to fecth data"
# 关闭数据库连接
db.close()
# 7、数据库更新操作
# SQL 更新语句
sql = "UPDATE EMPLOYEE SET AGE = AGE + 1 WHERE SEX = '%c'" % ('M')
try:
# 执行SQL语句
cursor.execute(sql)
# 提交到数据库执行
db.commit()
except:
# 发生错误时回滚
db.rollback()
# 关闭数据库连接
db.close()
# 8、删除操作
# SQL 删除语句
sql = "DELETE FROM EMPLOYEE WHERE AGE > %s" % (20)
try:
# 执行SQL语句
cursor.execute(sql)
# 提交修改
db.commit()
except:
# 发生错误时回滚
db.rollback()
# 关闭连接
db.close()
# 9、执行事务
#原子性(atomicity)。一个事务是一个不可分割的工作单位,事务中包括的诸操作要么都做,要么都不做。
#一致性(consistency)。事务必须是使数据库从一个一致性状态变到另一个一致性状态。一致性与原子性是密切相关的。
#隔离性(isolation)。一个事务的执行不能被其他事务干扰。即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。
#持久性(durability)。持续性也称永久性(permanence),指一个事务一旦提交,它对数据库中数据的改变就应该是永久性的。接下来的其他操作或故障不应该对其有任何影响。
# SQL删除记录语句
sql = "DELETE FROM EMPLOYEE WHERE AGE > %s" % (20)
try:
# 执行SQL语句
cursor.execute(sql)
# 向数据库提交
db.commit()
except:
# 发生错误时回滚
db.rollback()
注意:
1、错误处理
异常 | 描述 |
---|---|
Warning | 当有严重警告时触发,例如插入数据是被截断等等。必须是 StandardError 的子类。 |
Error | 警告以外所有其他错误类。必须是 StandardError 的子类。 |
InterfaceError | 当有数据库接口模块本身的错误(而不是数据库的错误)发生时触发。 必须是Error的子类。 |
DatabaseError | 和数据库有关的错误发生时触发。 必须是Error的子类。 |
DataError | 当有数据处理时的错误发生时触发,例如:除零错误,数据超范围等等。 必须是DatabaseError的子类。 |
OperationalError | 指非用户控制的,而是操作数据库时发生的错误。例如:连接意外断开、 数据库名未找到、事务处理失败、内存分配错误等等操作数据库是发生的错误。 必须是DatabaseError的子类。 |
IntegrityError | 完整性相关的错误,例如外键检查失败等。必须是DatabaseError子类。 |
InternalError | 数据库的内部错误,例如游标(cursor)失效了、事务同步失败等等。 必须是DatabaseError子类。 |
ProgrammingError | 程序错误,例如数据表(table)没找到或已存在、SQL语句语法错误、 参数数量错误等等。必须是DatabaseError的子类。 |
NotSupportedError | 不支持错误,指使用了数据库不支持的函数或API等。例如在连接对象上 使用.rollback()函数,然而数据库并不支持事务或者事务已关闭。 必须是DatabaseError的子类。 |
七、网络编程
提供了两个级别访问的网络服务
Socket
低级别的网络服务支持基本的 Socket,它提供了标准的 BSD Sockets API,可以访问底层操作系统 Socket 接口的全部方法。
什么是 Socket?
套接字,应用程序通常通过"套接字"向网络发出请求或者应答网络请求,使主机间或者一台计算机上的进程间可以通讯。
创建套接字
socket()函数来创建套接字,语法:
socket.socket([family[, type[, proto]]])
参数
函数 | 描述 |
---|---|
family | 套接字家族可以使 AF_UNIX 或者 AF_INET。 |
type | 套接字类型可以根据是面向连接的还是非连接分为 SOCK_STREAM 或 SOCK_DGRAM。 |
protocol | 一般不填默认为 0。 |
Socket 对象(内建)方法
服务器端套接字
方法 | 描述 |
---|---|
s.bind() | 绑定地址(host,port)到套接字, 在 AF_INET下,以元组(host,port)的形式表示地址。 |
s.listen() | 开始 TCP 监听。backlog 指定在拒绝连接之前,操作系统可以挂起的最大连接数量。该值至少为 1,大部分应用程序设为 5 就可以了。 |
s.accept() | 被动接受TCP客户端连接,(阻塞式)等待连接的到来 |
客户端套接字 | |
方法 | 描述 |
:– | :– |
s.connect() | 主动初始化TCP服务器连接,。一般address的格式为元组(hostname,port),如果连接出错,返回socket.error错误。 |
s.connect_ex() | connect()函数的扩展版本,出错时返回出错码,而不是抛出异常 |
公共用途的套接字函数 | |
方法 | 描述 |
:– | :– |
s.recv() | 接收 TCP 数据,数据以字符串形式返回,bufsize 指定要接收的最大数据量。flag 提供有关消息的其他信息,通常可以忽略。 |
s.send() | 发送 TCP 数据,将 string 中的数据发送到连接的套接字。返回值是要发送的字节数量,该数量可能小于 string 的字节大小。 |
s.sendall() | 完整发送 TCP 数据。将 string 中的数据发送到连接的套接字,但在返回之前会尝试发送所有数据。成功返回 None,失败则抛出异常。 |
s.recvfrom() | 接收 UDP 数据,与 recv() 类似,但返回值是(data,address)。其中 data 是包含接收数据的字符串,address 是发送数据的套接字地址。 |
s.sendto() | 发送 UDP 数据,将数据发送到套接字,address 是形式为(ipaddr,port)的元组,指定远程地址。返回值是发送的字节数。 |
s.close() | 关闭套接字 |
s.getpeername() | 返回连接套接字的远程地址。返回值通常是元组(ipaddr,port)。 |
s.getsockname() | 返回套接字自己的地址。通常是一个元组(ipaddr,port) |
s.setsockopt(level,optname,value) | 设置给定套接字选项的值。 |
s.getsockopt(level,optname[.buflen]) | 返回套接字选项的值。 |
s.settimeout(timeout) | 设置套接字操作的超时期,timeout是一个浮点数,单位是秒。值为None表示没有超时期。一般,超时期应该在刚创建套接字时设置,因为它们可能用于连接的操作(如connect()) |
s.gettimeout() | 返回当前超时期的值,单位是秒,如果没有设置超时期,则返回None。 |
s.fileno() | 返回套接字的文件描述符。 |
s.setblocking(flag) | 如果flag为0,则将套接字设为非阻塞模式,否则将套接字设为阻塞模式(默认值)。非阻塞模式下,如果调用recv()没有发现任何数据,或send()调用无法立即发送数据,那么将引起socket.error异常。 |
s.makefile() | 创建一个与该套接字相关连的文件 |
# 简单实例
# (1) 服务端
#!/usr/bin/python
# -*- coding: UTF-8 -*-
# 文件名:server.py
import socket # 导入 socket 模块
s = socket.socket() # 创建 socket 对象
host = socket.gethostname() # 获取本地主机名
port = 12345 # 设置端口
s.bind((host, port)) # 绑定端口
s.listen(5) # 等待客户端连接
while True:
c,addr = s.accept() # 建立客户端连接
print '连接地址:', addr
c.send('欢迎访问菜鸟教程!')
c.close() # 关闭连接
# (2) 客户端
#!/usr/bin/python
# -*- coding: UTF-8 -*-
# 文件名:client.py
import socket # 导入 socket 模块
s = socket.socket() # 创建 socket 对象
host = socket.gethostname() # 获取本地主机名
port = 12345 # 设置端口号
s.connect((host, port))
print s.recv(1024)
s.close()
# (3) 测试
# 先运行服务器
# 再运行客户端
# 结果
连接地址: ('192.168.0.118', 62461)
Internet 模块
协议 | 功能用处 | 端口号 | Python模块 |
---|---|---|---|
HTTP | 网页访问 | 80 | httplib, urllib, xmlrpclib |
NNTP | 阅读和张贴新闻文章,俗称为"帖子" | 119 | nntplib |
FTP | 文件传输 | 20 | ftplib, urllib |
SMTP | 发送邮件 | 25 | smtplib |
POP3 | 接收邮件 | 110 | poplib |
IMAP4 | 获取邮件 | 143 | imaplib |
Telnet | 命令行 | 23 | telnetlib |
Gopher | 信息查找 | 70 | gopherlib, urllib |
SocketServer
高级别的网络服务模块 SocketServer, 它提供了服务器中心类,可以简化网络服务器的开发。
八、SMTP发送邮件
SMTP(Simple Mail Transfer Protocol):简单邮件传输协议
原理:它是一组用于由源地址到目的地址传送邮件的规则,由它来控制信件的中转方式。
smtplib:python提供了一种很方便的途径发送电子邮件。
它对smtp协议进行了简单的封装。
创建SMTP对象
import smtplib
smtpObj = smtplib.SMTP( [host [, port [, local_hostname]]] )
参数 | 说明 |
---|---|
host | SMTP 服务器主机。 你可以指定主机的ip地址或者域名如: runoob.com,这个是可选参数。 |
port | 如果你提供了 host 参数, 你需要指定 SMTP 服务使用的端口号,一般情况下 SMTP 端口号为25。 |
local_hostname | 如果 SMTP 在你的本机上,你只需要指定服务器地址为 localhost 即可。 |
**发送邮件 **
SMTP.sendmail(from_addr, to_addrs, msg[, mail_options, rcpt_options])
参数 | 说明 |
---|---|
from_addr | 邮件发送者地址。 |
to_addrs | 字符串列表,邮件发送地址。 |
msg | 发送消息 |
例子
# (1) 本地的邮箱
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import smtplib
from email.mime.text import MIMEText
from email.header import Header
sender = 'from@runoob.com'
receivers = ['429240967@qq.com'] # 接收邮件,可设置为你的QQ邮箱或者其他邮箱
# 三个参数:第一个为文本内容,第二个 plain 设置文本格式,第三个 utf-8 设置编码
message = MIMEText('Python 邮件发送测试...', 'plain', 'utf-8')
message['From'] = Header("菜鸟教程", 'utf-8') # 发送者
message['To'] = Header("测试", 'utf-8') # 接收者
subject = 'Python SMTP 邮件测试'
message['Subject'] = Header(subject, 'utf-8')
try:
smtpObj = smtplib.SMTP('localhost')
smtpObj.sendmail(sender, receivers, message.as_string())
print "邮件发送成功"
except smtplib.SMTPException:
print "Error: 无法发送邮件"
#测试:
# 如果你本机安装 sendmail(邮件传输代理程序)
# 运行 $ python test.py
# 输出:邮件发送成功
# (2) 远程邮箱 SMTP 访问(QQ、网易、Google等)
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import smtplib
from email.mime.text import MIMEText
from email.header import Header
# 第三方 SMTP 服务
mail_host="smtp.XXX.com" #设置服务器
mail_user="XXXX" #用户名
mail_pass="XXXXXX" #口令
sender = 'from@runoob.com'
receivers = ['429240967@qq.com'] # 接收邮件,可设置为你的QQ邮箱或者其他邮箱
message = MIMEText('Python 邮件发送测试...', 'plain', 'utf-8')
message['From'] = Header("菜鸟教程", 'utf-8')
message['To'] = Header("测试", 'utf-8')
subject = 'Python SMTP 邮件测试'
message['Subject'] = Header(subject, 'utf-8')
try:
smtpObj = smtplib.SMTP()
smtpObj.connect(mail_host, 25) # 25 为 SMTP 端口号
smtpObj.login(mail_user,mail_pass)
smtpObj.sendmail(sender, receivers, message.as_string())
print "邮件发送成功"
except smtplib.SMTPException:
print "Error: 无法发送邮件"
# (3) 使用Python发送HTML格式的邮件
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import smtplib
from email.mime.text import MIMEText
from email.header import Header
sender = 'from@runoob.com'
receivers = ['429240967@qq.com'] # 接收邮件,可设置为你的QQ邮箱或者其他邮箱
mail_msg = """
<p>Python 邮件发送测试...</p>
<p><a href="http://www.runoob.com">这是一个链接</a></p>
"""
message = MIMEText(mail_msg, 'html', 'utf-8') # 设置第二个参数为html
message['From'] = Header("菜鸟教程", 'utf-8')
message['To'] = Header("测试", 'utf-8')
subject = 'Python SMTP 邮件测试'
message['Subject'] = Header(subject, 'utf-8')
try:
smtpObj = smtplib.SMTP('localhost')
smtpObj.sendmail(sender, receivers, message.as_string())
print "邮件发送成功"
except smtplib.SMTPException:
print "Error: 无法发送邮件"
# (4) Python 发送带附件的邮件
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.header import Header
sender = 'from@runoob.com'
receivers = ['429240967@qq.com'] # 接收邮件,可设置为你的QQ邮箱或者其他邮箱
#创建一个带附件的实例
message = MIMEMultipart() # 创建这种对象
message['From'] = Header("菜鸟教程", 'utf-8')
message['To'] = Header("测试", 'utf-8')
subject = 'Python SMTP 邮件测试'
message['Subject'] = Header(subject, 'utf-8')
#邮件正文内容
message.attach(MIMEText('这是菜鸟教程Python 邮件发送测试……', 'plain', 'utf-8'))
# 构造附件1,传送当前目录下的 test.txt 文件
att1 = MIMEText(open('test.txt', 'rb').read(), 'base64', 'utf-8')
att1["Content-Type"] = 'application/octet-stream'
# 这里的filename可以任意写,写什么名字,邮件中显示什么名字
att1["Content-Disposition"] = 'attachment; filename="test.txt"'
message.attach(att1)
# 构造附件2,传送当前目录下的 runoob.txt 文件
att2 = MIMEText(open('runoob.txt', 'rb').read(), 'base64', 'utf-8')
att2["Content-Type"] = 'application/octet-stream'
att2["Content-Disposition"] = 'attachment; filename="runoob.txt"'
message.attach(att2)
try:
smtpObj = smtplib.SMTP('localhost') # 发送
smtpObj.sendmail(sender, receivers, message.as_string())
print "邮件发送成功"
except smtplib.SMTPException:
print "Error: 无法发送邮件"
# (5) 在 HTML 文本中添加图片
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import smtplib
from email.mime.image import MIMEImage
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.header import Header
sender = 'from@runoob.com'
receivers = ['429240967@qq.com'] # 接收邮件,可设置为你的QQ邮箱或者其他邮箱
msgRoot = MIMEMultipart('related')
msgRoot['From'] = Header("菜鸟教程", 'utf-8')
msgRoot['To'] = Header("测试", 'utf-8')
subject = 'Python SMTP 邮件测试'
msgRoot['Subject'] = Header(subject, 'utf-8')
msgAlternative = MIMEMultipart('alternative')
msgRoot.attach(msgAlternative)
mail_msg = """
<p>Python 邮件发送测试...</p>
<p><a href="http://www.runoob.com">菜鸟教程链接</a></p>
<p>图片演示:</p>
<p><img src="cid:image1"></p>
"""
msgAlternative.attach(MIMEText(mail_msg, 'html', 'utf-8'))
# 指定图片为当前目录
fp = open('test.png', 'rb')
msgImage = MIMEImage(fp.read())
fp.close()
# 定义图片 ID,在 HTML 文本中引用
msgImage.add_header('Content-ID', '<image1>')
msgRoot.attach(msgImage)
try:
smtpObj = smtplib.SMTP('localhost')
smtpObj.sendmail(sender, receivers, msgRoot.as_string())
print "邮件发送成功"
except smtplib.SMTPException:
print "Error: 无法发送邮件"
# (6)QQ邮箱的发送
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import smtplib
from email.mime.text import MIMEText
from email.utils import formataddr
my_sender='429240967@qq.com' # 发件人邮箱账号
my_pass = 'xxxxxxxxxx' # 发件人邮箱密码
my_user='429240967@qq.com' # 收件人邮箱账号,我这边发送给自己
def mail():
ret=True
try:
msg=MIMEText('填写邮件内容','plain','utf-8')
msg['From']=formataddr(["FromRunoob",my_sender]) # 括号里的对应发件人邮箱昵称、发件人邮箱账号
msg['To']=formataddr(["FK",my_user]) # 括号里的对应收件人邮箱昵称、收件人邮箱账号
msg['Subject']="菜鸟教程发送邮件测试" # 邮件的主题,也可以说是标题
server=smtplib.SMTP_SSL("smtp.qq.com", 465) # 发件人邮箱中的SMTP服务器,端口是25
server.login(my_sender, my_pass) # 括号中对应的是发件人邮箱账号、邮箱密码
server.sendmail(my_sender,[my_user,],msg.as_string()) # 括号中对应的是发件人邮箱账号、收件人邮箱账号、发送邮件
server.quit() # 关闭连接
except Exception: # 如果 try 中的语句没有执行,则会执行下面的 ret=False
ret=False
return ret
ret=mail()
if ret:
print("邮件发送成功")
else:
print("邮件发送失败")
九、多线程
优点:
1、使用线程可以把占据长时间的程序中的任务放到后台去处理。
2、一些等待的任务实现上如用户输入、文件读写和网络收发数据等,线程就比较有用了。
每个线程都有他自己的一组CPU寄存器,称为线程的上下文(该上下文反映了线程上次运行该线程的CPU寄存器的状态。)
指令指针和堆栈指针寄存器:是线程上下文中两个最重要的寄存器,线程总是在进程得到上下文中运行的,这些地址都用于标志拥有线程的进程地址空间中的内存。
线程可以被抢占(中断)。
在其他线程正在运行时,线程可以暂时搁置(也称为睡眠) – 这就是线程的退让。
生成线程
# 函数式
thread.start_new_thread ( function, args[, kwargs] )
# function - 线程函数。
# args - 传递给线程函数的参数,他必须是个tuple类型。
# kwargs - 可选参数。
# 使用Threading模块创建线程
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import threading
import time
exitFlag = 0
class myThread (threading.Thread): #继承父类threading.Thread
def __init__(self, threadID, name, counter):
threading.Thread.__init__(self)
self.threadID = threadID
self.name = name
self.counter = counter
def run(self): #把要执行的代码写到run函数里面 线程在创建后会直接运行run函数
print "Starting " + self.name
print_time(self.name, self.counter, 5)
print "Exiting " + self.name
def print_time(threadName, delay, counter):
while counter:
if exitFlag:
(threading.Thread).exit()
time.sleep(delay)
print "%s: %s" % (threadName, time.ctime(time.time()))
counter -= 1
# 创建新线程
thread1 = myThread(1, "Thread-1", 1)
thread2 = myThread(2, "Thread-2", 2)
# 开启线程
thread1.start()
thread2.start()
print "Exiting Main Thread"
thread和threading线程模块方法
threading类
方法名 | 说明 |
---|---|
threading.currentThread() | 返回当前的线程变量。 |
threading.enumerate() | 返回一个包含正在运行的线程的list。正在运行指线程启动后、结束前,不包括启动前和终止后的线程。 |
threading.activeCount() | 返回正在运行的线程数量,与len(threading.enumerate())有相同的结果。 |
Thread类
方法名 | 说明 |
---|---|
run() | 用以表示线程活动的方法。 |
start() | 启动线程活动。 |
join([time]) | 等待至线程中止。这阻塞调用线程直至线程的join() 方法被调用中止-正常退出或者抛出未处理的异常-或者是可选的超时发生。 |
isAlive() | 返回线程是否活动的。 |
getName() | 返回线程名。 |
setName() | 设置线程名。 |
线程的同步
概述:如果多个线程共同对某个数据修改,则可能出现不可预料的结果,为了保证数据的正确性,需要对多个线程进行同步。
锁(锁定和未锁定)
使用Thread对象的Lock和Rlock可以实现简单的线程同步(两个对象都有acquire方法和release方法,对于那些需要每次只允许一个线程操作的数据,可以将其操作放到acquire和release方法之间。)。
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import threading
import time
class myThread (threading.Thread):
def __init__(self, threadID, name, counter):
threading.Thread.__init__(self)
self.threadID = threadID
self.name = name
self.counter = counter
def run(self):
print "Starting " + self.name
# 获得锁,成功获得锁定后返回True
# 可选的timeout参数不填时将一直阻塞直到获得锁定
# 否则超时后将返回False
threadLock.acquire()
print_time(self.name, self.counter, 3)
# 释放锁
threadLock.release()
def print_time(threadName, delay, counter):
while counter:
time.sleep(delay)
print "%s: %s" % (threadName, time.ctime(time.time()))
counter -= 1
threadLock = threading.Lock()
threads = []
# 创建新线程
thread1 = myThread(1, "Thread-1", 1)
thread2 = myThread(2, "Thread-2", 2)
# 开启新线程
thread1.start()
thread2.start()
# 添加线程到线程列表
threads.append(thread1)
threads.append(thread2)
# 等待所有线程完成
for t in threads:
t.join()
print "Exiting Main Thread"
线程优先级队列( Queue)
Queue模块:提供了同步的、线程安全的队列类,包括FIFO(先入先出)队列Queue,LIFO(后入先出)队列LifoQueue,和优先级队列PriorityQueue。
原理:这些队列都实现了锁原语,能够在多线程中直接使用。
Queue模块中的常用方法
方法名 | 说明 |
---|---|
Queue.qsize() | 返回队列的大小 |
Queue.empty() | 如果队列为空,返回True,反之False |
Queue.full() | 如果队列满了,返回True,反之False |
Queue.full | 与 maxsize 大小对应 |
Queue.get([block[, timeout]]) | 获取队列,timeout等待时间 |
Queue.get_nowait() | 相当Queue.get(False) |
Queue.put(item) | 写入队列,timeout等待时间 |
Queue.put_nowait(item) | 相当Queue.put(item, False) |
Queue.task_done() | 在完成一项工作之后,Queue.task_done()函数向任务已经完成的队列发送一个信号 |
Queue.join() | 实际上意味着等到队列为空,再执行别的操作 |
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import Queue
import threading
import time
exitFlag = 0
class myThread (threading.Thread):
def __init__(self, threadID, name, q):
threading.Thread.__init__(self)
self.threadID = threadID
self.name = name
self.q = q
def run(self):
print "Starting " + self.name
process_data(self.name, self.q)
print "Exiting " + self.name
def process_data(threadName, q):
while not exitFlag:
queueLock.acquire()
if not workQueue.empty():
data = q.get()
queueLock.release()
print "%s processing %s" % (threadName, data)
else:
queueLock.release()
time.sleep(1)
threadList = ["Thread-1", "Thread-2", "Thread-3"]
nameList = ["One", "Two", "Three", "Four", "Five"]
queueLock = threading.Lock()
workQueue = Queue.Queue(10)
threads = []
threadID = 1
# 创建新线程
for tName in threadList:
thread = myThread(threadID, tName, workQueue)
thread.start()
threads.append(thread)
threadID += 1
# 填充队列
queueLock.acquire()
for word in nameList:
workQueue.put(word)
queueLock.release()
# 等待队列清空
while not workQueue.empty():
pass
# 通知线程是时候退出
exitFlag = 1
# 等待所有线程完成
for t in threads:
t.join()
print "Exiting Main Thread"
十、解析XML
XML 指可扩展标记语言(eXtensible Markup Language)
作用:用来传输和存储数据。
XML 是一套定义语义标记的规则,这些标记将文档分成许多部件并对这些部件加以标识(元标记)。
元标记:定义了用于定义其他与特定领域有关的、语义的、结构化的标记语言的句法语言。
对XML解析
常见的 XML 编程接口有 DOM 和 SAX。
Python 有三种方法解析 XML,SAX,DOM,以及 ElementTree:
方法解析 | 说明 |
---|---|
SAX (simple API for XML ) | Python 标准库包含 SAX 解析器,SAX 用事件驱动模型,通过在解析XML的过程中触发一个个的事件并调用用户定义的回调函数来处理XML文件。 |
DOM(Document Object Model) | 将 XML 数据在内存中解析成一个树,通过对树的操作来操作XML。 |
ElementTree(元素树) | ElementTree就像一个轻量级的DOM,具有方便友好的API。代码可用性好,速度快,消耗内存少。 |
说明:
1、因DOM需要将XML数据映射到内存中的树,一是比较慢,二是比较耗内存。
2、SAX流式读取XML文件,比较快,占用内存少,但需要用户实现回调函数(handler)。
movies.xml
<collection shelf="New Arrivals">
<movie title="Enemy Behind">
<type>War, Thriller</type>
<format>DVD</format>
<year>2003</year>
<rating>PG</rating>
<stars>10</stars>
<description>Talk about a US-Japan war</description>
</movie>
<movie title="Transformers">
<type>Anime,Science Fiction</type>
<format>DVD</format>
<year>1989</year>
<rating>R</rating>
<stars>8</stars>
<description>A schientific fiction</description>
</movie>
<movie title="Trigun">
<type>Anime, Action</type>
<format>DVD</format>
<episodes>4</episodes>
<rating>PG</rating>
<stars>10</stars>
<description>Vash the Stampede!</description>
</movie>
<movie title="Ishtar">
<type>Comedy</type>
<format>VHS</format>
<rating>PG</rating>
<stars>2</stars>
<description>Viewable boredom</description>
</movie>
</collection>
使用SAX解析xml
SAX是一种基于事件驱动的 API。
利用SAX解析XML文档牵涉到两个部分: 解析器和事件处理器。
解析器:负责读取XML文档,并向事件处理器发送事件,如元素开始跟元素结束事件。
事件处理器:则负责对事件作出响应,对传递的XML数据进行处理。
应用:
1、对大型文件进行处理;
2、只需要文件的部分内容,或者只需从文件中得到特定信息。
3、想建立自己的对象模型的时候。
使用sax方式处理xml要先引入xml.sax中的parse函数,还有xml.sax.handler中的ContentHandler。
ContentHandler类方法介绍
方法 | 说明 |
---|---|
characters(content) | 调用时机:1、从行开始,遇到标签之前,存在字符,content 的值为这些字符串。2、从一个标签,遇到下一个标签之前, 存在字符,content 的值为这些字符串。3、从一个标签,遇到行结束符之前,存在字符,content 的值为这些字符串。4、标签可以是开始标签,也可以是结束标签。 |
startDocument() | 文档启动的时候调用。 |
endDocument() | 解析器到达文档结尾时调用。 |
startElement(name, attrs) | 遇到XML开始标签时调用,name是标签的名字,attrs是标签的属性值字典。 |
endElement(name) | 遇到XML结束标签时调用。 |
其他方法
方法 | 说明 | 参数 |
---|---|---|
xml.sax.make_parser( [parser_list] ) | 创建一个新的解析器对象并返回。 | parser_list - 可选参数,解析器列表 |
xml.sax.parse( xmlfile, contenthandler[, errorhandler]) | 创建一个 SAX 解析器并解析xml文档 | 1、xmlfile - xml文件名。2、contenthandler - 必须是一个ContentHandler的对象。3、errorhandler - 如果指定该参数,errorhandler必须是一个SAX ErrorHandler对象。 |
xml.sax.parseString(xmlstring, contenthandler[, errorhandler]) | 创建一个XML解析器并解析xml字符串 | 1、xmlstring - xml字符串。2、contenthandler - 必须是一个ContentHandler的对象。3、errorhandler - 如果指定该参数,errorhandler必须是一个SAX ErrorHandler对象。 |
实例
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import xml.sax
class MovieHandler( xml.sax.ContentHandler ):
def __init__(self):
self.CurrentData = ""
self.type = ""
self.format = ""
self.year = ""
self.rating = ""
self.stars = ""
self.description = ""
# 元素开始事件处理
def startElement(self, tag, attributes):
self.CurrentData = tag
if tag == "movie":
print "*****Movie*****"
title = attributes["title"]
print "Title:", title
# 元素结束事件处理
def endElement(self, tag):
if self.CurrentData == "type":
print "Type:", self.type
elif self.CurrentData == "format":
print "Format:", self.format
elif self.CurrentData == "year":
print "Year:", self.year
elif self.CurrentData == "rating":
print "Rating:", self.rating
elif self.CurrentData == "stars":
print "Stars:", self.stars
elif self.CurrentData == "description":
print "Description:", self.description
self.CurrentData = ""
# 内容事件处理
def characters(self, content):
if self.CurrentData == "type":
self.type = content
elif self.CurrentData == "format":
self.format = content
elif self.CurrentData == "year":
self.year = content
elif self.CurrentData == "rating":
self.rating = content
elif self.CurrentData == "stars":
self.stars = content
elif self.CurrentData == "description":
self.description = content
if ( __name__ == "__main__"):
# 创建一个 XMLReader
parser = xml.sax.make_parser()
# turn off namepsaces
parser.setFeature(xml.sax.handler.feature_namespaces, 0)
# 重写 ContextHandler
Handler = MovieHandler()
parser.setContentHandler( Handler )
parser.parse("movies.xml")
使用xml.dom解析xml
文件对象模型(Document Object Model,简称DOM),是W3C组织推荐的处理可扩展置标语言的标准编程接口。
一个 DOM 的解析器在解析一个 XML 文档时,一次性读取整个文档,把文档中所有元素保存在内存中的一个树结构里,之后你可以利用DOM 提供的不同的函数来读取或修改文档的内容和结构,也可以把修改过的内容写入xml文件。
例子
#!/usr/bin/python
# -*- coding: UTF-8 -*-
from xml.dom.minidom import parse
import xml.dom.minidom
# 使用minidom解析器打开 XML 文档
DOMTree = xml.dom.minidom.parse("movies.xml")
collection = DOMTree.documentElement
if collection.hasAttribute("shelf"):
print "Root element : %s" % collection.getAttribute("shelf")
# 在集合中获取所有电影
movies = collection.getElementsByTagName("movie")
# 打印每部电影的详细信息
for movie in movies:
print "*****Movie*****"
if movie.hasAttribute("title"):
print "Title: %s" % movie.getAttribute("title")
type = movie.getElementsByTagName('type')[0]
print "Type: %s" % type.childNodes[0].data
format = movie.getElementsByTagName('format')[0]
print "Format: %s" % format.childNodes[0].data
rating = movie.getElementsByTagName('rating')[0]
print "Rating: %s" % rating.childNodes[0].data
description = movie.getElementsByTagName('description')[0]
print "Description: %s" % description.childNodes[0].data
十一、GUI编程
Python 提供了多个图形开发界面的库,几个常用 Python GUI 库
库名 | 说明 |
---|---|
Tkinter | Tkinter 模块(Tk 接口)是 Python 的标准 Tk GUI 工具包的接口 .Tk 和 Tkinter 可以在大多数的 Unix 平台下使用,同样可以应用在 Windows 和 Macintosh 系统里。Tk8.0 的后续版本可以实现本地窗口风格,并良好地运行在绝大多数平台中。 |
wxPython | wxPython 是一款开源软件,是 Python 语言的一套优秀的 GUI 图形库,允许 Python 程序员很方便的创建完整的、功能健全的 GUI 用户界面。 |
Jython | Jython 程序可以和 Java 无缝集成。除了一些标准模块,Jython 使用 Java 的模块。Jython 几乎拥有标准的Python 中不依赖于 C 语言的全部模块。比如,Jython 的用户界面将使用 Swing,AWT或者 SWT。Jython 可以被动态或静态地编译成 Java 字节码。 |
Tkinter 编程
Tkinter 是 Python 的标准 GUI 库。Python 使用 Tkinter 可以快速的创建 GUI 应用程序。
Tkinter 是内置到 python 的安装包中、只要安装好 Python 之后就能 import Tkinter 库、而且 IDLE 也是用 Tkinter 编写而成、对于简单的图形界面 Tkinter 还是能应付自如。
创建一个GUI
# 1、导入 Tkinter 模块
# 注意:Python3.x 版本使用的库名为 tkinter,即首写字母 T 为小写。
import tkinter # Python3.x
import Tkinter # Python2.x
# 2、创建控件
# 3、指定这个控件的 master, 即这个控件属于哪一个
# 4、告诉 GM(geometry manager) 有一个控件产生了。
#!/usr/bin/python
# -*- coding: UTF-8 -*-
# Python2.x 导入方法
from Tkinter import * # 导入 Tkinter 库
# Python3.x 导入方法
#from tkinter import *
root = Tk() # 创建窗口对象的背景色
# 创建两个列表
li = ['C','python','php','html','SQL','java']
movie = ['CSS','jQuery','Bootstrap']
listb = Listbox(root) # 创建两个列表组件
listb2 = Listbox(root)
for item in li: # 第一个小部件插入数据
listb.insert(0,item)
for item in movie: # 第二个小部件插入数据
listb2.insert(0,item)
listb.pack() # 将小部件放置到主窗口中
listb2.pack()
root.mainloop() # 进入消息循环
Tkinter 组件
控件/部件:如按钮,标签和文本框。
部件名 | 说明 |
---|---|
Button | 按钮控件;在程序中显示按钮。 |
Canvas | 画布控件;显示图形元素如线条或文本 |
Checkbutton | 多选框控件;用于在程序中提供多项选择框 |
Entry | 输入控件;用于显示简单的文本内容 |
Frame | 框架控件;在屏幕上显示一个矩形区域,多用来作为容器 |
Label | 标签控件;可以显示文本和位图 |
Listbox | 列表框控件;在Listbox窗口小部件是用来显示一个字符串列表给用户 |
Menubutton | 菜单按钮控件,用于显示菜单项。 |
Menu | 菜单控件;显示菜单栏,下拉菜单和弹出菜单 |
Message | 消息控件;用来显示多行文本,与label比较类似 |
Radiobutton | 单选按钮控件;显示一个单选的按钮状态 |
Scale | 范围控件;显示一个数值刻度,为输出限定范围的数字区间 |
Scrollbar | 滚动条控件,当内容超过可视化区域时使用,如列表框。. |
Text | 文本控件;用于显示多行文本 |
Toplevel | 容器控件;用来提供一个单独的对话框,和Frame比较类似 |
Spinbox | 输入控件;与Entry类似,但是可以指定输入范围值 |
PanedWindow | PanedWindow是一个窗口布局管理的插件,可以包含一个或者多个子控件。 |
LabelFrame labelframe | 是一个简单的容器控件。常用与复杂的窗口布局。 |
tkMessageBox | 用于显示你应用程序的消息框。 |
属性 | 说明 |
---|---|
Dimension | 控件大小; |
Color | 控件颜色; |
Font | 控件字体; |
Anchor | 锚点; |
Relief | 控件样式; |
Bitmap | 位图; |
Cursor | 光标; |
Tkinter控件有特定的几何状态管理方法,管理整个控件区域组织,以下是Tkinter公开的几何管理类:包、网格、位置
几何方法 | 描述 |
---|---|
pack() | 包装; |
grid() | 网格; |
place() | 位置; |
十二、json
Python 语言来编码和解码 JSON 对象。
JSON(JavaScript Object Notation) :是一种轻量级的数据交换格式
函数 | 说明 | 语法 |
---|---|---|
json.dumps | 将 Python 对象编码成 JSON 字符串 | json.dumps(obj, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, cls=None, indent=None, separators=None, encoding=“utf-8”, default=None, sort_keys=False, **kw) |
json.loads | 将已编码的 JSON 字符串解码为 Python 对象 | json.loads(s[, encoding[, cls[, object_hook[, parse_float[, parse_int[, parse_constant[, object_pairs_hook[, **kw]]]]]]]]) |
# dumps使用
#!/usr/bin/python
import json
data = [ { 'a' : 1, 'b' : 2, 'c' : 3, 'd' : 4, 'e' : 5 } ]
data2 = json.dumps(data)
print(data2)
# loads使用
#!/usr/bin/python
import json
jsonData = '{"a":1,"b":2,"c":3,"d":4,"e":5}';
text = json.loads(jsonData)
print(text)
python 原始类型向 json 类型的转化对照表
python | json |
---|---|
dict | object |
list, tuple | array |
str, unicode | string |
int, long, float | number |
True | true |
False | false |
None | null |
json 类型转换到 python 的类型对照表
json | Python |
---|---|
object | dict |
array | list |
string | unicode |
number (int) | int, long |
number (real) | float |
true | True |
false | False |
null | None |
第三方库Demjson
Demjson 是 python 的第三方模块库,可用于编码和解码 JSON 数据,包含了 JSONLint 的格式化及校验功能。
环境配置
# 下载
# Github 地址:https://github.com/dmeranda/demjson
# 官方地址:http://deron.meranda.us/python/demjson/
$ tar -xvzf demjson-2.2.3.tar.gz
$ cd demjson-2.2.3
$ python setup.py install
# encode
#!/usr/bin/python
import demjson
data = [ { 'a' : 1, 'b' : 2, 'c' : 3, 'd' : 4, 'e' : 5 } ]
json = demjson.encode(data)
print(json)
# decode
#!/usr/bin/python
import demjson
json = '{"a":1,"b":2,"c":3,"d":4,"e":5}';
text = demjson.decode(json)
print(text)
json函数
函数 | 说明 | 语法 |
---|---|---|
encode | 将 Python 对象编码成 JSON 字符串 | demjson.encode(self, obj, nest_level=0) |
decode | 将已编码的 JSON 字符串解码为 Python 对象 | demjson.decode(self, txt) |