server=socket.socket()括号内参数不写默认为tcp协议
conn,addr=server.accept()
conn是链接对象,addr是地址
.join() 主线程等待子线程运行结束再执行
global 全局变量,局部修改全局
data='hello world'
字符串转二进制:
data=bytes(data,encoding='utf–8')
print(data)
二进制转字符串:
data=str(data,encoding='utf–8')
print(data)
进程
current_process().pid 查看当前进程号
os.getpid() 查看当前进程
os.getppid() 查看当前进程的父进程号
Windows终端命令:
tasklist 查看
tasklist |findstr PID查看具体的进程
Mac终端命令:
ps aux 筛选
ps aux|grep
僵尸进程:进程结束后不会立刻释放占用的资源(pid)会保留一段时间供父进程查看
孤儿进程:子进程存在 父进程意外死亡 操作系统会在一段时间后自动回收
守护进程:被守护的进程死亡 守护的进程也立刻跟着死亡
如何开启守护进程:在start语句之前写一下代码即可
p.daenon=Ture
p.atart()
互斥锁:针对一份票 很多人抢的情况 只让一人抢到票,一般是加锁处理
作用将并发改为串行,牺牲了程序运行的效率,保证了数据的安全
注意:只在操作数据的部分加锁即可,锁尽量不要自己去处理很容易造成死锁的现象
from multiporcesing import Lock
mutex=Lock()
抢锁:mutex.aequire()
释放锁:mutex.release()
行锁:操作表格中的一行数据的时候其他人都不能操作
表锁:操作一张表的时候其他人都不能操作
队列Queue
队列:先进先出 堆栈:先进后出
from multiporcesing import Queue
q=Queue括号内可以写数字来限制队列的大小
q.put()放数据 当队列满了再放 阻塞
q.get()取数据 当队列空了再取 阻塞
q.full()判断队列是否满了
q.empty()判断队列是否空了
q.get_nowait()取数据的时候如果没有数据直接报错
q.get_(timeout=5取数据的时候如果没有数据等5秒还没有则直接报错)
进程间通信:
进程之间是无法直接进行数据交互的 但是可以通过队列或者管道实现数据交互
队列:管道+锁
本地测试的时候才可能会用到Queue,实际生产用的都是别人封装好的功能非常强大的工具
Redis
kafka
RQ
生产者与消费者模型:
分成三部分:生产者+消息队列+消费者
生产数据 暂时存数据 从队列里面拿数据去处理
消息队列的存在是为了解决供需不平衡
JoinableQueue
可以被等待的q
你在往队列中放数据的时候 内部有一个计数器自动加1
你在从队列中取数据的时候 调用task_done()内部计时器自动减1
q.join()当前计数器为0的时候才继续往下运行
线程理论:
进程是资源单位 工厂
开进程和开线程的区别:开进程
申请内存空间
拷贝代码
消耗资源较大
线程是执行单位 流水线 是真正干活的人,干活过程中需要的资源由线程所在的进程提供
每一个进程肯定都自带一个线程
同一个进程内可以创建多个线程
开进程和开线程的区别:开线程
同一个进程内创建多个线程 无需上述两部操作,消耗资源相对小
开启进程的两种方式:
方式一:用这种的比较多
from multiprocessing import Process
import time
def task(name):
print('%s is running'%name)
time.sleep(3)
print ('%s isover'%name)
#Windows操作系统下 创建进程一定要在main内创建,因为Windows下创建进程类似于模块导入的方式,会从上往下依次执行代码,注重运行
#Linux中则是把代码完全拷贝一份注重交互
if __name__=='__main__'
#1.创建一个对象
p=Process (target=task,args=('Jason',))
#容器类型哪怕里面只有一个人元素,建议要用逗号隔开
2.开启进程
p.start()#告诉操作系统帮我创建一个进程
print('主')
第二种方法:类的继承(了解,用第一种比较多)
from multiprocessing import Process
import time
class MyProcess(Process):
#类的命名建议使用驼峰式,括号里写继承的Process
def run(self)#函数名字必须写run
print('hello world')
time.sleep(1)
print ('get out')
if __name__=='__main__'
p=MyProcess()#实例化这个类是对象
p.start()
print ('主')
总结:创建进程就是在内存中申请一块内存空间,将需要运行的代码丢进去,一个进程对应在内存中就是一块独立的内存空间,多个进程对应在内存中就是多块独立的内存空间,进程与进程之间,数据默认情况下是无法直接交互的,如果想交互可以借助与第三方工具,模块
join方法:让主进程等待子进程类似于同步
若多个p,结果无固定顺序
若要开很多个就可以用for循环:
start_time=time.time()
for i in range (1, 4): 顾头不顾尾
p=Process (target=task,args='子进程%s'%i,i))
p.start()
p.join()
print ('主',time.time()-start_time)
但是这种就是将并发改为串行,时间很慢,一共要六秒多,所以可以把join方法用到全局来如下:
start_time=time.time()
p_list=[ ]#先建一个空列表
for i in range (1, 4): #顾头不顾尾
p=Process (target=task,args='子进程%s'%i,i))
p.start()
p_list.append(p)#拿到一个p就往空列表里追加一个p
for p in p_list:#再把列表的p循环取值
p.join()再让主进程等待子进程一起
print ('主',time.time()-start_time