python3 09 Outline

Recap the last 

##-networks

`` `
Socket
OSI seven layer protocol
two common TCP UDP transport layer protocol
tcp: connection-oriented, reliable, stream oriented message format
udp: connectionless and unreliable , packet-oriented message format is

`

#### and udp protocols TCP Socket

`
#服务端
import socket

server = socket.socket()
server.bind(('127.0.0.1',8001))

server.listen()

conn,addr = server.accept()

from_client_msg = conn.recv(1024)
print(from_client_msg)
conn.send(b'hello')

conn.close()
server.close()

#客户端
import socket
client = socket.socket()

client.connect(('127.0.0.1',8001))

client.send(b'haha')
from_server_msg = client.recv(1024)
print(from_server_msg)
client.close()
 
################################# 
socket under the udp protocol
#服务端
import socket
server = socket.socket(type=socket.SOCK_DGRAM)  # data gram 数据包
server.bind(('127.0.0.1',8001))
msg,client_addr = server.recvfrom(1024)
print(msg)
server.sendto(b'hello',client_addr)

#客户端
import socket
client = socket.socket(type=socket.SOCK_DGRAM)  # data gram 数据包
client.sendto(b'hehe',('127.0.0.1',8001))
msg,server_addr = client.recvfrom(1024)
print(msg)
 
```


#### tcp的黏包

```python
!.两个连续发送的小的数据包会被连在一起发送
2.第一次发送的数据比较大,2000B,如果我另外一端接受数据时,不知道发送来的数据有多大,那么我可能写了一个recv1024,第二次再接受另外一端发送的第二个数据的时候,就会发现,第一次的剩余数据也会被接收到

解决方法,发送数据前,先发送数据的长度
struct 打包模块
ret = struct.pack('i',len(信息)) --- 4个bytes数据,长度为4
send(ret) ---- recv(4) ---- len_ret = struct.unpack('i',recv(4))[0] --recv(len_ret)

```

#### 缓冲区:

```
输入缓冲区 和 输出缓冲区
```

subprocess模块

```
conn = subprocess.Popen(
    cmd,
    shell=True,
    stdout = subprocess.PIPE,
    stderr = subprocess.PIPE
)
conn.stdout.read().decode('gbk')  # standard out 标准输出
conn.stderr.read().decode('gbk')  # standard error 标准错误输出
```


#### socketserver

```


import socketserver
class MyServer(socketserver.BaseRequestHandler):  # 自定义类
    def handle(self):  # 方法名必须为handle
        while 1:
            from_client_msg = self.request.recv(1024)  # conn
            print(from_client_msg.decode('utf-8'))
            msg = input('to_client_msg>>>')
            self.request.send(msg.encode('utf-8'))

if __name__ == '__main__':
    ip_port = ('127.0.0.1',8001)
    server = socketserver.ThreadingTCPServer(ip_port,MyServer)
    server.serve_forever()
```


# 今日内容总结

## 进程 线程 协程


```

并发:伪并行,遇到IO,帮我们提高代码执行效率
并行:真正的同时运行,多核cpu

```



#### 进程:

##### 父进程和子进程

```
os.getpid()当前进程的id,getppid()父进程的id
```

##### 创建进程的两种方式:

```python
方式1:


from multiprocessing import Process
    def f(n)
        print(n)
    
    if __name__ == '__main__':
        p = Process(target=f,args=(1,))
        p.daemon = True
        p.start()
        p.join()  #主进程等待子进程
方式2:

from multiprocessing import Process

    class MyProcess(Process):

        def __init__(self,n):
            self.n = n
            super().__init__()

        #这是需要执行的代码逻辑
        def run(self):
            print(self.n)
            self.f2()
            print('xxxxxx')
        def f2(self):
            xxxx

    if __name__ == '__main__':
        p = MyProcess(20)
        p.start()
        print('主进程结束')
```


进程三状态:

```
就绪 运行 阻塞
```


#### 进程间通信(IPC)

##### 队列

``` python


from multiprocessing import Process,Queue
q = Queue(3)  #3个长度的队列
q.put(1)   #如果满了,阻塞程序
q.get()    #如果没了,阻塞程序
q.qsize()  #统计一下当前队列里面有多少个数据了
q.empty()  #是否为空,不可信
q.full()   #是否满了,不可信
q.put_nowait('a')  #如果满了就报错,不等待  
q.get_nowait() #如果没了就报错,不等待
```

进程通过队列通信:

```python


from multiprocessing import Process,Queue
def f1(q):
    ret = q.get()
    print('子进程的ret>>',ret)

if __name__ == '__main__':
    q = Queue(3)
    q.put('你好')
    p = Process(target=f1,args=(q,))
    p.start()
```


### 线程

创建线程的两种方式

```python
#方式1
from threading import Thread
def f1(n):
    pass

if __name__ == '__main__':
    t = Thread(target=f,args=(1,))
    t.daemon = True  #守护线程
    t.start()
    t.join()
#方式2:
class MyThread(Thread):
    def __init__(self,n):
        super().__init__()
        self.n = n
    def run(self):
        print(self.n)
        pass
if __name__ == '__main__':
    t = MyThread('aa')
    t.start()
 
```


##### 守护线程和守护进程的区别

```
守护进程:随着主进程的代码执行结束,而结束
守护线程:随着所有非守护线程的执行结束而结束
```


#### 锁

互斥锁 Lock

```python
作用:多线程或者多进程在操作共享数据的时候,会出现数据混乱的问题,加锁处理,牺牲了效率,保证了安全.


from threading import Thread,Lock
from multiprocessing import Process,Lock
def f1(loc):
    loc.acquire()
    xxxx
    loc.release()
    
    with loc:
        xxxxx

loc = Lock()
t = Thread(target=f1,args=(loc,))
t.start()
```

递归锁 RLock

```python
死锁现象,内部维护了一个计数器


from threading import Thread,RLock
from multiprocessing import Process,RLock

loc = RLock()
t = Thread(target=f1,args=(loc,))
t.start()
```



线程队列:

```python


import queue
#先进先出的
q = queue.Queue(4)
...
#先进后出的
q = queue.LifoQueue(4)
#优先级的
q = queue.PriorityQueue(4)
q.put((1,'xx'))  #数字越小,优先级越高,越早被取出
q.get() -- (1,'xx')
如果优先级数字相同,后面的值类型不能不一样,而且两个字典也不能比
```



线程池和进程池

```python


from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor
#线程池ThreadPoolExecutor
#进程池ProcessPoolExecutor

def f1(n,m)
    pass
    return n*n
    
def call_back(m):  m.result()--n*n
    print(m) #结果集对象
    print(m.result())

pool = ThreadPoolExecutor(max_workers=5)
pool = ProcessPoolExecutor(max_workers=5)
ret = pool.submit(f1,1,2)
ret.result()  #类似join,拿不到结果就阻塞程序
pool.shutdown()  #关闭池子
pool.submit(f1,1,2).add_done_callback(call_back)
```

### 协程

```python
gevent --- 基于greenlet模块


def f1(n):
    pass
def f2(n):
    pass
g1 = gevent.spawn(f1,1) 
g2 = gevent.spawn(f2,1) 
g1.join() #一个一个的join
gevent.joinall([g1,g2])
print('主任务')


```

参考博客:

```python
进程:https://www.cnblogs.com/clschao/articles/9629392.html
线程:https://www.cnblogs.com/clschao/articles/9684694.html
协程:https://www.cnblogs.com/clschao/articles/9712056.html
```


 
 

Guess you like

Origin www.cnblogs.com/lilyxiaoyy/p/10964077.html