python学习日志--day10

一、笔记

1、IO操作不占用cpu

2、计算占用cpu

3、python多线程,不适合cpu密集操作型的任务,适合IO操作密集型的任务


二、多进程(multiprocessing)

from multiprocessing import Process
import os

# 子进程要执行的代码
def run_proc(name):
    print ('Run child process %s (%s)...' % (name, os.getpid()))

if __name__=='__main__':
    print ('Parent process %s.' % os.getpid())
    p = Process(target=run_proc, args=('test',))
    print ('Process will start.')
    p.start()
    p.join()
    print ('Process end.')

输出结果



from multiprocessing import Process
import os


def info(title):
    print(title)
    print('module name:', __name__)
    print('parent process:', os.getppid())
    print('process id:', os.getpid())
    print("\n\n")


def f(name):
    info('\033[31;1mcalled from child process function f\033[0m')
    print('hello', name)

if __name__ == '__main__':
    info('\033[32;1mmain process line\033[0m')
    p = Process(target=f, args=('bob',))
    p.start()

输出结果



进程间通信(不同进程间内存是不共享的

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()

输出结果



进程池

  • apply
  • apply_async
from  multiprocessing import Process, Pool,freeze_support
import time
import os

def Foo(i):
    time.sleep(2)
    print("in process",os.getpid())
    return i + 100

def Bar(arg):
    print('-->exec done:', arg,os.getpid())

if __name__ == '__main__':
    #freeze_support()
    pool = Pool(processes=3) #允许进程池同时放入5个进程
    print("主进程",os.getpid())
    for i in range(10):
        pool.apply_async(func=Foo, args=(i,), callback=Bar) #callback=回调
        #pool.apply(func=Foo, args=(i,)) #串行
        #pool.apply_async(func=Foo, args=(i,)) #串行
    print('end')
    pool.close()
    pool.join() #进程池中进程执行完毕后再关闭,如果注释,那么程序直接关闭。.join()

输出结果



协程(Coroutine)--一种用户态的轻量级线程

定义:

  • 必须在只有一个单线程里实现并发
  • 修改共享数据不需加锁
  • 用户程序里自己保存多个控制流的上下文栈
  • 一个协程遇到IO 操作自动切换到其他协程


优点:

  • 无需线程上下文切换的开销
  • 无需原子操作锁定及同步的开销(原子操作:不会被线程调度机制打断的操作)
  • 方便切换控制流,简化编程模型
  • 高并发+高扩展+低成本
Greenlet

from greenlet import greenlet
def test1():
    print(12)
    gr2.switch()
    print(34)
    gr2.switch()
def test2():
    print(56)
    gr1.switch()
    print(78)

gr1 = greenlet(test1) #启动一个携程
gr2 = greenlet(test2)
gr1.switch()

输出结果




Gevent

import gevent

def foo():
    print('Running in foo')   #切换bar-print
    gevent.sleep(2)   #切换
    print('Explicit context switch to foo again')
def bar():
    print('Explicit精确的 context内容 to bar')   #切换到func3-print
    gevent.sleep(1)
print('Implicit context switch back to bar')def func3(): print("running func3 ") #切换到foo-gevent,卡住;切换到bar-gevent,卡住,直接执行func3-geven,没卡住,func3-print2 gevent.sleep(0) print("running func3 again ")gevent.joinall([ gevent.spawn(foo), #生成, gevent.spawn(bar), gevent.spawn(func3),])


输出结果



简单的网页爬虫


from urllib import request

def f(url):
    print('GET: %s' % url)
    resp = request.urlopen(url)
    data = resp.read()
    f = open("url.html","wb")
    f.write(data)
    f.close()
    print('%d bytes received from %s.' % (len(data), url))

f("http://www.cnblogs.com/alex3714/articles/5248247.html")

输出结果



生成的文件



IO多路复用

  • 虚拟空间分为:用户空间和内核空间

select解析socket通信

服务器端

import select
import socket
import queue


server = socket.socket()
server.bind(('localhost',9000))
server.listen(1000)


server.setblocking(False) #不阻塞

msg_dic = {}

inputs = [server,]
#inputs = [server,conn] #[conn,]
#inputs = [server,conn,conn2] #[conn2,]
outputs = [] #
#outputs = [r1,] #
while True:
    readable ,writeable,exceptional= select.select(inputs, outputs, inputs )
    print(readable,writeable,exceptional)
    for r in readable:
        if r is server: #代表来了一个新连接
            conn,addr = server.accept()
            print("来了个新连接",addr)
            inputs.append(conn) #是因为这个新建立的连接还没发数据过来,现在就接收的话程序就报错了,
            #所以要想实现这个客户端发数据来时server端能知道,就需要让select再监测这个conn
            msg_dic[conn] = queue.Queue() #初始化一个队列,后面存要返回给这个客户端的数据
        else: #conn2
            data = r.recv(1024)
            print("收到数据",data)
            msg_dic[r].put(data)

            outputs.append(r) #放入返回的连接队列里
            # r.send(data)
            # print("send done....")

    for w in writeable: #要返回给客户端的连接列表
        data_to_client = msg_dic[w].get()
        w.send(data_to_client) #返回给客户端源数据

        outputs.remove(w) #确保下次循环的时候writeable,不返回这个已经处理完的连接了

    for e in exceptional:
        if e in outputs:
            outputs.remove(e)

        inputs.remove(e)

        del msg_dic[e]

客户端

import socket

HOST = 'localhost'  # The remote host
PORT = 9001  # The same port as used by the server
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))
while True:
    msg = bytes(input(">>:"), encoding="utf8")
    s.sendall(msg)
    data = s.recv(1024)

    #
    print('Received', data)
s.close()





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值