1.计算机的发展史
看alex的博客吧,了解一下可以了
2.线程与GIL简介
#线程 #一道单一的指令的控制流,寄生在进程中 #单一进程里的多个线程是共享数据的 #多个线程涉及修改共享数据的时候需要枷锁,看的时候不需要 #GIL global interperter lock 全局锁 #有多少个cpu,启动多少个线程,python执行的时候只会在同一时刻只允许一个线程运行
3.多线程的写法
#多线程代码 简单 # import threading # import time # def run(n): # time.sleep(1) # print('thread>>>:',n) # # t1 = threading.Thread(target=run,args=(1,)) #分支线程 # t1.start() # print('----------------fengexian') #主线 因为主线更快,所以先显示 # t2 = threading.Thread(target=run,args=(2,))#分之线程 # t2.start() #多线程代码 并发量高 # print("多线程代码 并发量高") # import threading # import time # def run(n): # time.sleep(1) # print('thread>>>:',n) # for i in range(10): # t = threading.Thread(target=run,args=(i,)) # t.start() #多线程代码里面一些常用语句 # import threading # import time # def run(n): # time.sleep(1) # print(threading.get_ident()) #可以理解一个线程号,但是在该线程中唯一的,但是在系统中不一定唯一 # print('thread>>>:',n) # print(threading.current_thread()) 打印当前正在运行线程的实例 # for i in range(10): # t = threading.Thread(target=run,args=(i,)) # t.start() # t.setName("t-"%i) 更改线程名 # print(t.getName()) #线程名 # print(threading.active_count()) #活跃的线程数统计 # print(threading.current_thread()) 打印主线程的实例 #主线程死了相当于程序退出了,其他的线程是平行的。所以没关系
4.通过类的方式继承启用多线程
#通过类的方式继承启用多线程 一般不这么写 # print("#通过类的方式继承启用多线程") # class MyThread(threading.Thread): # def __init__(self, num): # threading.Thread.__init__(self) # self.num = num # def run(self): # 定义每个线程要运行的函数 # print("running on number:%s" % self.num) # time.sleep(3) # if __name__ == '__main__': # t1 = MyThread(1) # t2 = MyThread(2) # t1.start() # t2.start()
5.线程等待,就是主线程需要等待分支线程结束才继续执行
#线程等待 # import threading # import time # def run(n): # time.sleep(1) # print("thread:::",n) # a_list = [] # for i in range(10): # a = threading.Thread(target=run,args=(i,)) # a.start() # a_list.append(a) # # a.join() #相当于串行 但是我需要线程都结束才走主线程 # for a in a_list: # a.join() #把等待线程结束放这里,相当于等待全部线程结束 # #必须用for循环,直接放在外面不能保证每个线程都执行完 # print("--main thread--")
6.守护线程,当主线程挂了,分支线程也会相应的结束
#主线程死了,线程就该停了 守护进程的概念 # import threading # import time # def run(n): # time.sleep(1) # print("thread:::",n) # for i in range(10): # a = threading.Thread(target=run,args=(i,)) # a.setDaemon(True) #设置为守护线程 当主线程执行完,不管线程结没结束都退出 # a.start() # print("--main thread--")
7.线程锁(普通锁LOCK,递归锁RLOCK),为了避免出现同时更改一个共享数据发生错乱
#线程锁 防止多个线程修改同一个共享数据 #一个进程下可以启动多个线程,多个线程共享父进程的内存空间,也就意味着每个线程可以访问同一份数据,此时,如果2个线程同时要修改同一份数据,会出现什么状况? #此代码没有出现混乱的问题,就是本来应该是10而显示只有 8 9 这个样子 #一定要加锁 # import threading # import time # def run(n): # global num # l.acquire() #获取锁 # num +=1 # time.sleep(1) #修改完数据之后,立刻就把锁释放,因为只要你一锁,只要全局需要等你的数据,就整个程序卡住了,就出现串行了 # l.release() #释放锁 # # time.sleep(1) #如果把这个放到释放锁上面,那就成为串行了。 # print("thread:::",n) # # def run2(): # count = 0 # while num<9: # print('-----',count) # count += 1 # # num = 0 # l = threading.Lock() #声明一把锁 # a_list = [] # for i in range(10): # a = threading.Thread(target=run,args=(i,)) # a.start() # a_list.append(a) # # a2 = threading.Thread(target=run2) # a2.start() # for t in a_list: # t.join() # # print("--main thread--") # print(num) #RLock(递归锁)就是在一个大锁中还要再包含子锁 # import threading, time # # def run1(): # print("grab the first part data") # lock.acquire() # global num # num += 1 # lock.release() # return num # # def run2(): # print("grab the second part data") # lock.acquire() # global num2 # num2 += 1 # lock.release() # return num2 # # def run3(): # lock.acquire() # res = run1() # print('--------between run1 and run2-----') # res2 = run2() # lock.release() # print(res, res2) # # if __name__ == '__main__': # # num, num2 = 0, 0 # lock = threading.RLock() #如果Rlock 换成lock 就会错乱了 # for i in range(10): # t = threading.Thread(target=run3) # t.start() # # while threading.active_count() != 1: # print(threading.active_count()) # else: # print('----all threads done---') # print(num, num2)
8.GIL全局解释其锁和用户级别的Lock的区别
#GIL VS LOCK #GIL 全局解释器锁,作用是保证在同一时刻只有一个线程真正在运行 #GIL 解释器自己的锁,为了解决内存回收机制,很有可能当内存清除的时候会有线程调用它才加的锁 #GIL 和用户Lock是不一样的锁,没有任何关系
9.信号量
# Semaphore(信号量) # 互斥锁 同时只允许一个线程更改数据,而Semaphore是同时允许一定数量的线程更改数据 ,比如厕所有3个坑,那最多只允许3个人上厕所,后面的人只能等里面有人出来了才能再进去。 #改代码执行后结果为五个五个出 # import threading, time # def run(n): # semaphore.acquire() # time.sleep(1) # print("run the thread: %s\n" % n) # semaphore.release() # # if __name__ == '__main__': # # num = 0 # semaphore = threading.BoundedSemaphore(5) # 最多允许5个线程同时运行 # for i in range(20): # t = threading.Thread(target=run, args=(i,)) # t.start() # # while threading.active_count() != 1: # pass # print threading.active_count() # else: # print('----all threads done---') # print(num)
10.定时任务
#定时任务 Timer 3秒之后运行这个线程 # import threading # def hello(): # print("hello, world") # # t = threading.Timer(3.0, hello) # t.start() # after 30 seconds, "hello, world" will be printed
11.events 线程间的交互
#Events 线程间的交互 #通过Event来实现两个或多个线程间的交互,下面是一个红绿灯的例子,即起动一个线程做交通指挥灯,生成几个线程做车辆,车辆行驶按红灯停,绿灯行的规则。 #可以当做线程内部的一个标志,当这个标志发生变化,就说明该线程干完了 #红绿灯 # import threading,time # # def ligher(): # count = 0 # while True: # if count < 30: # if not event.is_set(): #如果没被set我就set # event.set() # print("\033[32m;green light\033[0m") # elif count < 34: # print("\033[33m;yellow light\033[0m") # elif count < 60: # if event.is_set(): # event.clear() # print("\033[31m;red light\033[0m") # else: # count = 0 # count += 1 # time.sleep(0.2) # def car(n): # count = 0 # while True: # event.wait() # print("car [%s] dududu..." % n) # count += 1 # time.sleep(1) # # event = threading.Event() # t = threading.Thread(target=ligher) # t.start() # c1 = threading.Thread(target=car,args=(1,)) # c1.start()
12.队列
#队列 Queue #先进先出 FIFO first in first out 常规 #后入先出 last in first out #不按顺序出,优先级 #先进先出队列 # import queue # q = queue.Queue() # q.put(1) # q.put(2) # q.put(3) # q.put('alex') # print(q.qsize()) #数量 # print(q.get()) #取数 # print(q.empty()) #做一个判断是不是空而已不是清空 # print(q.get()) # print(q.full()) #判断队列会不会满 如果满了,就会阻塞了,q = queue.Queue(maxsize=2),等于2的时候就会返回TRUE # q.put_nowait(4) #如果满了就直接报错了 #先进后出队列 # import queue # q = queue.LifoQueue() # q.put(1) # q.put(2) # q.put(3) # q.put('alex') # print(q.get()) #优先级队列 # import queue # q = queue.PriorityQueue() # q.put([3,'joker']) # q.put([2,'lili']) # q.put([1,'alex']) # print(q.get()) #1 2 3代表优先级,数字越小权重越大 列表,元祖都可以
13.生产者与消费者模型 就是为了解决供不应求,供过于求的时候
#生产者消费者模型 就是为了解决 线程产生和处理线程的速度不一致问题 #在并发编程中使用生产者和消费者模式能够解决绝大多数并发问题。该模式通过平衡生产线程和消费线程的工作能力来提高程序的整体处理数据的速度。 #为什么要使用生产者和消费者模式 #在线程世界里,生产者就是生产数据的线程,消费者就是消费数据的线程。在多线程开发当中,如果生产者处理速度很快,而消费者处理速度很慢,那么生产者就必须等待消费者处理完,才能继续生产数据 #同样的道理,如果消费者的处理能力大于生产者,那么消费者就必须等待生产者。为了解决这个问题于是引入了生产者和消费者模式。 #什么是生产者消费者模式 #生产者消费者模式是通过一个容器来解决生产者和消费者的强耦合问题。 #生产者和消费者彼此之间不直接通讯,而通过阻塞队列来进行通讯,所以生产者生产完数据之后不用等待消费者处理,直接扔给阻塞队列,消费者不找生产者要数据,而是直接从阻塞队列里取,阻塞队列就相当于一个缓冲区,平衡了生产者和消费者的处理能力。 #吃骨头 #就是为了解决供不应求,供大于求,最大一个特点程序解耦合,添加生产者不会影响消费者,添加消费者不会影响生产者。提高程序运行效率 # import threading,time # import queue # def producer(name): # count = 0 # while True: # if q.qsize() < 5: # print("%s生成了骨头" %name,count) # q.put(count) # count+=1 # time.sleep(3) # # def consumer(n): # while True: # print("%s 取到骨头并吃了它" % n, q.get()) # time.sleep(0.5) # # q = queue.Queue(maxsize=4) # # p = threading.Thread(target=producer,args=('joker',)) # p2 = threading.Thread(target=producer,args=('alex',)) # c = threading.Thread(target=consumer,args=('lili',)) # p.start() # p2.start() # c.start() #消费完任务之后都要给生产者回执,当生产者回执都结束了,就可以结束了 例如发邮件 转账 # import threading,time # import queue # def producer(name): # count = 0 # for i in range(10): # print("%s生成了骨头" %name,count) # q.put(count) # count+=1 # time.sleep(0.3) # q.join() # print("所有骨头都被吃了") # def consumer(n): # while True: # print("%s 取到骨头并吃了它" % n, q.get()) # time.sleep(0.5) # q.task_done() # 代表我吃完了,就像邮件回执,代表你肯定吃了,肯定回执邮件,这个任务你干完了 # q = queue.Queue(maxsize=4) # p = threading.Thread(target=producer,args=('joker',)) # c = threading.Thread(target=consumer,args=('lili',)) # p.start() # c.start()
14.多进程
#多进程multiprocessing #绕过GIL 例子。八核八个进程,每个进程是个线程 # from multiprocessing import Process # import time # # def f(name): # time.sleep(2) # print('hello', name) # # if __name__ == '__main__': # for i in range(10): # p = Process(target=f, args=('bob',)) # p.start() # # p.join() #打开就是串行出来hello bob #多进程的用法 # from multiprocessing import Process # import os,time # def info(title): # print(title) # print('module name:', __name__) # print('parent process:', os.getppid()) #父id # print('process id:', os.getpid()) #当前Id # print("\n\n") # # def f(name): # info('\033[31;1mfunction f\033[0m') # print('hello', name) # time.sleep(10) # # if __name__ == '__main__': # info('\033[32;1mmain process line\033[0m') # p = Process(target=f, args=('bob',)) # p.start() # p.join()
15.进程间通讯,Queue,pipe 进程数据交互,并没有改变数据,真正可以改变数据的用manager
#进程间通讯 #不同进程间内存是不共享的,要想实现两个进程间的数据交换,可以用以下方法: #Queues 使用方法跟threading里的queue差不多 但是线程内存共享的,进程不行 # from multiprocessing import Process, Queue # # def f(q): # q.put([42, None, 'hello']) # # if __name__ == '__main__': # q = Queue() # p = Process(target=f, args=(q,)) # p.start() # print(q.get()) # prints "[42, None, 'hello']" # p.join() #Pipes 管道 儿子发,父亲收 当然也可以双向,2个进程间通信 # from multiprocessing import Process, Pipe # # def f(conn): # conn.send([42, None, 'hello']) #这里需要注意,发送数据多次没有什么问题,但是要是收的时候没有数据就会卡住 # print("from parent",conn.recv()) #双向 # conn.close() # # if __name__ == '__main__': # parent_conn, child_conn = Pipe() #生成管道 # p = Process(target=f, args=(child_conn,)) # p.start() # print(parent_conn.recv()) # prints "[42, None, 'hello']" # parent_conn.send("hello son") #双向 # p.join() #Queues 和 Pipe 解决了2个进程间的传递并没有解决2个进程之间修改数据 #Manager # from multiprocessing import Process, Manager # # def f(d, l,): #def f(d, l, n,): 加n为了字典效果 # # d[n] = n #为了字典效果 # d[1] = '1' # d['2'] = 2 # d[0.25] = None # l.append(2) #每次进程加个2 # #l.append(n) 为了字典效果 # print(l) # # if __name__ == '__main__': # with Manager() as manager: #打开manager # d = manager.dict() #生成一个字典 # # l = manager.list(range(5)) #就是生成了五个列表值 [0, 1, 2, 3, 4] # p_list = [] # for i in range(10): # p = Process(target=f, args=(d, l)) # # p = Process(target=f, args=(d, l, i,)) 为了字典效果 # p.start() # p_list.append(p) # # for res in p_list: # res.join() # # print(d) # print(l)
16.进程同步
#进程同步 就是Lock 进程数据独立为什么还需要锁呢 #因为共享一个屏幕,可能输出会乱,加了锁,输出显示就没问题,输入文件也要加锁 # from multiprocessing import Process, Lock # # def f(l, i): # l.acquire() # try: # print('hello world', i) # finally: # l.release() # # if __name__ == '__main__': # lock = Lock() # # for num in range(10): # Process(target=f, args=(lock, num)).start() 进程自己把锁传进去
17.进程池
进程池 就是同一时间只有多少个进程运行 #进程池内部维护一个进程序列,当使用时,则去进程池中获取一个进程,如果进程池序列中没有可供使用的进进程,那么程序就会等待,直到进程池中有可用进程为止。 # 进程池中有两个方法: # apply 是串行 ,不要用 # apply_async # from multiprocessing import Process, Lock, Pool # import time # # def f(num): # print('hello world %s' % num) # time.sleep(1) # return num #返回值告诉主进程我子进程运行结束了么 # # def callback(data): #这个就是上面f函数的返回值 他的pid永远都是一个,所以只维护一个连接就可以 # print("exec-->:",data) # # if __name__ == '__main__': # lock = Lock() # # pool = Pool(processes=5) # # for num in range(100): # pool.apply_async(func=f, args=(num,),callback=callback) # pool.close() #添加完了必须告诉程序地址池我加完了 # pool.join() #进程池中进程执行完毕后再关闭,如果注释,那么程序直接关闭。
18.paramiko 简单的ssh模块
#paramiko 模块 import paramiko # 创建SSH对象 ssh = paramiko.SSHClient() # 允许连接不在know_hosts文件中的主机 ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) #第一次连接在不在自己本机上,不在自己就加上去 # 连接服务器 ssh.connect(hostname=') # 执行命令 返回三个值 stdin, stdout, stderr = ssh.exec_command('df') # 获取命令结果 result = stdout.read() print(result.decode()) # 关闭连接 ssh.close()