1.yum -y install python
2.中文乱码:
# -*- coding: UTF-8 -*-
3.Python保留字符
and | exec | not |
assert | finally | or |
break | for | pass |
class | from | |
continue | global | raise |
def | if | return |
del | import | try |
elif | in | while |
else | is | with |
except | lambda | yield |
4.行和缩进
if True:
print "True"
else:
print "False"
报错:Python要求严格缩进
5.多行语句
使用 \ 来多行显示
total = item1 + \
item2 + \
item3
或者 [] , (), {} 来直接包含
days = [‘1‘,‘2‘,
‘3‘]
6.引号
word=‘word‘
sentence="这是一个句子"
paragraph="""这是一个
段落"""
7.注释
# ----单行注释
‘‘‘.....‘‘‘ 多行注释
8.输入
raw_input()
9.多变量赋值
a=b=c=1
a,b,c=1,2,3
10.标准数据类型
Number(int,float,long,complex),String,List,Tuple,Dictionary
11.字符串处理
#!/usr/bin/python
# -*- coding: UTF-8 -*-
str = ‘Hello World!‘
print str # 输出完整字符串
print str[0] # 输出字符串中的第一个字符
print str[2:5] # 输出字符串中第三个至第五个之间的字符串
print str[2:] # 输出从第三个字符开始的字符串
print str * 2 # 输出字符串两次
print str + "TEST" # 输出连接的字符串
12.列表处理
#!/usr/bin/python
# -*- coding: UTF-8 -*-
list = [ ‘abcd‘, 786 , 2.23, ‘john‘, 70.2 ]
tinylist = [123, ‘john‘]
print list # 输出完整列表
print list[0] # 输出列表的第一个元素
print list[1:3] # 输出第二个至第三个的元素
print list[2:] # 输出从第三个开始至列表末尾的所有元素
print tinylist * 2 # 输出列表两次
print list + tinylist # 打印组合的列表
13.元组处理
#!/usr/bin/python
# -*- coding: UTF-8 -*-
tuple = ( ‘abcd‘, 786 , 2.23, ‘john‘, 70.2 )
tinytuple = (123, ‘john‘)
print tuple # 输出完整元组
print tuple[0] # 输出元组的第一个元素
print tuple[1:3] # 输出第二个至第三个的元素
print tuple[2:] # 输出从第三个开始至列表末尾的所有元素
print tinytuple * 2 # 输出元组两次
print tuple + tinytuple # 打印组合的元组
以下是元组无效的,因为元组是不允许更新的。而列表是允许更新的:
tuple = ( ‘abcd‘, 786 , 2.23, ‘john‘, 70.2 )
list = [ ‘abcd‘, 786 , 2.23, ‘john‘, 70.2 ]
tuple[2] = 1000 # 元组中是非法应用
list[2] = 1000 # 列表中是合法应用
14.元字典处理
#!/usr/bin/python
# -*- coding: UTF-8 -*-
dict = {}
dict[‘one‘] = "This is one"
dict[2] = "This is two"
tinydict = {‘name‘: ‘john‘,‘code‘:6734, ‘dept‘: ‘sales‘}
print dict[‘one‘] # 输出键为‘one‘ 的值
print dict[2] # 输出键为 2 的值
print tinydict # 输出完整的字典
print tinydict.keys() # 输出所有键
print tinydict.values() # 输出所有值
15.算术运算
+ | 加 - 两个对象相加 | a + b 输出结果 30 |
- | 减 - 得到负数或是一个数减去另一个数 | a - b 输出结果 -10 |
* | 乘 - 两个数相乘或是返回一个被重复若干次的字符串 | a * b 输出结果 200 |
/ | 除 - x除以y | b / a 输出结果 2 |
% | 取模 - 返回除法的余数 | b % a 输出结果 0 |
** | 幂 - 返回x的y次幂 | a**b 为10的20次方, 输出结果 100000000000000000000 |
// | 取整除 - 返回商的整数部分 | 9//2 输出结果 4 , 9.0//2.0 输出结果 4.0 |
16.逻辑运算
and | 布尔"与" - 如果x为False,x and y返回False,否则它返回y的计算值。 | (a and b) 返回 true。 |
or | 布尔"或" - 如果x是True,它返回True,否则它返回y的计算值。 | (a or b) 返回 true。 |
not | 布尔"非" - 如果x为True,返回False。如果x为False,它返回True。 | not(a and b) 返回 false。 |
17.成员运算符
in | 如果在指定的序列中找到值返回True,否则返回False。 | x 在 y序列中 , 如果x在y序列中返回True。 |
not in | 如果在指定的序列中没有找到值返回True,否则返回False。 | x 不在 y序列中 , 如果x不在y序列中返回True。 |
18.身份运算符
is | is是判断两个标识符是不是引用自一个对象 | x is y, 如果 id(x) 等于 id(y) , is 返回结果 1 |
is not | is not是判断两个标识符是不是引用自不同对象 | x is not y, 如果 id(x) 不等于 id(y). is not 返回结果 1 |
19.运算符优先级
** | 指数 (最高优先级) |
~ + - | 按位翻转, 一元加号和减号 (最后两个的方法名为 +@ 和 [email protected]) |
* / % // | 乘,除,取模和取整除 |
+ - | 加法减法 |
>> << | 右移,左移运算符 |
& | 位 ‘AND‘ |
^ | | 位运算符 |
<= < > >= | 比较运算符 |
<> == != | 等于运算符 |
= %= /= //= -= += *= **= | 赋值运算符 |
is is not | 身份运算符 |
in not in | 成员运算符 |
not or and | 逻辑运算符 |
20.pass 语句
Python pass是空语句,是为了保持程序结构的完整性。
passass 不做任何事情,一般用做占位语句
21.Unicode 字符
u‘Hello World !‘
22.时间
#!/usr/bin/pythonimport
time;
# This is required to include time module.
ticks =
time.time()print
"Number of ticks since 12:00am, January 1, 1970:",
ticks
获取当前时间
localtime = time.localtime(time.time());
获取格式化的时间
localtime = time.asctime(time.time());
获取某月日历
import calendar
cal = calendar.month(2008, 1);
23. lambda 函数
sum = lambda arg1, arg2: arg1 + arg2;
调用: sum(10, 20)
reduce(lambda x,y : x + y,Sn)
python中的reduce内建函数是一个二元操作函数,他用来将一个数据集合(链表,元组等)中的所有数据进行下列操作:用传给reduce中的函数 func()(必须是一个二元操作函数)先对集合中的第1,2个数据进行操作,得到的结果再与第三个数据用func()函数运算,最后得到一个结果
24.dir 函数
用来获取一个模块中所有的定义的模块
import math
content = dir(math)
25.文件 I/O
input([prompt]) 函数和 raw_input([prompt]) 函数基本类似,但是 input 可以接收一个Python表达式作为输入,并将运算结果返回。
str = input("请输入:");
请输入:[x*5 for x in range(2,10,2)]你输入的内容是: [10, 20, 30, 40]
File对象的属性
属性 | 描述 |
---|---|
file.closed | 返回true如果文件已被关闭,否则返回false。 |
file.mode | 返回被打开文件的访问模式。 |
file.name | 返回文件的名称。 |
file.softspace | 如果用print输出后,必须跟一个空格符,则返回false。否则返回true。 |
fo = open("foo.txt", "wb") fo.write( "www.runoob.com!\nVery good site!\n");# 关闭打开的文件 fo.close()
# 打开一个文件 fo = open("foo.txt", "r+") str = fo.read(10);print "读取的字符串是 : ", str # 关闭打开的文件 fo.close()
文件定位:
tell()方法告诉你文件内的当前位置;换句话说,下一次的读写会发生在文件开头这么多字节之后。
seek(offset [,from])方法改变当前文件的位置。Offset变量表示要移动的字节数。From变量指定开始移动字节的参考位置。
如果from被设为0,这意味着将文件的开头作为移动字节的参考位置。如果设为1,则使用当前的位置作为参考位置。如果它被设为2,那么该文件的末尾将作为参考位置。
fo = open("foo.txt", "r+") str = fo.read(10);print "读取的字符串是 : ", str # 查找当前位置 position = fo.tell();print "当前文件位置 : ", position # 把指针再次重新定位到文件开头 position = fo.seek(0, 0); str = fo.read(10);print "重新读取字符串 : ", str # 关闭打开的文件 fo.close()
重命名跟删除文件
import os # 重命名文件test1.txt到test2.txt。 os.rename( "test1.txt", "test2.txt" )
import os # 删除一个已经存在的文件test2.txt os.remove("test2.txt")
创建目录
import os # 创建目录test os.mkdir("test")
import os # 将当前目录改为"/home/newdir" os.chdir("/home/newdir")
import os # 给出当前的目录 os.getcwd()
import os # 删除”/tmp/test”目录 os.rmdir( "/tmp/test" )
26.异常触发:
#!/usr/bin/python# Define a function here.def temp_convert(var):try:return int(var)except ValueError, Argument:print "The argument does not contain numbers\n", Argument# Call above function here. temp_convert("xyz");
主动触发异常
def functionName( level ):if level < 1:raise "Invalid level!", level
用户自定义异常
class Networkerror(RuntimeError):def __init__(self, arg):self.args = arg
try:raise Networkerror("Bad hostname")except Networkerror,e:print e.args
27.对象:
#!/usr/bin/python# -*- coding: UTF-8 -*-class Employee:‘所有员工的基类‘ empCount = 0def __init__(self, name, salary):self.name = name self.salary = salary Employee.empCount += 1def displayCount(self):print "Total Employee %d" % Employee.empCount def displayEmployee(self):print "Name : ", self.name, ", Salary: ", self.salary "创建 Employee 类的第一个对象" emp1 = Employee("Zara", 2000)"创建 Employee 类的第二个对象" emp2 = Employee("Manni", 5000) emp1.displayEmployee() emp2.displayEmployee()print "Total Employee %d" % Employee.empCount
你也可以使用以下函数的方式来访问属性:
- getattr(obj, name[, default]) : 访问对象的属性。
- hasattr(obj,name) : 检查是否存在一个属性。
- setattr(obj,name,value) : 设置一个属性。如果属性不存在,会创建一个新属性。
- delattr(obj, name) : 删除属性。
hasattr(emp1, ‘age‘) # 如果存在 ‘age‘ 属性返回 True。 getattr(emp1, ‘age‘) # 返回 ‘age‘ 属性的值 setattr(emp1, ‘age‘, 8) # 添加属性 ‘age‘ 值为 8 delattr(empl, ‘age‘) # 删除属性 ‘age‘
Python内置类属性
- __dict__ : 类的属性(包含一个字典,由类的数据属性组成)
- __doc__ :类的文档字符串
- __name__: 类名
- __module__: 类定义所在的模块(类的全名是‘__main__.className‘,如果类位于一个导入模块mymod中,那么className.__module__ 等于 mymod)
- __bases__ : 类的所有父类构成元素(包含了以个由所有父类组成的元组)
python对象销毁(垃圾回收)
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, "销毁" pt1 = Point() pt2 = pt1 pt3 = pt1 print id(pt1), id(pt2), id(pt3) # 打印对象的iddel pt1 del pt2 del pt3
类的继承
class Parent: # 定义父类 parentAttr = 100def __init__(self):print "调用父类构造函数"def parentMethod(self):print ‘调用父类方法‘def setAttr(self, attr):Parent.parentAttr = attr def getAttr(self):print "父类属性 :", Parent.parentAttr class Child(Parent): # 定义子类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)
- isinstance(obj, Class) 布尔函数如果obj是Class类的实例对象或者是一个Class子类的实例对象则返回true。
方法重写
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同样支持运算符重载,实例如下:
#!/usr/bin/pythonclass 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
共有属性跟私有属性
class JustCounter: __secretCount = 0 # 私有变量 publicCount = 0 # 公开变量def count(self):self.__secretCount += 1self.publicCount += 1print self.__secretCount
28.正则表达式
re.match函数
re.match(pattern, string, flags=0)
参数 | 描述 |
---|---|
pattern | 匹配的正则表达式 |
string | 要匹配的字符串。 |
flags | 标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。 |
import re print(re.match(‘www‘, ‘www.runoob.com‘).span()) # 在起始位置匹配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!!"
re.match与re.search的区别
re.match只匹配字符串的开始,如果字符串开始不符合正则表达式,则匹配失败,函数返回None;而re.search匹配整个字符串,直到找到一个匹配。
matchObj = re.search( r‘dogs‘, line, re.M|re.I)if matchObj:print "search --> matchObj.group() : ", matchObj.group()else:print "No match!!"
检索和替换
re.sub(pattern, repl, string, max=0)
返回的字符串是在字符串中用 RE 最左边不重复的匹配来替换。如果模式没有发现,字符将被没有改变地返回。
可选参数 count 是模式匹配后替换的最大次数;count 必须是非负整数。缺省值是 0 表示替换所有的匹配。
正则表达式修饰符 - 可选标志
正则表达式可以包含一些可选标志修饰符来控制匹配的模式。修饰符被指定为一个可选的标志。多个标志可以通过按位 OR(|) 它们来指定。如 re.I | re.M 被设置成 I 和 M 标志:
修饰符 | 描述 |
---|---|
re.I | 使匹配对大小写不敏感 |
re.L | 做本地化识别(locale-aware)匹配 |
re.M | 多行匹配,影响 ^ 和 $ |
re.S | 使 . 匹配包括换行在内的所有字符 |
re.U | 根据Unicode字符集解析字符。这个标志影响 \w, \W, \b, \B. |
re.X | 该标志通过给予你更灵活的格式以便你将正则表达式写得更易于理解。 |
29.访问 mysql 数据库
1)下载 Mysql-python
https://pypi.python.org/pypi/MySQL-python
2)解压安装
$ 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
3)数据库连接
#!/usr/bin/python# -*- coding: UTF-8 -*-import MySQLdb# 打开数据库连接 db = MySQLdb.connect("localhost","testuser","test123","TESTDB" )# 使用cursor()方法获取操作游标 cursor = db.cursor()# 使用execute方法执行SQL语句 cursor.execute("SELECT VERSION()")# 使用 fetchone() 方法获取一条数据库。 data = cursor.fetchone()print "Database version : %s " % data # 关闭数据库连接 db.close()
4)创建数据库表
# 打开数据库连接 db = MySQLdb.connect("localhost","testuser","test123","TESTDB" )# 使用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)
5)数据库插入数据
# 打开数据库连接 db = MySQLdb.connect("localhost","testuser","test123","TESTDB" )# 使用cursor()方法获取操作游标 cursor = db.cursor()# SQL 插入语句 sql = """INSERT INTO EMPLOYEE(FIRST_NAME, LAST_NAME, AGE, SEX, INCOME) VALUES (‘Mac‘, ‘Mohan‘, 20, ‘M‘, 2000)"""try:# 执行sql语句 cursor.execute(sql)# 提交到数据库执行 db.commit()except:# Rollback in case there is any error db.rollback()
也可以写成
# SQL 插入语句 sql = "INSERT INTO EMPLOYEE(FIRST_NAME, LAST_NAME, AGE, SEX, INCOME) VALUES (‘%s‘, ‘%s‘, ‘%d‘, ‘%c‘, ‘%d‘ )" % (‘Mac‘, ‘Mohan‘, 20, ‘M‘, 2000)
6)数据库查询
Python查询Mysql使用 fetchone() 方法获取单条数据, 使用fetchall() 方法获取多条数据。
- fetchone(): 该方法获取下一个查询结果集。结果集是一个对象
- fetchall():接收全部的返回结果行.
- rowcount: 这是一个只读属性,并返回执行execute()方法后影响的行数。
# 打开数据库连接 db = MySQLdb.connect("localhost","testuser","test123","TESTDB" )# 使用cursor()方法获取操作游标 cursor = db.cursor()# SQL 查询语句 sql = "SELECT * FROM EMPLOYEE WHERE INCOME > ‘%d‘" % (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=%d,sex=%s,income=%d" % (fname, lname, age, sex, income )except:print "Error: unable to fecth data"
7)数据库更新
# 打开数据库连接 db = MySQLdb.connect("localhost","testuser","test123","TESTDB" )# 使用cursor()方法获取操作游标 cursor = db.cursor()# SQL 更新语句 sql = "UPDATE EMPLOYEE SET AGE = AGE + 1 WHERE SEX = ‘%c‘" % (‘M‘)try:# 执行SQL语句 cursor.execute(sql)# 提交到数据库执行 db.commit()except:# 发生错误时回滚 db.rollback()
8)事务
执行事务
事务机制可以确保数据一致性。
事务应该具有4个属性:原子性、一致性、隔离性、持久性。这四个属性通常称为ACID特性。
- 原子性(atomicity)。一个事务是一个不可分割的工作单位,事务中包括的诸操作要么都做,要么都不做。
- 一致性(consistency)。事务必须是使数据库从一个一致性状态变到另一个一致性状态。一致性与原子性是密切相关的。
- 隔离性(isolation)。一个事务的执行不能被其他事务干扰。即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。
- 持久性(durability)。持续性也称永久性(permanence),指一个事务一旦提交,它对数据库中数据的改变就应该是永久性的。接下来的其他操作或故障不应该对其有任何影响。
# SQL删除记录语句 sql = "DELETE FROM EMPLOYEE WHERE AGE > ‘%d‘" % (20)try:# 执行SQL语句 cursor.execute(sql)# 向数据库提交 db.commit()except:# 发生错误时回滚 db.rollback()
9)错误处理
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的子类。 |
30.SMTP
import smtplib smtpObj = smtplib.SMTP( [host [, port [, local_hostname]]] )
参数说明:
- host: SMTP 服务器主机。 你可以指定主机的ip地址或者域名如:w3cschool.cc,这个是可选参数。
- 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: 发送消息
这里要注意一下第三个参数,msg是字符串,表示邮件。我们知道邮件一般由标题,发信人,收件人,邮件内容,附件等构成,发送邮件的时候,要注意msg的格式。这个格式就是smtp协议中定义的格式。
31.多线程
thread.start_new_thread ( function, args[, kwargs] )
参数说明:
- function - 线程函数。
- args - 传递给线程函数的参数,他必须是个tuple类型。
- kwargs - 可选参数。
#!/usr/bin/python# -*- coding: UTF-8 -*-import thread import time # 为线程定义一个函数def print_time( threadName, delay): count = 0while count < 5: time.sleep(delay) count += 1print "%s: %s" % ( threadName, time.ctime(time.time()) )# 创建两个线程try: thread.start_new_thread( print_time, ("Thread-1", 2, ) ) thread.start_new_thread( print_time, ("Thread-2", 4, ) )except:print "Error: unable to start thread"while 1:pass
thread 模块提供的其他方法:
- threading.currentThread(): 返回当前的线程变量。
- threading.enumerate(): 返回一个包含正在运行的线程的list。正在运行指线程启动后、结束前,不包括启动前和终止后的线程。
- threading.activeCount(): 返回正在运行的线程数量,与len(threading.enumerate())有相同的结果。
除了使用方法外,线程模块同样提供了Thread类来处理线程,Thread类提供了以下方法:
- run(): 用以表示线程活动的方法。
- start():启动线程活动。
- join([time]): 等待至线程中止。这阻塞调用线程直至线程的join() 方法被调用中止-正常退出或者抛出未处理的异常-或者是可选的超时发生。
- isAlive(): 返回线程是否活动的。
- getName(): 返回线程名。
- setName(): 设置线程名。
#!/usr/bin/python# -*- coding: UTF-8 -*-import threading import time exitFlag = 0class myThread (threading.Thread): #继承父类threading.Threaddef __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: 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对象的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"
线程优先级队列
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() 实际上意味着等到队列为空,再执行别的操作
#!/usr/bin/python# -*- coding: UTF-8 -*-import Queueimport 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"