python16_day08【异常、多线程】

一、反射及相关

  1.isinstance(obj, cls)

  检查是否obj是否是类 cls 的对象

class Foo(object):
    pass
 
obj = Foo()
 
isinstance(obj, Foo)

  2.issubclass(sub, super)

  检查sub类是否是 super 类的派生类

class Foo(object):
    pass
 
class Bar(Foo):
    pass
 
issubclass(Bar, Foo)

  3.反射

  python中的反射功能是由以下四个内置函数提供:hasattr、getattr、setattr、delattr,改四个函数分别用于对对象内部执行:检查是否含有某成员、获取成员、设置成员、删除成员。

 1 class Foo(object):
 2  
 3     def __init__(self):
 4         self.name = 'wupeiqi'
 5  
 6     def func(self):
 7         return 'func'
 8  
 9 obj = Foo()
10  
11 # #### 检查是否含有成员 ####
12 hasattr(obj, 'name')
13 hasattr(obj, 'func')
14  
15 # #### 获取成员 ####
16 getattr(obj, 'name')
17 getattr(obj, 'func')
18  
19 # #### 设置成员 ####
20 setattr(obj, 'age', 18)
21 setattr(obj, 'show', lambda num: num + 1)
22  
23 # #### 删除成员 ####
24 delattr(obj, 'name')
25 delattr(obj, 'func')
obj.name有三种访问方式
    obj.name
    obj.__dict__['name']
    getattr(obj, 'name')

  结论:反射是通过字符串的形式操作对象相关的成员。一切事物都是对象!!!

 1 #!/usr/bin/env python
 2 # -*- coding:utf-8 -*-
 3 
 4 import sys
 5 
 6 
 7 def s1():
 8     print 's1'
 9 
10 
11 def s2():
12     print 's2'
13 
14 
15 this_module = sys.modules[__name__]
16 
17 hasattr(this_module, 's1')
18 getattr(this_module, 's2')
 1 class Foo(object):
 2  
 3     staticField = "old boy"
 4  
 5     def __init__(self):
 6         self.name = 'wupeiqi'
 7  
 8     def func(self):
 9         return 'func'
10  
11     @staticmethod
12     def bar():
13         return 'bar'
14  
15 print getattr(Foo, 'staticField')
16 print getattr(Foo, 'func')
17 print getattr(Foo, 'bar')
反射类的字段 

二、异常处理

  在编程过程中为了增加友好性,在程序出现bug时一般不会将错误信息显示给用户,而是现实一个提示的页面,通俗来说就是不让用户看见大黄页!

while True:
    num1 = raw_input('num1:')
    num2 = raw_input('num2:')
    try:
        num1 = int(num1)
        num2 = int(num2)
        result = num1 + num2
    except Exception, e:
        print '出现异常,信息如下:'
        print e
AttributeError 试图访问一个对象没有的树形,比如foo.x,但是foo没有属性x
IOError 输入/输出异常;基本上是无法打开文件
ImportError 无法引入模块或包;基本上是路径问题或名称错误
IndentationError 语法错误(的子类) ;代码没有正确对齐
IndexError 下标索引超出序列边界,比如当x只有三个元素,却试图访问x[5]
KeyError 试图访问字典里不存在的键
KeyboardInterrupt Ctrl+C被按下
NameError 使用一个还未被赋予对象的变量
SyntaxError Python代码非法,代码不能编译(个人认为这是语法错误,写错了)
TypeError 传入对象类型与要求的不符合
UnboundLocalError 试图访问一个还未被设置的局部变量,基本上是由于另有一个同名的全局变量,
导致你以为正在访问它
ValueError 传入一个调用者不期望的值,即使值的类型是正确的
 1 ArithmeticError
 2 AssertionError
 3 AttributeError
 4 BaseException
 5 BufferError
 6 BytesWarning
 7 DeprecationWarning
 8 EnvironmentError
 9 EOFError
10 Exception
11 FloatingPointError
12 FutureWarning
13 GeneratorExit
14 ImportError
15 ImportWarning
16 IndentationError
17 IndexError
18 IOError
19 KeyboardInterrupt
20 KeyError
21 LookupError
22 MemoryError
23 NameError
24 NotImplementedError
25 OSError
26 OverflowError
27 PendingDeprecationWarning
28 ReferenceError
29 RuntimeError
30 RuntimeWarning
31 StandardError
32 StopIteration
33 SyntaxError
34 SyntaxWarning
35 SystemError
36 SystemExit
37 TabError
38 TypeError
39 UnboundLocalError
40 UnicodeDecodeError
41 UnicodeEncodeError
42 UnicodeError
43 UnicodeTranslateError
44 UnicodeWarning
45 UserWarning
46 ValueError
47 Warning
48 ZeroDivisionError
49 
50 更多异常
1 try:
2     raise Exception('错误了。。。')
3 except Exception,e:
4     print e
 1 class WupeiqiException(Exception):
 2  
 3     def __init__(self, msg):
 4         self.message = msg
 5  
 6     def __str__(self):
 7         return self.message
 8  
 9 try:
10     raise WupeiqiException('我的异常')
11 except WupeiqiException,e:
12     print e
# assert 条件
 
assert 1 == 1
 
assert 1 == 2

 

三、线程

  线程是最小工作单位,进程是资源池。

  1.直接调用

 1 import threading
 2 import time
 3  
 4 def sayhi(num): #定义每个线程要运行的函数
 5  
 6     print("running on number:%s" %num)
 7  
 8     time.sleep(3)
 9  
10 if __name__ == '__main__':
11  
12     t1 = threading.Thread(target=sayhi,args=(1,)) #生成一个线程实例
13     t2 = threading.Thread(target=sayhi,args=(2,)) #生成另一个线程实例
14  
15     t1.start() #启动线程
16     t2.start() #启动另一个线程
17  
18     print(t1.getName()) #获取线程名
19     print(t2.getName())
 1 import threading
 2 import time
 3  
 4  
 5 class MyThread(threading.Thread):
 6     def __init__(self,num):
 7         threading.Thread.__init__(self)
 8         self.num = num
 9  
10     def run(self):#定义每个线程要运行的函数
11  
12         print("running on number:%s" %self.num)
13  
14         time.sleep(3)
15  
16 if __name__ == '__main__':
17  
18     t1 = MyThread(1)
19     t2 = MyThread(2)
20     t1.start()
21     t2.start()
#_*_coding:utf-8_*_
 
import time
import threading
 
 
def run(n):
 
    print('[%s]------running----\n' % n)
    time.sleep(2)
    print('--done--')
 
def main():
    for i in range(5):
        t = threading.Thread(target=run,args=[i,])
        t.start()
        t.join(1)
        print('starting thread', t.getName())
 
 
m = threading.Thread(target=main,args=[])
m.setDaemon(True) #将main线程设置为Daemon线程,它做为程序主线程的守护线程,当主线程退出时,m线程也会退出,由m启动的其它子线程会同时退出,不管是否执行完任务
m.start()
m.join(timeout=2)
print("---main thread done----")
    • start            线程准备就绪,等待CPU调度
    • setName      为线程设置名称
    • getName      获取线程名称
    • setDaemon   设置为后台线程或前台线程(默认)
                         如果是后台线程,主线程执行过程中,后台线程也在进行,主线程执行完毕后,后台线程不论成功与否,均停止
                          如果是前台线程,主线程执行过程中,前台线程也在进行,主线程执行完毕后,等待前台线程也执行完成后,程序停止
    • join              逐个执行每个线程,执行完毕后继续往下执行,该方法使得多线程变得无意义
    • run              线程被cpu调度后自动执行线程对象的run方法

 

  2.线程锁(Lock、RLock)

    由于线程之间是进行随机调度,并且每个线程可能只执行n条执行之后,当多个线程同时修改同一条数据时可能会出现脏数据,所以,出现了线程锁 - 同一时刻允许一个线程执行操作。

 1 #!/usr/bin/env python
 2 # -*- coding:utf-8 -*-
 3 import threading
 4 import time
 5 
 6 gl_num = 0
 7 
 8 def show(arg):
 9     global gl_num
10     time.sleep(1)
11     gl_num +=1
12     print(gl_num)
13 
14 for i in range(10):
15     t = threading.Thread(target=show, args=(i,))
16     t.start()
17 
18 print('main thread stop')
未使用锁
 1 #!/usr/bin/env python
 2 #coding:utf-8
 3    
 4 import threading
 5 import time
 6    
 7 gl_num = 0
 8    
 9 lock = threading.RLock()
10    
11 def Func():
12     lock.acquire()
13     global gl_num
14     gl_num +=1
15     time.sleep(1)
16     print(gl_num)
17     lock.release()
18        
19 for i in range(10):
20     t = threading.Thread(target=Func)
21     t.start()
22 print("main thread stop")
使用锁

   3.信号量(semaphore)

     互斥锁 同时只允许一个线程更改数据,而Semaphore是同时允许一定数量的线程更改数据 ,比如厕所有3个坑,那最多只允许3个人上厕所,后面的人只能等里面有人出来了才能再进去

  

  4.事件(event)

  python线程的事件用于主线程控制其他线程的执行,事件主要提供了三个方法 set、wait、clear。

  事件处理的机制:全局定义了一个“Flag”,如果“Flag”值为 False,那么当程序执行 event.wait 方法时就会阻塞,如果“Flag”值为True,

  那么event.wait 方法时便不再阻塞。

  clear 将flag设置为False

  set 将flag设置为True

 1 import threading
 2  
 3  
 4 def do(event):
 5     print 'start'
 6     event.wait()
 7     print 'execute'
 8  
 9  
10 event_obj = threading.Event()
11 for i in range(10):
12     t = threading.Thread(target=do, args=(event_obj,))
13     t.start()
14  
15 event_obj.clear()
16 inp = raw_input('input:')
17 if inp == 'true':
18     event_obj.set()

  5.条件(Condition)

   使得线程等待,只有满足某条件时,才释放n个线程

 1 import threading
 2  
 3 def run(n):
 4     con.acquire()
 5     con.wait()
 6     print("run the thread: %s" %n)
 7     con.release()
 8  
 9 if __name__ == '__main__':
10  
11     con = threading.Condition()
12     for i in range(10):
13         t = threading.Thread(target=run, args=(i,))
14         t.start()
15  
16     while True:
17         inp = input('>>>')
18         if inp == 'q':
19             break
20         con.acquire()
21         con.notify(int(inp))
22         con.release()

  6.线程池

 1 from concurrent.futures import ThreadPoolExecutor
 2 import requests
 3 
 4 
 5 def task(url):
 6     response = requests.get(url)
 7     print("得到结果:", url, len(response.content))
 8 
 9 url_list = [
10     'http://www.baidu.com',
11     'http://www.sina.com.cn',
12     'http://www.autohome.com.cn'
13     ]
14 
15 pool = ThreadPoolExecutor(2)
16 
17 for url in url_list:
18     print("请求开始", url)
19     pool.submit(task, url)

 

四、进程

 1 from multiprocessing import Process
 2 import threading
 3 import time
 4   
 5 def foo(i):
 6     print('say hi',i)
 7   
 8 for i in range(10):
 9     p = Process(target=foo, args=(i,))
10     p.start()

注意:由于进程之间的数据需要各自持有一份,所以创建进程需要的非常大的开销。

 

  1.进程数据共享

  进程各自持有一份数据,默认无法共享数据

 1 from multiprocessing import Process
 2  
 3 import time
 4  
 5 li = []
 6  
 7 def foo(i):
 8     li.append(i)
 9     print('say hi',li)
10   
11 for i in range(10):
12     p = Process(target=foo, args=(i,))
13     p.start()
14      
15 print 'ending',li
 1 #方法一,Array
 2 from multiprocessing import Process,Array
 3 
 4 temp = Array('i', [11,22,33,44])
 5  
 6 def Foo(i):
 7     temp[i] = 100+i
 8     for item in temp:
 9         print i,'----->',item
10  
11 for i in range(2):
12     p = Process(target=Foo, args=(i,))
13     p.start()
14  
方法一
 1 #方法二:manage.dict()共享数据
 2 from multiprocessing import Process,Manager
 3  
 4 manage = Manager()
 5 dic = manage.dict()
 6  
 7 def Foo(i):
 8     dic[i] = 100+i
 9     print(dic.values())
10  
11 for i in range(2):
12     p = Process(target=Foo, args=(i,))
13     p.start()
14     p.join()
方法二

  2.进程锁  

 1 from multiprocessing import Process, Array, RLock
 2 
 3 def Foo(lock, temp, i):
 4     """
 5     将第0个数加100
 6     """
 7     lock.acquire()
 8     temp[0] = 100+i
 9     for item in temp:
10         print(i,'----->',item)
11     lock.release()
12 
13 lock = RLock()
14 temp = Array('i', [11, 22, 33, 44])
15 
16 for i in range(20):
17     p = Process(target=Foo, args=(lock, temp, i,))
18     p.start()

  3.进程池

 1 from concurrent.futures import ProcessPoolExecutor
 2 
 3 
 4 def task(arg):
 5     print(arg)
 6     return arg + 100
 7 
 8 
 9 def call(arg):
10     data = arg.result()
11     print(data)
12 
13 
14 if __name__ == '__main__':
15     pool = ProcessPoolExecutor(5)
16     for i in range(10):
17         obj = pool.submit(task, i)
18         obj.add_done_callback(call)

 

五、协程

  线程和进程的操作是由程序触发系统接口,最后的执行者是系统;协程的操作则是程序员。

  协程存在的意义:对于多线程应用,CPU通过切片的方式来切换线程间的执行,线程切换时需要耗时(保存状态,下次继续)。

  协程,则只使用一个线程,在一个线程中规定某个代码块执行顺序。

  协程的适用场景:当程序中存在大量不需要CPU的操作时(IO),适用于协程;

  1.greenlet

 1 from greenlet import greenlet
 2 
 3 def test1():
 4     print(12)
 5     gr2.switch()
 6     print(34)
 7     gr2.switch()
 8 
 9 
10 def test2():
11     print(56)
12     gr1.switch()
13     print(78)
14 
15 gr1 = greenlet(test1)
16 gr2 = greenlet(test2)
17 gr1.switch()

  2.gevent

 1 from gevent import monkey;monkey.patch_all()
 2 import gevent
 3 import requests
 4 
 5 
 6 def f(url):
 7     print('GET: %s' % url)
 8     resp = requests.get(url)
 9     print('%s bytes received from %s' % (resp.status_code, url))
10 
11 gevent.joinall([
12         gevent.spawn(f, 'http://www.baidu.com/'),
13         gevent.spawn(f, 'http://www.sina.com.cn/'),
14 ])

 

posted @ 2017-03-16 11:39  willianflasky  阅读(220)  评论(0编辑  收藏  举报