网络编程

72 阅读6分钟

开启进程的两种方式

 #方式一:
 from multiprocessing import Process
 import time
 
 def task(name):
 print('%s is running' %name)
 time.sleep(3)
 print('%s is done' %name)
 
 if __name__ == '__main__':
  Process(target=task,kwargs={'name':'子进程1'})
 p=Process(target=task,args=('子进程1',))
 p.start() #仅仅只是给操作系统发送了一个信号
 
 print('主')
*#方式二***
from multiprocessing import Process
import time

class MyProcess(Process):
    def __init__(self,name):
        super().__init__()
        self.name=name

    def run(self):
        print('%s is running' %self.name)
        time.sleep(3)
        print('%s is done' %self.name)


if __name__ == '__main__':
    p=MyProcess('子进程1')
    p.start()
    print('主')

守护进程

from multiprocessing import Process
import time


def task(name):
    print('%s is running' %name)
    time.sleep(2)
    p=Process(target=time.sleep,args=(3,))
    p.start()


if __name__ == '__main__':
    p=Process(target=task,args=('子进程1',))
    p.daemon=True
    p.start()

    p.join()
    print('主')

#互斥锁,可以对局部代码,即共享数据进行加锁,使其串性执行,而join 则是只能对全局代码实行串行

from multiprocessing import Process,Lock
import time

def task(name,mutex):
    mutex.acquire()
    print('%s 1' %name)
    time.sleep(1)
    print('%s 2' %name)
    time.sleep(1)
    print('%s 3' %name)
    mutex.release()

if __name__ == '__main__':
    mutex = Lock()
    for i in range(3):
        p=Process(target=task,args=('进程%s' %i,mutex))
        p.start()

#抢票系统

import json
import time

def search(name):
    time.sleep(1)
    dic=json.load(open('db.txt','r',encoding='utf-8'))
    print('<%s> 查看到剩余票数【%s】' %(name,dic['count']))


def get(name):
    time.sleep(1)
    dic=json.load(open('db.txt','r',encoding='utf-8'))
    if dic['count'] > 0:
        dic['count']-=1
        time.sleep(3)
        json.dump(dic,open('db.txt','w',encoding='utf-8'))
        print('<%s> 购票成功' %name)


def task(name,mutex):
    search(name)
    mutex.acquire()
    get(name)
    mutex.release()

if __name__ == '__main__':
    mutex=Lock()
    for i in range(10):
        p=Process(target=task,args=('路人%s' %i,mutex))
        p.start()

#队列


q=Queue(3)

q.put('hello')
q.put({'a':1})
q.put([3,3,3,])
print(q.full())

# q.put(4)

print(q.get())
print(q.get())
print(q.get())
print(q.empty())

print(q.get())

JoinableQueue(生成者消费者模型)

import time

def producer(q):
    for i in range(2):
        res='包子%s' %i
        time.sleep(0.5)
        print('生产者生产了%s' %res)

        q.put(res)
    q.join()

def consumer(q):
    while True:
        res=q.get()
        if res is None:break
        time.sleep(1)
        print('消费者吃了%s' % res)
        q.task_done()


if __name__ == '__main__':
    #容器
    q=JoinableQueue()

    #生产者们
    p1=Process(target=producer,args=(q,))
    p2=Process(target=producer,args=(q,))
    p3=Process(target=producer,args=(q,))

    #消费者们
    c1=Process(target=consumer,args=(q,))
    c2=Process(target=consumer,args=(q,))
    c1.daemon=True
    c2.daemon=True

    p1.start()
    p2.start()
    p3.start()
    c1.start()
    c2.start()


    p1.join()
    p2.join()
    p3.join()
    print('主')

#开线程的两个方式

import random
from threading import Thread

def piao(name):
    print('%s piaoing' %name)
    time.sleep(random.randrange(1,5))
    print('%s piao end' %name)

if __name__ == '__main__':
    t1=Thread(target=piao,args=('egon',))
    t1.start()
    print('主线程')



import time
import random
from threading import Thread

class MyThread(Thread):
    def __init__(self,name):
        super().__init__()
        self.name=name

    def run(self):
        print('%s piaoing' %self.name)

        time.sleep(random.randrange(1,5))
        print('%s piao end' %self.name)

if __name__ == '__main__':
    t1=MyThread('egon')
    t1.start()
    print('主')

守护线程--要等到所有线程全程结束后才结束

import time

def foo():
    print(123)
    time.sleep(1)
    print("end123")

def bar():
    print(456)
    time.sleep(3)
    print("end456")

if __name__ == '__main__':
    t1=Thread(target=foo)
    t2=Thread(target=bar)

    t1.daemon=True
    t1.start()
    t2.start()
    print("main-------")

    '''
    123
    456
    main-------
    end123
    end456
    
    '''

互斥锁,死锁,递归锁GIL-解析器锁

from threading import Thread,Lock
import time

mutexA=Lock()
mutexB=Lock()

class MyThread(Thread):
    def run(self):
        self.f1()
        self.f2()

    def f1(self):
        mutexA.acquire()
        print('%s 拿到了A锁' %self.name)

        mutexB.acquire()
        print('%s 拿到了B锁' %self.name)
        mutexB.release()

        mutexA.release()


    def f2(self):
        mutexB.acquire()
        print('%s 拿到了B锁' % self.name)
        time.sleep(0.1)

        mutexA.acquire()
        print('%s 拿到了A锁' % self.name)
        mutexA.release()

        mutexB.release()

if __name__ == '__main__':
    for i in range(10):
        t=MyThread()
        t.start()


互斥锁只能acquire一次
from threading import Thread,Lock

mutexA=Lock()

mutexA.acquire()
mutexA.release()


递归锁:可以连续acquire多次,每acquire一次计数器+1,只有计数为0时,才能被抢到acquire
from threading import Thread,RLock
import time

mutexB=mutexA=RLock()

class MyThread(Thread):
    def run(self):
        self.f1()
        self.f2()

    def f1(self):
        mutexA.acquire()
        print('%s 拿到了A锁' %self.name)

        mutexB.acquire()
        print('%s 拿到了B锁' %self.name)
        mutexB.release()

        mutexA.release()


    def f2(self):
        mutexB.acquire()
        print('%s 拿到了B锁' % self.name)
        time.sleep(7)

        mutexA.acquire()
        print('%s 拿到了A锁' % self.name)
        mutexA.release()

        mutexB.release()

if __name__ == '__main__':
    for i in range(10):
        t=MyThread()
        t.start()

**信号量 **互斥锁同一时间只能有一把锁,信号量同一时间可以有多把锁

import time,random

sm=Semaphore(3)

def task():
    # sm.acquire()
    # print('%s in' %currentThread().getName())
    # sm.release()
    with sm:
        print('%s in' %currentThread().getName())
        time.sleep(random.randint(1,3))


if __name__ == '__main__':
    for i in range(10):
        t=Thread(target=task)
        t.start()

event事务-线程之间相互控制

# import time
#
# event=Event()
# # event.wait()
# # event.set()
#
# def student(name):
#     print('学生%s 正在听课' %name)
#     event.wait(2)
#     print('学生%s 课间活动' %name)
#
# def teacher(name):
#     print('老师%s 正在授课' %name)
#     time.sleep(7)
#     event.set()
#
# if __name__ == '__main__':
#     stu1=Thread(target=student,args=('alex',))
#     stu2=Thread(target=student,args=('wxx',))
#     stu3=Thread(target=student,args=('yxx',))
#     t1=Thread(target=teacher,args=('egon',))
#
#     stu1.start()
#     stu2.start()
#     stu3.start()
#     t1.start()

from threading import Thread,Event,currentThread
import time

event=Event()

def conn():
    n=0
    while not event.is_set():
        if n == 3:
            print('%s try too many times' %currentThread().getName())
            return
        print('%s try %s' %(currentThread().getName(),n))
        event.wait(0.5)
        n+=1

    print('%s is connected' %currentThread().getName())

def check():
    print('%s is checking' %currentThread().getName())
    time.sleep(1)
    event.set()

if __name__ == '__main__':
    for i in range(3):
        t=Thread(target=conn)
        t.start()
    t=Thread(target=check)
    t.start()

定时器——应用于验证码的定时刷新

# from threading import Timer
#
# def task(name):
#     print('hello %s' %name)
#
# t=Timer(5,task,args=('egon',))
# t.start()

from threading import Timer
import random

class Code:
    def __init__(self):
        self.make_cache()

    def make_cache(self,interval=5):
        self.cache=self.make_code()
        print(self.cache)
        self.t=Timer(interval,self.make_cache)
        self.t.start()

    def make_code(self,n=4):
        res=''
        for i in range(n):
            s1=str(random.randint(0,9))
            s2=chr(random.randint(65,90))
            res+=random.choice([s1,s2])
        return res

    def check(self):
        while True:
            code=input('请输入你的验证码>>: ').strip()
            if code.upper() == self.cache:
                print('验证码输入正确')
                self.t.cancel()
                break
obj=Code()
obj.check()

线程queque

import queue

q=queue.Queue(3) #先进先出->队列

q.put('first')
q.put(2)
q.put('third')
# q.put(4)
# q.put(4,block=False) #q.put_nowait(4)
# q.put(4,block=True,timeout=3)

print(q.get())
print(q.get())
print(q.get())
# print(q.get(block=False)) #q.get_nowait()
# print(q.get_nowait())

# print(q.get(block=True,timeout=3))

q=queue.LifoQueue(3) #后进先出->堆栈
q.put('first')
q.put(2)
q.put('third')

print(q.get())
print(q.get())
print(q.get())

q=queue.PriorityQueue(3) #优先级队列

q.put((10,'one'))
q.put((40,'two'))
q.put((30,'three'))

print(q.get())
print(q.get())
print(q.get())

进程池线程池

# from concurrent.futures import ProcessPoolExecutor,ThreadPoolExecutor
# import os,time,random
#
# def task(name):
#     print('name:%s pid:%s run' %(name,os.getpid()))
#     time.sleep(random.randint(1,3))
#
#
# if __name__ == '__main__':
#     # pool=ProcessPoolExecutor(4)
#     pool=ThreadPoolExecutor(5)
#
#     for i in range(10):
#         pool.submit(task,'egon%s' %i)
#
#     pool.shutdown(wait=True)
#
#     print('主')

from concurrent.futures import ProcessPoolExecutor,ThreadPoolExecutor
from threading import currentThread
import os,time,random

def task():
    print('name:%s pid:%s run' %(currentThread().getName(),os.getpid()))
    time.sleep(random.randint(1,3))

if __name__ == '__main__':
    pool=ThreadPoolExecutor(5)

    for i in range(10):
        pool.submit(task,)

    pool.shutdown(wait=True)

    print('主')

异步调用与回调机制

#提交任务的两种方式
#1、同步调用:提交完任务后,就在原地等待任务执行完毕,拿到结果,再执行下一行代码,导致程序是串行执行
#
# from concurrent.futures import ThreadPoolExecutor
# import time
# import random
#
# def la(name):
#     print('%s is laing' %name)
#     time.sleep(random.randint(3,5))
#     res=random.randint(7,13)*'#'
#     return {'name':name,'res':res}
#
# def weigh(shit):
#     name=shit['name']
#     size=len(shit['res'])
#     print('%s 拉了 《%s》kg' %(name,size))
#
#
# if __name__ == '__main__':
#     pool=ThreadPoolExecutor(13)
#
#     shit1=pool.submit(la,'alex').result()
#     weigh(shit1)
#
#     shit2=pool.submit(la,'wupeiqi').result()
#     weigh(shit2)
#
#     shit3=pool.submit(la,'yuanhao').result()
#     weigh(shit3)


#2、异步调用:提交完任务后,不地等待任务执行完毕,

from concurrent.futures import ThreadPoolExecutor
import time
import random

def la(name):
    print('%s is laing' %name)
    time.sleep(random.randint(3,5))
    res=random.randint(7,13)*'#'
    return {'name':name,'res':res}


def weigh(shit):
    shit=shit.result()
    name=shit['name']
    size=len(shit['res'])
    print('%s 拉了 《%s》kg' %(name,size))


if __name__ == '__main__':
    pool=ThreadPoolExecutor(13)

    pool.submit(la,'alex').add_done_callback(weigh)

    pool.submit(la,'wupeiqi').add_done_callback(weigh)

    pool.submit(la,'yuanhao').add_done_callback(weigh)

爬虫-线程池并发回调下载

from concurrent.futures import ThreadPoolExecutor
import requests
import time

def get(url):
    print('GET %s' %url)
    response=requests.get(url)
    time.sleep(3)
    return {'url':url,'content':response.text}


def parse(res):
    res=res.result()
    print('%s parse res is %s' %(res['url'],len(res['content'])))


if __name__ == '__main__':
    urls=[
        'http://www.cnblogs.com/linhaifeng',
        'https://www.python.org',
        'https://www.openstack.org',
    ]

    pool=ThreadPoolExecutor(2)

    for url in urls:
        pool.submit(get,url).add_done_callback(parse)

#基于线程池实现通讯--控制客户端数量,达到优化运行效率

from socket import *
from concurrent.futures import ThreadPoolExecutor

def communicate(conn):
    while True:
        try:
            data=conn.recv(1024)
            if not data:break
            conn.send(data.upper())
        except ConnectionResetError:
            break

    conn.close()

def server(ip,port):
    server = socket(AF_INET, SOCK_STREAM)
    server.bind((ip,port))
    server.listen(5)

    while True:
        conn, addr = server.accept()
        pool.submit(communicate,conn)

    server.close()

if __name__ == '__main__':
    pool=ThreadPoolExecutor(2)
    server('127.0.0.1', 8081)

协程是用户态的轻量级线程,协程即由用户程序自己控制调用

1.必须在单线程下实现并发
2.修改共享数据不许加锁
3.控制来回切
4.自动监控,遇到io再切(gevent)
#并发执行
import time

def producer():
    g=consumer()
    next(g)
    for i in range(10000000):
        g.send(i)



def consumer():
    while True:
        res=yield


start_time=time.time()
producer()
stop_time=time.time()
print(stop_time-start_time)

#串行
import time

def producer():
    res=[]
    for i in range(10000000):
        res.append(i)
    return res


def consumer(res):
    pass

start_time=time.time()
res=producer()
consumer(res)
stop_time=time.time()
print(stop_time-start_time)

gevent模块监控io实现协程

from gevent import monkey;monkey.patch_all()
import gevent
import time

def eat(name):
    print('%s eat 1' % name)
    time.sleep(3)
    print('%s eat 2' % name)

def play(name):
    print('%s play 1' % name)
    time.sleep(4)
    print('%s play 2' % name)

g1=gevent.spawn(eat,'egon')
g2=gevent.spawn(play,'alex')

# time.sleep(5)

# g1.join()
# g2.join()

gevent.joinall([g1,g2])