简单学习记录(1)
简单放些自己学习中遇到的问题和学到的东西新类别
大概会一直加下去吧
Typora预览模式换行Enter怎么是直接换段落,换回vscode去了
最近又把bot拉起来用了,给群友用的时候后发现之前连写带抄的涩涩一下在用的时候有的时候会特别慢,然后还不能同时响应其他写的插件。
一直不知道原因,后来看见404群里有大佬在亲切解答萌新问题的时候发现原来是requests的问题
在不借助其他第三方库的情况下,requests只能发送同步请求;aiohttp只能发送异步请求;httpx既能发送同步请求,又能发送异步请求
(然后是没了解太懂的口胡+copy环节)
异步与同步
简单的概括
- 同步:一个一个步骤的往下执行。只有在上一步完成后,程序才会进入下一个步骤。
- 异步:不用于同步的是,系统不会等待执行步骤完成后再继续执行下一个步骤,而是直接继续往后执行
- 举个例子大概就是,同步是一个一个排队在瀑布下接水,一个接完了(执行完毕)才开始下一个;异步是来一个就去一个接水,先接完的直接离开了
- 同步严格按照顺序进行处理并返回结果,异步每次调用了方法后直接执行后续代码而不会返回结果,需要通过状态或通知以及回调函数来告知调用者或处理,因此返回的结果顺序也不一定是和发出一样的
Python在3.4引入了asyncio
——异步I/O,是用来编写并发代码的库,3.5加入async/await
简化使用
async
声明一个函数为异步函数await
声明处理比较耗费时间的操作
nb2就是基于asyncio
编写的,因此能够实现多个插件或事件能够互不干扰地响应处理
写的时候把我自己绕进去了,老是和并发混起来了,概念还是不懂啊
好晕
因此之前插件里用的是同步的requests
库,直接让整个bot都停下来等待执行爬虫完毕,会因为网络的限制让bot的运行效率大大降低
大概就这样有时间重构下用httpx好了
GIL
先来一个官方wiki
GIL的全称是全局解释器锁(Global Interpreter Lock
),是最流行的Python解释器Cpython中用来防止多个本机线程并发执行机器码的手段,官方解释如下
In CPython, the global interpreter lock, or GIL, is a mutex that protects access to Python objects, preventing multiple threads from executing Python bytecodes at once. The GIL prevents race conditions and ensures thread safety.
与之相对应的,其他的Python解释器如PyPy
也有和CPython
一样的GIL
而使用java开发的JPython
和与使用.net开发的IronPython
因为开发语言的特性使得没有GIL,可以充分的发挥出多线程的功能。还有个Cython
也有GIL但是可以使用with语句临时释放
目前大部分Python环境下的默认的解释器为CPython,所以GIL算是日常使用python中一个影响比较大(主要是并发)的存在。
GIL的发明原因是因为CPthon的内存管理不是线程安全的,因为python线程共享相同的内存,若是多个线程同时运行,用户无法知道线程共享访问数据的先后顺序。因此规定一次只能运行一个线程,可以让CPython的用户生活更加轻松。
(这大部分都是copy的)下面是实际开发中涉及到线程安全的例子:
a = 2//定义一个共享变量a
threadA a = a + 2//某个线程A内执行的操作
threadB a = a * a//某个线程B内执行的操作
如果在没有GIL的情况下,AB的先后发生顺序会使得共享变量a的值发生不同的变化。例如先A后B,则最终a的值为16,反之先B后A,a的最终值变成了6。
因此知晓执行顺序并确保不会被其他线程所影响正是GIL所要做的。这个例子只是战士了a的变化,若是在AB两个线程的后续中需要调用a来赋值计算或者是给a重新赋值,那么不知道先后顺序造成的后果会更加严重。
由于全局锁的存在,Python几乎无法做到“多线程优于单线程”,因为无论如何都是在一个核上跑的伪并行,无疑是对开发者的限制
因此包括官方wiki上都给出了一个“Eliminating the GIL"的条目,但由于大部分的库包功能都已经依赖GIL许久,除非能够让所有的开发者来一次彻底的大重构,否则直接取代会使整个生态系统崩溃。
目前的解决方法有
- 使用多核多进程实现每个进程跑一个线程的“多线程”,但是这样速度也没有和单核多线程拉开
- 使用其他解释器,但其他解释器没有CPython一样庞大的社区支持开发与使用特性
- 使用
multiprocessing
库,但也不算是彻底之计。这个库也有一些缺陷 - 等Python官方改(wiki上给的21年在改了在改了)
大概比较弄懂了的就这些,后续再加点吧。
参考资料
Python GIL全局解释器锁详解
深入GIL(上)
Python的GIL是什么鬼
官方wiki里的文章
GloballInterpreterLock
asyncio
python异步编程