整理文档发现两年前学习paython3的笔记。当时工作有需要结果也没用上,现在忘的差不多了,在这里整理下。
按 菜鸟编程python3教程编写的demo。链接
高级教程
1.Python 面向对象.py:
#Python 面向对象
"""
Python从设计之初就已经是一门面向对象的语言
面向对象技术简介:
类(Class): 用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。
类变量:类变量在整个实例化的对象中是公用的。类变量定义在类中且在函数体之外。类变量通常不作为实例变量使用。
数据成员:类变量或者实例变量用于处理类及其实例对象的相关的数据。
方法重写:如果从父类继承的方法不能满足子类的需求,可以对其进行改写,这个过程叫方法的覆盖(override),也称为方法的重写。
实例变量:定义在方法中的变量,只作用于当前实例的类。
继承:即一个派生类(derived class)继承基类(base class)的字段和方法。继承也允许把一个派生类的对象作为一个基类对象对待。例如,有这样一个设计:一个Dog类型的对象派生自Animal类,这是模拟"是一个(is-a)"关系(例图,Dog是一个Animal)。
实例化:创建一个类的实例,类的具体对象。
方法:类中定义的函数。
对象:通过类定义的数据结构实例。对象包括两个数据成员(类变量和实例变量)和方法。
"""
# 1.创建类:使用class语句来创建一个新类,class之后为类的名称并以冒号结尾
"""
class ClassName:
'类的帮助信息' #类文档字符串
class_suite #类体
"""
#创建实例对象(注意包名写法)
from 学习笔记.高级教程.面向对象.Employee import Employee
emp1 = Employee("Zara", 2000)
emp2 = Employee("Manni", 5000)
#访问属性
print (emp1.displayEmployee1()) #注意方法没有return时,默认返回None
print (emp2.displayEmployee2())
print ("Total Employee %d" % emp1.empCount) #注意这里在构造函数中,每次全局变量empCount都加1
#添加,删除,修改类的属性:
emp1.age = 7 # 添加一个 'age' 属性
emp1.age = 8 # 修改 'age' 属性
del emp1.age # 删除 'age' 属性
#使用以下函数的方式来访问属性:
"""
getattr(obj, name[, default]) : 访问对象的属性。
hasattr(obj,name) : 检查是否存在一个属性。
setattr(obj,name,value) : 设置一个属性。如果属性不存在,会创建一个新属性。
delattr(obj, name) : 删除属性。
"""
setattr(emp1, 'age', 8) # 添加属性 'age' 值为 8
hasattr(emp1, 'age') # 如果存在 'age' 属性返回 True。
getattr(emp1, 'age') # 返回 'age' 属性的值
delattr(emp1, 'age') # 删除属性 'age'
#Python内置类属性:
"""
__dict__ : 类的属性(包含一个字典,由类的数据属性组成)
__doc__ :类的文档字符串
__name__: 类名
__module__: 类定义所在的模块(类的全名是'__main__.className',如果类位于一个导入模块mymod中,那么className.__module__ 等于 mymod)
__bases__ : 类的所有父类构成元素(包含了以个由所有父类组成的元组)
"""
print ("Employee.__doc__:", Employee.__doc__)
print ("Employee.__name__:", Employee.__name__)
print ("Employee.__module__:", Employee.__module__)
print ("Employee.__bases__:", Employee.__bases__)
print ("Employee.__dict__:", Employee.__dict__)
# 2.python对象销毁(垃圾回收):
"""
同Java语言一样,Python使用了引用计数这一简单技术来追踪内存中的对象。
在Python内部记录着所有使用中的对象各有多少引用。
一个内部跟踪变量,称为一个引用计数器。
当对象被创建时, 就创建了一个引用计数, 当这个对象不再需要时, 也就是说, 这个对象的引用计数变为0 时, 它被垃圾回收。但是回收不
是"立即"的, 由解释器在适当的时机,将垃圾对象占用的内存空间回收。
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
垃圾回收机制不仅针对引用计数为0的对象,同样也可以处理循环引用的情况。循环引用指的是,两个对象相互引用,但是没有其他变量引用他们。
这种情况下,仅使用引用计数是不够的。Python 的垃圾收集器实际上是一个引用计数器和一个循环垃圾收集器。作为引用计数的补充, 垃圾收集
器也会留心被分配的总量很大(及未通过引用计数销毁的那些)的对象。 在这种情况下, 解释器会暂停下来, 试图清理所有未引用的循环。
"""
#实例:析构函数 __del__ ,__del__在对象销毁的时候被调用,当对象不再被使用时,__del__方法运行:
from 学习笔记.高级教程.面向对象.Point import Point
pt1 = Point()
pt2 = pt1
pt3 = pt1
print (id(pt1), id(pt2), id(pt3)) # 打印对象的id
print('del pt1');
del pt1 ;
print('del pt2');
del pt2 ;
print('del pt3');
del pt3 ;
# 3.类的继承:
"""
语法:
继承语法 class 派生类名(基类名)://... 基类名写作括号里,基本类是在类定义的时候,在元组之中指明的。
class SubClassName (ParentClass1[, ParentClass2, ...]):
'Optional class documentation string'
class_suite
在python中继承中的一些特点:
1:在继承中基类的构造(__init__()方法)不会被自动调用,它需要在其派生类的构造中亲自专门调用。
2:在调用基类的方法时,需要加上基类的类名前缀,且需要带上self参数变量。区别于在类中调用普通函数时并不需要带上self参数
3:Python总是首先查找对应类型的方法,如果它不能在派生类中找到对应的方法,它才开始到基类中逐个查找。(先在本类中查找调用的方法,找不到才去基类中找)。
如果在继承元组中列了一个以上的类,那么它就被称作"多重继承" 。
"""
class Parent: # 定义父类
parentAttr = 100
def __init__(self):
print ("调用父类构造函数")
def parentMethod(self):
print ('调用父类方法')
def setAttr(self, attr):
Parent.parentAttr = attr
def getAttr(self):
print ("父类属性 :", Parent.parentAttr)
class Child(Parent): # 定义子类,注意父类放在元祖中 class C(A, B)
def __init__(self):
print ("调用子类构造方法")
def childMethod(self):
print ('调用子类方法 child method')
c = Child() # 实例化子类
c.childMethod() # 调用子类的方法
c.parentMethod() # 调用父类方法
c.setAttr(200) # 再次调用父类的方法
c.getAttr() # 再次调用父类的方法
#检测继承关系:使用issubclass()或者isinstance()方法来检测
"""
issubclass() - 布尔函数判断一个类是另一个类的子类或者子孙类,语法:issubclass(sub,sup),sup可以是元祖
isinstance(obj, Class) 布尔函数如果obj是Class类的实例对象或者是一个Class子类的实例对象则返回true。
"""
p = Parent();
pt = Point()
c = Child()
print (issubclass(c.__class__,p.__class__))
print (issubclass(c.__class__,pt.__class__))
print (issubclass(c.__class__,(p.__class__,pt.__class__)))
print (isinstance(c,p.__class__))
print (isinstance(c,(p.__class__,pt.__class__)))
# 4.方法重写:和java一致
class Parent: # 定义父类
def myMethod(self):
print ('调用父类方法')
class Child(Parent): # 定义子类
def myMethod(self):
print ('调用子类方法')
c = Child() # 子类实例
c.myMethod() # 子类调用重写方法
# 基础重载方法:
"""
序号 方法 描述 简单的调用
1 __init__ ( self [,args...] ) 构造函数 简单的调用方法: obj = className(args)
2 __del__( self ) 析构方法, 删除一个对象 简单的调用方法 : dell obj
3 __repr__( self ) 转化为供解释器读取的形式 简单的调用方法 : repr(obj)
4 __str__( self ) 用于将值转化为适于人阅读的形式 简单的调用方法 : str(obj)
5 __cmp__ ( self, x ) 对象比较 简单的调用方法 : cmp(obj, x)
"""
# 运算符重载:Python同样支持运算符重载
class Vector:
def __init__(self, a, b):
self.a = a
self.b = b
def __str__(self):
return 'Vector (%d, %d)' % (self.a, self.b)
def __add__(self, other):
return Vector(self.a + other.a, self.b + other.b)
v1 = Vector(2, 10)
v2 = Vector(5, -2)
print('v1 + v2:',v1 + v2)
# 5.类属性与方法
#类的私有属性:__private_attrs:两个下划线开头,声明该属性为私有,不能在类地外部被使用或直接访问。在类内部的方法中使用时 self.__private_attrs。
#类的方法:在类地内部,使用def关键字可以为类定义一个方法,与一般函数定义不同,类方法必须包含参数self,且为第一个参数
class JustCounter:
__secretCount = 0 # 私有变量
publicCount = 0 # 公开变量
def count(self):
self.__secretCount += 1
self.publicCount += 1
print ('私有变量',self.__secretCount)
counter = JustCounter()
counter.count()
counter.count()
print ('公开变量',counter.publicCount)
# print (counter.__secretCount) # 报错,实例不能访问私有变量
"""
类的专有方法:
__init__ : 构造函数,在生成对象时调用
__del__ : 析构函数,释放对象时使用
__repr__ : 打印,转换
__setitem__ : 按照索引赋值
__getitem__: 按照索引获取值
__len__: 获得长度
__cmp__: 比较运算
__call__: 函数调用
__add__: 加运算
__sub__: 减运算
__mul__: 乘运算
__div__: 除运算
__mod__: 求余运算
__pow__: 乘方
"""
Employee.py:
#!/usr/bin/python
# -*- coding: UTF-8 -*-
class Employee:
'所有员工的基类' #__doc__() 类的文档字符串
empCount = 0 #类变量
def __init__(self, name, salary): #__init__(),构造函数
self.name = name
self.salary = salary
Employee.empCount += 1
def displayCount(self):
print("Total Employee %d" % Employee.empCount)
def displayEmployee1(self):
print("Name : ", self.name, ", Salary: ", self.salary)
def displayEmployee2(self):
print("Name : ", self.name, ", Salary: ", self.salary)
return '操作完成'
Point.py
class Point:
def __init__( self, x=0, y=0):
self.x = x
self.y = y
def __del__(self):
class_name = self.__class__.__name__
print (class_name, "销毁")
2.Python正则表达式.py:
#Python正则表达式
"""
Python 自1.5版本起增加了re 模块,它提供 Perl 风格的正则表达式模式。(Perl 一般被称为“实用报表提取语言”(Practical Extraction and Report Language))
re 模块使 Python 语言拥有全部的正则表达式功能。
compile 函数根据一个模式字符串和可选的标志参数生成一个正则表达式对象。该对象拥有一系列方法用于正则表达式匹配和替换。
re 模块也提供了与这些方法功能完全一致的函数,这些函数使用一个模式字符串做为它们的第一个参数。
"""
# 1.re.match函数:re.match 尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话,match()就返回none。
"""
函数语法:
re.match(pattern, string, flags=0)
函数参数说明:
参数 描述
pattern 匹配的正则表达式
string 要匹配的字符串。
flags 标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。
匹配成功re.match方法返回一个匹配的对象,否则返回None。
我们可以使用group(num) 或 groups() 匹配对象函数来获取匹配表达式。
匹配对象方法 描述
group(num=0) 匹配的整个表达式的字符串,group() 可以一次输入多个组号,在这种情况下它将返回一个包含那些组所对应值的元组。
groups() 返回一个包含所有小组字符串的元组,从 1 到 所含的小组号。
"""
print ("re.match函数:");
import re
print(re.match('www', 'www.runoob.com').span()) # 在起始位置匹配 span(self, group=0)
print(re.match('com', 'www.runoob.com')) # 起始位匹配不到
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!!")
'''
r'(.*) are (.*?) .*'
首先,这是一个字符串,前面的一个r表示字符串为非转义的原始字符串,让编译器忽略反斜杠,也就是忽略转义字符。但是这个字符串里没有反斜杠,所以这个r可有可无。
(.*) 第一个匹配分组,.*代表匹配除换行符之外的所有字符
(.*?)第二个匹配分组,.*?后面多个问号,代表非贪婪模式,也就是说只匹配符合条件的最少字符
后面的一个.* 没有括号包围,所以不是分组,匹配效果和第一个一样,但是不计入匹配结果中。
matchObj.group() 等同于 matchObj.group(0),表示匹配到的完整文本字符
matchObj.group(1) 得到第一组匹配结果,也就是(.*)匹配到的
matchObj.group(2) 得到第二组匹配结果,也就是(.*?)匹配到的
因为只有匹配结果中只有两组,所以填3时会报错。(这里不会报错,返回最后一个匹配结果 )
'''
# 2.re.search方法:re.search 扫描整个字符串并返回第一个成功的匹配。
"""
函数语法:
re.search(pattern, string, flags=0)
函数参数说明:
参数 描述
pattern 匹配的正则表达式
string 要匹配的字符串。
flags 标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。
匹配成功re.search方法返回一个匹配的对象,否则返回None。
我们可以使用group(num) 或 groups() 匹配对象函数来获取匹配表达式。
匹配对象方法 描述
group(num=0) 匹配的整个表达式的字符串,group() 可以一次输入多个组号,在这种情况下它将返回一个包含那些组所对应值的元组。
groups() 返回一个包含所有小组字符串的元组,从 1 到 所含的小组号。
"""
print ("\nre.search方法:");
import re
print(re.search('www', 'www.runoob.com').span()) # 在起始位置匹配
print(re.search('com', 'www.runoob.com').span()) # 不在起始位置匹配
line = "Cats are smarter than dogs";
searchObj = re.search( r'(.*) are (.*?) .*', line, re.M|re.I)
if searchObj:
print ("searchObj.group() : ", searchObj.group())
print ("searchObj.group(1) : ", searchObj.group(1))
print ("searchObj.group(2) : ", searchObj.group(2))
else:
print ("Nothing found!!")
#re.match与re.search的区别:re.match只匹配字符串的开始,如果字符串开始不符合正则表达式,则匹配失败,函数返回None;而re.search匹配整个字符串,直到找到一个匹配。
# 3.检索和替换:Python 的re模块提供了re.sub用于替换字符串中的匹配项。
"""
语法:
re.sub(pattern, repl, string, max=0)
返回的字符串是在字符串中用 RE 最左边不重复的匹配来替换。如果模式没有发现,字符将被没有改变地返回。
可选参数 count 是模式匹配后替换的最大次数;count 必须是非负整数。缺省值是 0 表示替换所有的匹配。
"""
print('\n检索和替换:')
import re
phone = "2004-959-559 # This is Phone Number"
# Delete Python-style comments
num = re.sub(r'#.*$', "", phone) #匹配#和字符,保留了数字和符号
print ("Phone Num : ", num)
# Remove anything other than digits
num = re.sub(r'\D', "", phone) #匹配非数字,保留了数字
print ("Phone Num : ", num)
# 4.正则表达式修饰符 - 可选标志:正则表达式可以包含一些可选标志修饰符来控制匹配的模式。修饰符被指定为一个可选的标志。多个标志可以通过按位 OR(|) 它们来指定
"""
修饰符 描述
re.I 使匹配对大小写不敏感
re.L 做本地化识别(locale-aware)匹配
re.M 多行匹配,影响 ^ 和 $
re.S 使 . 匹配包括换行在内的所有字符
re.U 根据Unicode字符集解析字符。这个标志影响 \w, \W, \b, \B.
re.X 该标志通过给予你更灵活的格式以便你将正则表达式写得更易于理解。
"""
#正则表达式模式:http://www.runoob.com/python/python-reg-expressions.html
"""
模式字符串使用特殊的语法来表示一个正则表达式:
字母和数字表示他们自身。一个正则表达式模式中的字母和数字匹配同样的字符串。
多数字母和数字前加一个反斜杠时会拥有不同的含义。
标点符号只有被转义时才匹配自身,否则它们表示特殊的含义。
反斜杠本身需要使用反斜杠转义。
由于正则表达式通常都包含反斜杠,所以你最好使用原始字符串来表示它们。模式元素(如 r'/t',等价于'//t')匹配相应的特殊字符。
下表列出了正则表达式模式语法中的特殊元素。如果你使用模式的同时提供了可选的标志参数,某些模式元素的含义会改变。
"""
"""
具体的模式和示例参考:http://www.runoob.com/python/python-reg-expressions.html
"""
# Python CGI编程
"""
CGI 目前由NCSA维护,NCSA定义CGI如下:
CGI(Common Gateway Interface),通用网关接口,它是一段程序,运行在服务器上如:HTTP服务器,提供同客户端HTML页面的接口。
"""
# Web服务器支持及配置:
"""
在你进行CGI编程前,确保您的Web服务器支持CGI及已经配置了CGI的处理程序。
Apache 支持CGI 配置:
设置好CGI目录:
ScriptAlias /cgi-bin/ /var/www/cgi-bin/
所有的HTTP服务器执行CGI程序都保存在一个预先配置的目录。这个目录被称为CGI目录,并按照惯例,它被命名为/var/www/cgi-bin目录。
CGI文件的扩展名为.cgi,python也可以使用.py扩展名。
默认情况下,Linux服务器配置运行的cgi-bin目录中为/var/www。
如果你想指定其他运行CGI脚本的目录,可以修改httpd.conf配置文件,如下所示:
AllowOverride None
Options +ExecCGI
Order allow,deny
Allow from all
在 AddHandler 中添加 .py 后缀,这样我们就可以访问 .py 结尾的 python 脚本文件:
AddHandler cgi-script .cgi .pl .py
"""
'''
在Python2.6版本里,/usr/bin/lib/python2.6/ 目录下会有 BaseHTTPServer.py, SimpleHTTPServer.py, CGIHTTPServer.py
(2.6里的CGIHTTPServer.py有bug:http://my.oschina.net/hevakelcj/blog/372923)
但是在Python3里,就没有上面的3个文件,而是合闭到了 /usr/bin/python3.4/http/server.py文件里了。
在python2.6里启动CGI服务命令是:
$ python -m CGIHTTPServer 8080
在python3.4里则是:
$ py -m http/server --cgi 8080 #执行命令:py -m http.server --cgi 8080
端口号是可选参数。
'''
#HTTP头部:
"""
form.py文件内容中的" Content-type:text/html"即为HTTP头部的一部分,它会发送给浏览器告诉浏览器文件的内容类型。
HTTP头部的格式如下:
HTTP 字段名: 字段内容
例如:
1Content-type: text/html
"""
'''
CGI程序中HTTP头部经常使用的信息:
头 描述
Content-type: 请求的与实体对应的MIME信息。例如: Content-type:text/html
Expires: Date 响应过期的日期和时间
Location: URL 用来重定向接收方到非请求URL的位置来完成请求或标识新的资源
Last-modified: Date 请求资源的最后修改时间
Content-length: N 请求的内容长度
Set-Cookie: String 设置Http Cookie
'''
'''
CGI环境变量:http://www.runoob.com/python/python-cgi.html
'''
#get和post同java相同
#CGI中使用Cookie:
#python操作mysql数据库
# Python 标准数据库接口为 Python DB-API,Python DB-API为开发人员提供了数据库应用编程接口:
"""
Python 数据库接口支持非常多的数据库,你可以选择适合你项目的数据库:
GadFly
mSQL
MySQL
PostgreSQL
Microsoft SQL Server 2000
Informix
Interbase
Oracle
Sybase
"""
# Python数据库接口及API:https://wiki.python.org/moin/DatabaseInterfaces
# MySQLdb:MySQLdb 是用于Python链接Mysql数据库的接口,它实现了 Python 数据库 API 规范 V2.0,基于 MySQL C API 上建立的。
# 执行:import MySQLdb,报出ImportError: No module named 'MySQLdb',表示未安装。
"""
数据库连接:3.0 python不再支持 MySQLdb,使用pymysql 或 mysql.connector
安装MySQLdb: http://sourceforge.net/projects/mysql-python,说明:http://www.runoob.com/python/python-mysql.html
安装pymysql:https://pypi.python.org/pypi/PyMySQL3
· 解压到指定的路径
· 在命令行模式下进入安装目录,执行 python setup.py install命令
"""
# 数据库操作:写操作注意事务。
"""
fetchone(): 该方法获取下一个查询结果集。结果集是一个对象
fetchall():接收全部的返回结果行.
rowcount: 这是一个只读属性,并返回执行execute()方法后影响的行数
"""
import pymysql;
conn = pymysql.connect(host='172.24.7.23', port=3306, user='admin',passwd='admin' ,db='pom',charset='utf8') # 注意utf8
cur = conn.cursor() #获得游标
try:
cur.execute("SELECT * FROM base_wms_company limit 1,10")
# 获取所有记录列表,两种方式
# for r in cur:
# print("wms_company_id:" + str(r[0]) + " ,wms_no:" + str(r[1]) + " ,wms_name:" + str(r[2]))
results = cur.fetchall()
for row in results:
wms_company_id = row[0]
wms_no = row[1]
wms_name = row[2]
alias_name = row[3]
income = row[4]
# 打印结果
print("wms_company_id=%s,wms_no=%s,wms_name=%s,alias_name=%s,income=%s" % \
(wms_company_id, wms_no, wms_name, alias_name, income))
# cur.execute('insert into Login values("%s", "%s")' % (user_id, password)) #用这种字符串格式化方式匹配
# conn.commit(); #写操作需要注意
except:
conn.rollback(); #写操作需要注意
finally:
cur.close()
conn.close()
# 执行事务:和java一致:原子性、一致性、隔离性、持久性。
"""
对于支持事务的数据库, 在Python数据库编程中,当游标建立之时,就自动开始了一个隐形的数据库事务。
commit()方法游标的所有更新操作,rollback()方法回滚当前游标的所有操作。每一个方法都开始了一个新的事务
"""
# 错误处理:DB API中定义了一些数据库操作的错误及异常
"""
异常 描述
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的子类。
"""
5.Python网络编程.py
#Python 网络编程
"""
Python 提供了两个级别访问的网络服务。:
低级别的网络服务支持基本的 Socket,它提供了标准的 BSD Sockets API,可以访问底层操作系统Socket接口的全部方法。
高级别的网络服务模块 SocketServer, 它提供了服务器中心类,可以简化网络服务器的开发。
"""
# Socket:Socket又称"套接字",应用程序通常通过"套接字"向网络发出请求或者应答网络请求,使主机间或者一台计算机上的进程间可以通讯。
'''
socket()函数:Python 中,我们用 socket()函数来创建套接字
语法:
socket.socket([family[, type[, proto]]])
参数:
family: 套接字家族可以使AF_UNIX或者AF_INET
type: 套接字类型可以根据是面向连接的还是非连接分为SOCK_STREAM或SOCK_DGRAM
protocol: 协议 ,一般不填默认为0.
常用socket函数详解:http://blog.csdn.net/g_brightboy/article/details/12854117
'''
#简单实例:
"""
服务端:
我们使用 socket 模块的 socket 函数来创建一个 socket 对象。socket 对象可以通过调用其他函数来设置一个 socket 服务。
现在我们可以通过调用 bind(hostname, port) 函数来指定服务的 port(端口)。
接着,我们调用 socket 对象的 accept 方法。该方法等待客户端的连接,并返回 connection 对象,表示已连接到客户端。
"""
# 同目录下 server.py
'''
客户端:
socket.connect(hosname, port ) 方法打开一个 TCP 连接到主机为 hostname 端口为 port 的服务商。连接后我们就可以从服务端后期数据,记住,操作完成后需要关闭连接。
'''
# 同目录下 client.py
# Python 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
更多内容可以参阅官网: https://docs.python.org/3.0/library/socket.html
"""
server.py:
# 导入 socket 模块
import socket
# 创建 socket 对象
serversocket = socket.socket(
socket.AF_INET, socket.SOCK_STREAM)
# 获取本地主机名
host = socket.gethostname()
port = 9999
# 绑定端口
serversocket.bind((host, port))
# 设置最大连接数,超过后排队
serversocket.listen(5)
while True:
# 建立客户端连接
clientsocket, addr = serversocket.accept()
print("连接地址: %s" % str(addr))
msg = '白兴宇!哈哈哈哈' + "\r\n"
clientsocket.send(msg.encode('utf-8'))
clientsocket.close()
client.py:
# 导入 socket 模块
import socket
# 创建 socket 对象
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 获取本地主机名
host = socket.gethostname()
# 设置端口好
port = 9999
# 连接服务,指定主机和端口
s.connect((host, port))
# 接收小于 1024 字节的数据
msg = s.recv(1024)
s.close()
print (msg.decode('utf-8'))
# Python SMTP发送邮件
"""
说明:
SMTP(Simple Mail Transfer Protocol)即简单邮件传输协议,它是一组用于由源地址到目的地址传送邮件的规则,由它来控制信件的中转方式。
python的smtplib提供了一种很方便的途径发送电子邮件。它对smtp协议进行了简单的封装。
1.创建 SMTP 对象:
语法:
import smtplib
smtpObj = smtplib.SMTP( [host [, port [, local_hostname]]] )
参数说明:
host: SMTP 服务器主机。 你可以指定主机的ip地址或者域名如:w3cschool.cc,这个是可选参数。
port: 如果你提供了 host 参数, 你需要指定 SMTP 服务使用的端口号,一般情况下SMTP端口号为25。
local_hostname: 如果SMTP在你的本机上,你只需要指定服务器地址为 localhost 即可。
2.sendmail方法发送邮件:
语法:
SMTP.sendmail(from_addr, to_addrs, msg[, mail_options, rcpt_options]
参数说明:
from_addr: 邮件发送者地址。
to_addrs: 字符串列表,邮件发送地址。
msg: 发送消息, ##注意这里是smtp协议中定义的格式。包含标题,发信人,收件人,邮件内容,附件等。
"""
'''
标准邮件的头部域:
Date域表示建立信件的时间。
From域表示邮件作者。
Subject域就是邮件的主题。
Sender域表示邮件的实际发送者。
To,cc域都表示接受的邮件地址。
MIME-Version域表示MIME的版本(以后扩充的域)
'''
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 = '[email protected]'
receivers = ['[email protected]','[email protected]'] # 接收邮件,可设置为你的QQ邮箱或者其他邮箱
#一般邮件:
message = MIMEText('Python 邮件发送测试...', 'plain', 'utf-8')
#html类型邮件:
mail_msg = """
Python 邮件发送测试...
"""
message = MIMEText(mail_msg, 'html', 'utf-8') #这里类型为‘html’
#带附件的邮件:
from email.mime.multipart import MIMEMultipart #引入邮件组件
#创建一个带附件的实例
message = MIMEMultipart()
# 构造附件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)
message['From'] = Header("白兴宇", 'utf-8')
message['To'] = Header("测试", 'utf-8')
subject = 'Python SMTP 邮件测试'
message['Subject'] = Header(subject, 'utf-8')
try:
smtpObj = smtplib.SMTP() #这里通过实例化 smtplib 模块的 SMTP 对象 来连接到 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: 无法发送邮件")
#带图片的邮件
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 = '[email protected]'
receivers = ['[email protected]'] # 接收邮件,可设置为你的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 = """
Python 邮件发送测试...
图片演示:
"""
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', '')
msgRoot.attach(msgImage)
try:
smtpObj = smtplib.SMTP('localhost')
smtpObj.sendmail(sender, receivers, msgRoot.as_string())
print ("邮件发送成功")
except smtplib.SMTPException:
print ("Error: 无法发送邮件")
#Python 多线程
#Python中使用线程有两种方式:函数或者用类来包装线程对象。
"""
函数式:调用thread模块中的start_new_thread()函数来产生新线程。语法如下:
thread.start_new_thread ( function, args[, kwargs] )
参数说明:
function - 线程函数。
args - 传递给线程函数的参数,他必须是个tuple类型。
kwargs - 可选参数。
"""
import _thread #2.0版本是thread包
import time
# 1.为线程定义一个函数
def print_time( threadName, delay):
count = 0
while count < 5:
time.sleep(delay)
count += 1
print ("_thread多线程 %s: %s" % ( threadName, time.ctime(time.time()) ))
#_thread.exit() # exit()方法退出线程
# 创建两个线程
# try:
# _thread.start_new_thread( print_time, ("线程1", 1) )
# _thread.start_new_thread( print_time, ("线程2", 2 ) )
# except Exception as e:
# print ("Error: unable to start thread:", e)
# while 1:
# pass
#线程模块:Python通过两个标准库thread和threading提供对线程的支持。thread提供了低级别的、原始的线程以及一个简单的锁。
"""
thread 模块提供的其他方法:
threading.currentThread(): 返回当前的线程变量。
threading.enumerate(): 返回一个包含正在运行的线程的list。正在运行指线程启动后、结束前,不包括启动前和终止后的线程。
threading.activeCount(): 返回正在运行的线程数量,与len(threading.enumerate())有相同的结果。
除了使用方法外,线程模块同样提供了Thread类来处理线程,Thread类提供了以下方法:
run(): 用以表示线程活动的方法。
start():启动线程活动。
join([time]): 等待至线程中止。这阻塞调用线程直至线程的join() 方法被调用中止-正常退出或者抛出未处理的异常-或者是可选的超时发生。
isAlive(): 返回线程是否活动的。
getName(): 返回线程名。
setName(): 设置线程名。
"""
# 2.使用Threading模块创建线程:使用Threading模块创建线程,直接从threading.Thread继承,然后重写__init__方法和run方法:
print('\nThreading:')
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 ("Threading 运行 " + self.name)
print_time(self.name, self.counter, 5)
print ("Threading 关闭 " + self.name)
def print_time(threadName, delay, counter):
while counter:
if exitFlag: #控制开关,可以通过全局变量控制
_thread.exit()
time.sleep(delay)
print ("Threading信息 %s: %s" % (threadName, time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())))
counter -= 1
# 创建新线程
thread1 = myThread(1, "Threading-1", 1)
thread2 = myThread(2, "Threading-2", 2)
# 开启线程
# thread1.start()
# thread2.start()
# print ('Threading 开始')
# 3.线程同步:
"""
使用Thread对象的Lock和Rlock可以实现简单的线程同步,这两个对象都有acquire方法和release方法,对于那些需要每次只允许一个线程操作的数据,可以将其操作放到
acquire 和 release 方法之间。
锁的概念:
锁有两种状态——锁定和未锁定。每当一个线程比如"set操作"要访问共享数据时,必须先获得锁定;如果已经有别的线程比如"print操作"获得锁定了,那么就让线程"set"暂
停,也就是同步阻塞;等到线程"print"访问完毕,释放锁以后,再让线程"set"继续。
"""
print('\n线程同步:')
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 ("运行线程: " + self.name)
# 获得锁,成功获得锁定后返回True
# 可选的timeout参数不填时将一直阻塞直到获得锁定
# 否则超时后将返回False
print('获得锁:',threadLock.acquire())
print_time(self.name, self.counter, 3)
# 释放锁
print('释放锁',threadLock.release())
def print_time(threadName, delay, counter):
while counter:
time.sleep(delay)
print("Threading信息 %s: %s" % (threadName, time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())))
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:
# print('等待上个线程执行完:',t.join())
# print ("停止 Main Thread")
# 4.线程优先级队列( Queue):Python的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() 实际上意味着等到队列为空,再执行别的操作
'''
print('\n队列:')
import queue #注意3.0 是小写的
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 ("运行线程: " + self.name)
process_data(self.name, self.q)
print ("结束线程: " + self.name)
def process_data(threadName, q):
while not exitFlag:
print('线程运行 获取队列锁',threadName,queueLock.acquire())
if not workQueue.empty():
data = q.get()
print('队列值:',data)
print('线程运行 释放队列锁',threadName,queueLock.release())
print ("%s 运行内容 %s" % (threadName, data))
else:
queueLock.release()
time.sleep(1)
threadList = ["Thread-1", "Thread-2", "Thread-3"]
nameList = ["0","1", "2", "3", "4", "5", "6", "7", "8", "9"]
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
print('threadList:',threadList)
# 填充队列
print('填充队列 queueLock.acquire()',queueLock.acquire())
for word in nameList:
print('workQueue.put(word)',word,workQueue.put(word))
print('填充队列 queueLock.release()',queueLock.release())
# 等待队列清空
while not workQueue.empty():
pass
# 通知线程是时候退出
exitFlag = 1
# 等待所有线程完成
for t in threads:
print('等待上个线程执行完:',t._name,t.join())
print ("所有线程结束")
#Python XML解析
# 1.python对XML的解析:python有三种方法解析XML,SAX,DOM,以及ElementTree:
"""
1.SAX (simple API for XML )
python 标准库包含SAX解析器,SAX用事件驱动模型,通过在解析XML的过程中触发一个个的事件并调用用户定义的回调函数来处理XML文件。
2.DOM(Document Object Model)
将XML数据在内存中解析成一个树,通过对树的操作来操作XML。
3.ElementTree(元素树)
ElementTree就像一个轻量级的DOM,具有方便友好的API。代码可用性好,速度快,消耗内存少。
注:因DOM需要将XML数据映射到内存中的树,一是比较慢,二是比较耗内存,而SAX流式读取XML文件,比较快,占用内存少,但需要用户实现回调函数(handler)。
"""
# python对xml的解析和java类似,使用的时候可以互相参考:http://www.runoob.com/python/python-xml.html
# Python JSON
# Python2.7后内置了json,之前的版本需要需要先安装 JSON 模块。
'''
下载 Demjson 并安装:
Demjson:http://deron.meranda.us/python/demjson/
$ tar xvfz demjson-1.6.tar.gz
$ cd demjson-1.6
$ python setup.py install
'''
#JSON 函数:
"""
encode 将 Python 对象编码成 JSON 字符串
decode 将已编码的 JSON 字符串解码为 Python 对象
"""
#encode:.encode(self, obj, nest_level=0) 函数用于将 Python 对象编码成 JSON 字符串。
import json
data = [ { 'a' : '1', 'b' : 2, 'c' : 3, 'd' : 4, 'e' : 5 } ]
repr(data) #规范data
print('data',data)
print ('json.encode',json._default_encoder.encode(data))
#decode:.decode(self, txt)。该函数返回 Python 字段的数据类型。
import json
data = '{"a":1,"b":2,"c":3,"d":4,"e":5}';
text = json._default_decoder.decode(data)
print (text)
# Python3 中可以使用 json 模块来对 JSON 数据进行编解码,它包含了两个函数:
'''
json.dumps(): 对数据进行编码。
json.loads(): 对数据进行解码。
在json的编解码过程中,python 的原始类型与json类型会相互转换,具体的转化对照如下:
Python 编码为 JSON 类型转换对应表:
Python JSON
dict object
list, tuple array
str string
int, float, int- & float-derived Enums number
True true
False false
None null
JSON 解码为 Python 类型转换对应表:
JSON Python
object dict
array list
string str
number (int) int
number (real) float
true True
false False
null None
'''
# json.dumps 与 json.loads 实例
import json
# Python 字典类型转换为 JSON 对象
data1 = {
'no' : 1,
'name' : '白兴宇',
'url' : 'http://www.bxy.com'
}
json_str = json.dumps(data1)
print ("\nPython 原始数据:", repr(data1))
print ("JSON 对象:", json_str)
# 将 JSON 对象转换为 Python 字典
data2 = json.loads(json_str)
print ("data2['name']: ", data2['name'])
print ("data2['url']: ", data2['url'])
# 文件处理:使用 json.dump() 和 json.load() 来编码和解码JSON数据
# 写入 JSON 数据
with open('data.json', 'w') as f:
json.dump(data, f)
# 读取数据
with open('data.json', 'r') as f:
data = json.load(f)
print('\n',data)
data.json
"{\"a\":1,\"b\":2,\"c\":3,\"d\":4,\"e\":5}"