当前位置:首页 » 编程语言 » python异步编程

python异步编程

发布时间: 2023-05-30 09:38:27

1. python都可以干什么

网络爬虫

爬虫,指的是从互联网采集数据的程序脚本

爬天爬地爬空气 ,无聊的时候爬一爬吃鸡数据、b站评论,能得出很多有意思的结论。知乎有个很有意思的问题——"利用爬虫技术能做到哪些很酷很有趣很有用的事情",感兴趣的朋友可以自行搜索。

目前正值各大企业的秋季招聘期,没有合适的简历模板,用Python爬一波就搞定。

人工智能

其实,Python 无论是在传统机器学习还是深度学习领域都占有不可替代的地位。许多诸如 Scikit-learn 等机器学习库使得 Python 极具优势 ;

Keras 、TensorFlow 、Pytorch 等深度学习主流框架也决定了 Python在深度学习领域的天选之子地位。

2. python做web开发好吗

Python适合从简单到复杂的各种Web项目。它广泛用于旅行,医疗保健,交通运输,金融等不同领域,用于Web开发和软件测试,脚本编写和生成。
选择Python进行Web开发的优点:
1、易于使用和阅读
有几个因素可以简化Python在Web开发中的使用:
低入门门槛 Python与我们日常生活中使用的英语相似。语法的简单性使您可以处理复杂的系统,并确保所有元素之间都具有明确的关系。因此,更多的新手程序员可以学习该语言并更快地加入编程社区。
良好的可视化 效果通过使用不同的图和图表,可以以易于理解的格式表示数据。它们是可视化呈现和理解数据的有效方法。Web开发公司利用Python库(例如Matplotlib)来可视化数据并创建清晰且易于理解的报告。
Python非常易于阅读,因此开发人员通常在理解由其他程序员编写的代码时不会遇到任何问题。这可以促使从事同一项目的开发人员之间的通信效率更高。
2、异步编码
由于没有死锁或研究争执或任何其他令人困惑的问题,因此使用Python 编写和维护异步代码无需花费太多精力。此类代码的每个单元分别运行,从而使您能够更快地处理各种情况和问题。
3、较少限制的编程方法
与其他编码语言(例如Java)相比,Python具有较少限制的编程方法。它具有多种范例,可以支持多种编程风格,包括过程性,面向对象和功能性(命令性)。这使Python成为初创公司的绝佳语言,因为项目可能需要随时更改方法。
4、企业应用集成
Python是企业软件应用程序的流行选择,这在很大程度上要归功于Python与传统上用于企业开发的其他语言(例如Java,PHP和.NET)的流畅集成。
Python直接与Java,C ++或C代码进行调用,从而可以对大多数常用协议和数据格式进行大量的过程控制和实现。
除此之外,它还可以用于组装基础结构的新旧片段,这是复杂移动应用程序中的典型情况。
5、可以使用Python框架快速进行Web开发
Python的另一个优点是它具有许多简化开发过程的框架。根据您的工作,可能需要不同的框架。
6、科学计算库方便
有各种各样的软件包和库可用于开发科学和数字应用程序,以及工具包(例如VTK 3D和MayaVi),单独的成像库以及许多其他工具。
7、用于机器学习和AI
机器学习(ML)和人工智能(AI)技术越来越受到关注,因此越来越多的开发人员正在尝试将它们纳入各种项目中。如果使用正确的语言,这是可能的。
根据让·弗朗索瓦·普吉,IBM的机器学习部门的代表,Python是ML和AI项目的顶尖语言,许多开发商同意。Python具有高效的ML软件包,用于可视化结果的工具,并且远远超出了数据分析和其他使该应用程序领域受益的功能。
Python确实是机器学习和人工智能最火热的语言,没有之一。
最典型的用语在线语音合成,在线语音识别,如果你的项目是建立一个人工智能的web应用,那么Python再适合不过了。
8、作为应用程序脚本
由于Python与C,C ++和Java的强大集成,Python可以很方便地用于应用程序脚本编写。从一开始就被设计为可嵌入的,它对于自定义大型应用程序并为其进行扩展非常有用。
不敢说Python可以代替Lua,不过Python可以和Lua那样被嵌入C/C++中。
9、软件测试
Python用于测试自动化。许多QA自动化专家选择Python是因为它具有简单的学习曲线-对于技术背景较为有限的人(强大的社区,清晰的语法和可读性)也非常有用。Python甚至有一个易于使用的单元测试框架(例如,您可以使用它对移动应用程序执行地理位置测试)。
M年前我在一家路由生产商上班,那时候我看到测试部门用Tcl脚本去测试路由器端口,我当时就觉得很诧异,毕竟Tcl脚本的语法真的很怪异,相比这点,Python的语法真的干净简洁。
10、在原型制作中使用
用Python创建原型已被证明是一个快速而简单的过程。编程语言的敏捷性使代码重构变得容易,并且可以将初始原型快速开发为最终产品。
11、开源
Python具有开放源代码许可证,该许可证使用户可以轻松访问它,并有助于重新分发和无限制的修改。开发人员可以自由使用该语言并为它的改进做出贡献。
12、服务器端脚本
如上所述,使用Python进行服务器端脚本编写的优点之一是其简单的语法,从而大大加快了处理速度。该代码由功能模块及其之间的连接组成,可让您根据用户操作执行程序算法。Python还支持Web开发中所需的图形用户界面。
13、便携性和交互性
Python具有动态语义和快速原型制作的出色功能,这要归功于它的交互性和可移植性。它可以轻松地嵌入各种应用程序中,甚至是使用不同编码语言的应用程序。因此,您可以轻松修复新模块并扩展Python的核心词汇。它可以连接各种组件。难怪它有时被称为“胶水语言”。
推荐学习:《Python教程》

3. 在Python中使用Asyncio系统(3-4)​Task 和 Future

Task 和 Future

前面我们讨论了协程,以及如何在循环中运行它们才有用。现在我想简单谈谈Task和Future api。你将使用最多的是Task,因为你的大部分工作将涉及使用create_task()函数运行协程,就像在第22页的“快速开始”中设置的那样。Future类实际上是Task的超类,它提供了与循环交互操作的所有功能。

可以这样简单地理解:Future表示某个活动的未来完成状态,并由循环管理。Task是完全相同的,但是具体的“activity”是一个协程——可能是你用async def函数加上create_task()创建的协程。

Future类表示与循环交互的某个东西的状态。这个描述太模糊了,不太有用,所以你可以将Future实例视为一个切换器,一个完成状态的切换器。当创建Future实例时,切换设置为“尚未完成”状态,但稍后它将是“完成”状态。事实上,Future实例有一个名为done()的方法,它允许你检查状态,如示例 3-15所示。

示例 3-15. 用done()方法检查完成状态

Future实例还可以执行以下操作:

• 设置一个result值(用.set_result(value)设置值并且使用 .result()获取值)

• 使用.cancel()方法取消 (并且会用使用.cancelled()检查是否取消)

• 增加一个Future完成时回调的函数

即使Task更常见,也不可能完全避免使用Future:例如,在执行器上运行函数将返回Future实例,而不是Task。让我们快速看一下 示例 3-16 ,了解一下直接使用Future实例是什么感觉。

示例 3-16. 与Future实例的交互

(L3)创建一个简单的 main函数。我们运行这个函数,等上一会儿然后在Future f上设置一个结果。

(L5)设置一个结果。

(L8)手动创建一个Future实例。注意,这个实例(默认情况下)绑定到我们的循环,但它没有也不会被附加到任何协程(这就是Tasks的作用)。

(L9)在做任何事情之前,确认future还没有完成。

(L11)安排main()协程,传递future。请记住,main()协程所做的所有工作就是sleep,然后切换Future实例。(注意main()协程还不会开始运行:协程只在事件循环运行时才开始运行。)

(L13)在这里我们在Future实例上而不是Task实例上使用run_until_complete()。这和你以前见过的不一样。现在循环正在运行,main()协程将开始执行.

(L16)最终,当future的结果被设置时,它就完成了。完成后,可以访问结果。

当然,你不太可能以这里所示的方式直接使用Future;代码示例仅用于教育目的。你与asynccio的大部分联系都是通过Task实例进行的。

你可能想知道如果在Task实例上调用set_result()会发生什么。在Python 3.8之前可以这样做,但现在不允许这么做了。任务实例是协程对象的包装器,它们的结果值只能在内部设置为底层协程函数的结果,如 示例 3-17所示那样。

示例 3-17. 在task上调用set_result

(L13)唯一的区别是我们创建的是Task实例而不是Future实例。当然,Task API要求我们提供一个协程;这里我们使用sleep()只是因为简单方便。

(L7)正在传入一个Task实例。它满足函数的类型签名(因为Task是Future的子类),但从Python 3.8开始,我们不再允许在Task上调用set_result():尝试这样做将引发RuntimeError。这个想法是,一个Task代表一个正在运行的协程,所以结果应该总是来自于task自身。

(L10, L24)但是,我们仍然可以cancel()一个任务,它将在底层协程中引发CancelledError。

Create_task? Ensure_Future? 下定决心吧!

在第22页的“快速入门”中,我说过运行协程的方法是使用asyncio.create_task()。在引入该函数之前,有必要获取一个循环实例并使用loop.create_task()完成相同的任务。事实上,这也可以通过一个不同的模块级函数来实现:asyncio.ensure_future()。一些开发人员推荐create_task(),而其他人推荐ensure_future()。

在我为这本书做研究的过程中,我确信API方法asyncio.ensure_future()是引起对asyncio库广泛误解的罪魁祸首。API的大部分内容都非常清晰,但在学习过程中还存在一些严重的障碍,这就是其中之一。当你遇到ensure_future()时,你的大脑会非常努力地将其集成到关于asyncio应该如何使用的心理模型中——但很可能会失败!

在Python 3.6 asyncio 文档中,这个现在已经臭名昭着的解释突出了 ensure_future() 的问题:

asyncio.ensure_future(coro_or_future, *, _loop =None)

安排执行一个协程对象:把它包装在future中。返回一个Task对象。如果参数是Future,则直接返回。

什么!? 当我第一次读到这篇文章时,我很困惑。下面希望是对ensure_future()的更清楚的描述:

这个函数很好地说明了针对终端用户开发人员的asyncio API(高级API)和针对框架设计人员的asyncio API(低级API)之间的区别。让我们在示例 3-18中自习看看它是如何工作的。

示例 3-18. 仔细看看ensure_future()在做什么

(L3)一个简单的什么都不做的协程函数。我们只需要一些能组成协程的东西。

(L6)我们通过直接调用该函数来创建协程对象。你的代码很少会这样做,但我想在这里明确地表示,我们正在向每个create_task()和ensure_future()传递一个协程对象。

(L7)获取一个循环。

(L9)首先,我们使用loop.create_task()在循环中调度协程,并返回一个新的Task实例。

(L10)验证类型。到目前为止,没有什么有趣的。

(L12)我们展示了asyncio.ensure_future()可以被用来执行与create_task()相同的动作:我们传入了一个协程,并返回了一个Task实例(并且协程已经被安排在循环中运行)!如果传入的是协程,那么loop.create_task()和asyncio.ensure_future()之间没有区别。

(L15)如果我们给ensure_future()传递一个Task实例会发生什么呢?注意我们要传递的Task实例是已经在第4步通过loop.create_task()创建好的。

(L16)返回的Task实例与传入的Task实例完全相同:它在被传递时没有被改变。

直接传递Future实例的意义何在?为什么用同一个函数做两件不同的事情?答案是,ensure_future()的目的是让框架作者向最终用户开发者提供可以处理两种参数的API。不相信我?这是ex-BDFL自己说的:

ensure_future()的要点是,如果你有一个可能是协程或Future(后者包括一个Task,因为它是Future的子类)的东西,并且你想能够调用一个只在Future上定义的方法(可能唯一有用的例子是cancel())。当它已经是Future(或Task)时,它什么也不做;当它是协程时,它将它包装在Task中。

如果您知道您有一个协程,并且希望它被调度,那么正确的API是create_task()。唯一应该调用ensure_future()的时候是当你提供一个API(像大多数asyncio自己的API),它接受协程或Future,你需要对它做一些事情,需要你有一个Future。

—Guido van Rossum

总而言之,asyncio.sure_future()是一个为框架设计者准备的辅助函数。这一点最容易通过与一种更常见的函数进行类比来解释,所以我们来做这个解释。如果你有几年的编程经验,你可能已经见过类似于例3-19中的istify()函数的函数。示例 3-19中listify()的函数。

示例 3-19. 一个强制输入列表的工具函数

这个函数试图将参数转换为一个列表,不管输入的是什么。api和框架中经常使用这类函数将输入强制转换为已知类型,这将简化后续代码——在本例中,您知道参数(来自listify()的输出)将始终是一个列表。

如果我将listify()函数重命名为ensure_list(),那么您应该开始看到与asyncio.ensure_future()的类似之处:它总是试图将参数强制转换为Future(或子类)类型。这是一个实用函数,它使框架开发人员(而不是像你我这样的终端用户开发人员)的工作变得更容易。

实际上,asyncio标准库模块本身使用ensure_future()正是出于这个原因。当你下次查看API时,你会发现函数参数被描述为“可等待对象”,很可能内部使用ensure_future()强制转换参数。例如,asyncio.gather()函数就像下面的代码一样:

aws参数表示“可等待对象”,包括协程、task和future。在内部,gather()使用ensure_future()进行类型强制转换:task和future保持不变,而把协程强制转为task。

这里的关键是,作为终端用户应用程序开发人员,应该永远不需要使用asyncio.ensure_future()。它更像是框架设计师的工具。如果你需要在事件循环上调度协程,只需直接使用asyncio.create_task()来完成。

在接下来的几节中,我们将回到语言级别的特性,从异步上下文管理器开始。

4. python都可以做什么

从语言的角度上来看,除了极少的领域之外,Python几乎无所不能,该语言通俗易懂、容易入门、功能强大,学习后可以从事以下工作岗位:
1. Web开发
最火的Python web框架Django,支持异步高并发的Tornado框架,短小精悍的flask,bottle,Django官方的标语把Django定义为the framework for perfectionist with deadlines(大意是一个为完全主义者开发的高效率web框架)
2. 网络编程
支持高并发的Twisted网络框架,py3引入的asyncio使异步编程变的非常简单
3. 爬虫开发
爬虫领域,Python几乎是霸主地位,Scrapy/Request/BeautifuSoap/urllib等,想爬啥就爬啥
4. 云计算开发
目前最火最知名的云计算框架就是OpenStack,Python现在的火,很大一部分就是因为云计算市场近几年的爆发
5. 人工智能
MASA和Google早期大量使用Python,为什么Python积累了丰富的科学运算库,当AI时代来临后,Python从众多编程语言中脱颖而出,各种人工智能算法都基于Python编写,由其PyTorch之后,Python作为AI时代头牌语言的位置基本确立!
6. 自动化运维
问问中国的每个运维人员,运维人员必须会的语言是什么?10个人详细会给你一个相同的答案,它的名字叫Python
7. 金融分析
金融公司使用的很多分析程序、高频交易软件就是用的Python,目前,Python是金融分析、量化交易领域里用的最多的语言
8. 科学运算
97年开始,NASA就在大量使用Python在进行各种复杂的科学运算,随着NumPy,SciPy,Matplotlib,Enthought librarys等众多程序库的开发,使得Python越来越适合做科学计算、绘制高质量的2D和3D图像。和科学计算领域最流行的商业软件Matlab相比,Python是一门通用的程序设计语言,比Matlab所采用的脚本语言的应用范围更广泛
9. 游戏开发
在网络游戏开发中Python也有很多应用。相比Lua or C++,Python比Lua有更高阶的抽象能力,可以用更少的代码描述游戏业务逻辑,与Lua相比,Python更适合作为一种Host语言,即程序的入口点是在Python那一端会比较好,然后用C/C++在非常必要的时候写一些扩展。Python非常适合编写1万行以上的项目,而且能够很好的把网游项目的规模控制在10万行代码以内。
10. 桌面软件
虽然大家很少使用桌面软件了,但是Python在图形界面开发上也很强大,你可以用tkinter/PyQT框架开发各种桌面软件!

5. 一篇文章带你深度解析Python线程和进程

使用Python中的线程模块,能够同时运行程序的不同部分,并简化设计。如果你已经入门Python,并且想用线程来提升程序运行速度的话,希望这篇教程会对你有所帮助。

线程与进程

什么是进程

进程是系统进行资源分配和调度的一个独立单位 进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位。每个进程都有自己的独立内存空间,不同进程通过进程间通信来通信。由于进程比较重量,占据独立的内存,所以上下文进程间的切换开销(栈、寄存器、虚拟内存、文件句柄等)比较大,但相对比较稳定安全。

什么是线程

CPU调度和分派的基本单位 线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源。线程间通信主要通过共享内存,上下文切换很快,资源开销较少,但相比进程不够稳定容易丢失数据。

进程与线程的关系图

线程与进程的区别:

进程

现实生活中,有很多的场景中的事情是同时进行的,比如开车的时候 手和脚共同来驾驶 汽车 ,比如唱歌跳舞也是同时进行的,再比如边吃饭边打电话;试想如果我们吃饭的时候有一个领导来电,我们肯定是立刻就接听了。但是如果你吃完饭再接听或者回电话,很可能会被开除。

注意:

多任务的概念

什么叫 多任务 呢?简单地说,就是操作系统可以同时运行多个任务。打个比方,你一边在用浏览器上网,一边在听MP3,一边在用Word赶作业,这就是多任务,至少同时有3个任务正在运行。还有很多任务悄悄地在后台同时运行着,只是桌面上没有显示而已。

现在,多核CPU已经非常普及了,但是,即使过去的单核CPU,也可以执行多任务。由于CPU执行代码都是顺序执行的,那么,单核CPU是怎么执行多任务的呢?

答案就是操作系统轮流让各个任务交替执行,任务1执行0.01秒,切换到任务2,任务2执行0.01秒,再切换到任务3,执行0.01秒,这样反复执行下去。表面上看,每个任务都是交替执行的,但是,由于CPU的执行速度实在是太快了,我们感觉就像所有任务都在同时执行一样。

真正的并行执行多任务只能在多核CPU上实现,但是,由于任务数量远远多于CPU的核心数量,所以,操作系统也会自动把很多任务轮流调度到每个核心上执行。 其实就是CPU执行速度太快啦!以至于我们感受不到在轮流调度。

并行与并发

并行(Parallelism)

并行:指两个或两个以上事件(或线程)在同一时刻发生,是真正意义上的不同事件或线程在同一时刻,在不同CPU资源呢上(多核),同时执行。

特点

并发(Concurrency)

指一个物理CPU(也可以多个物理CPU) 在若干道程序(或线程)之间多路复用,并发性是对有限物理资源强制行使多用户共享以提高效率。

特点

multiprocess.Process模块

process模块是一个创建进程的模块,借助这个模块,就可以完成进程的创建。

语法:Process([group [, target [, name [, args [, kwargs]]]]])

由该类实例化得到的对象,表示一个子进程中的任务(尚未启动)。

注意:1. 必须使用关键字方式来指定参数;2. args指定的为传给target函数的位置参数,是一个元祖形式,必须有逗号。

参数介绍:

group:参数未使用,默认值为None。

target:表示调用对象,即子进程要执行的任务。

args:表示调用的位置参数元祖。

kwargs:表示调用对象的字典。如kwargs = {'name':Jack, 'age':18}。

name:子进程名称。

代码:

除了上面这些开启进程的方法之外,还有一种以继承Process的方式开启进程的方式:

通过上面的研究,我们千方百计实现了程序的异步,让多个任务可以同时在几个进程中并发处理,他们之间的运行没有顺序,一旦开启也不受我们控制。尽管并发编程让我们能更加充分的利用IO资源,但是也给我们带来了新的问题。

当多个进程使用同一份数据资源的时候,就会引发数据安全或顺序混乱问题,我们可以考虑加锁,我们以模拟抢票为例,来看看数据安全的重要性。

加锁可以保证多个进程修改同一块数据时,同一时间只能有一个任务可以进行修改,即串行的修改。加锁牺牲了速度,但是却保证了数据的安全。

因此我们最好找寻一种解决方案能够兼顾:1、效率高(多个进程共享一块内存的数据)2、帮我们处理好锁问题。

mutiprocessing模块为我们提供的基于消息的IPC通信机制:队列和管道。队列和管道都是将数据存放于内存中 队列又是基于(管道+锁)实现的,可以让我们从复杂的锁问题中解脱出来, 我们应该尽量避免使用共享数据,尽可能使用消息传递和队列,避免处理复杂的同步和锁问题,而且在进程数目增多时,往往可以获得更好的可获展性( 后续扩展该内容 )。

线程

Python的threading模块

Python 供了几个用于多线程编程的模块,包括 thread, threading 和 Queue 等。thread 和 threading 模块允许程序员创建和管理线程。thread 模块 供了基本的线程和锁的支持,而 threading 供了更高级别,功能更强的线程管理的功能。Queue 模块允许用户创建一个可以用于多个线程之间 共享数据的队列数据结构。

python创建和执行线程

创建线程代码

1. 创建方法一:

2. 创建方法二:

进程和线程都是实现多任务的一种方式,例如:在同一台计算机上能同时运行多个QQ(进程),一个QQ可以打开多个聊天窗口(线程)。资源共享:进程不能共享资源,而线程共享所在进程的地址空间和其他资源,同时,线程有自己的栈和栈指针。所以在一个进程内的所有线程共享全局变量,但多线程对全局变量的更改会导致变量值得混乱。

代码演示:

得到的结果是:

首先需要明确的一点是GIL并不是Python的特性,它是在实现Python解析器(CPython)时所引入的一个概念。就好比C++是一套语言(语法)标准,但是可以用不同的编译器来编译成可执行代码。同样一段代码可以通过CPython,PyPy,Psyco等不同的Python执行环境来执行(其中的JPython就没有GIL)。

那么CPython实现中的GIL又是什么呢?GIL全称Global Interpreter Lock为了避免误导,我们还是来看一下官方给出的解释:

主要意思为:

因此,解释器实际上被一个全局解释器锁保护着,它确保任何时候都只有一个Python线程执行。在多线程环境中,Python 虚拟机按以下方式执行:

由于GIL的存在,Python的多线程不能称之为严格的多线程。因为 多线程下每个线程在执行的过程中都需要先获取GIL,保证同一时刻只有一个线程在运行。

由于GIL的存在,即使是多线程,事实上同一时刻只能保证一个线程在运行, 既然这样多线程的运行效率不就和单线程一样了吗,那为什么还要使用多线程呢?

由于以前的电脑基本都是单核CPU,多线程和单线程几乎看不出差别,可是由于计算机的迅速发展,现在的电脑几乎都是多核CPU了,最少也是两个核心数的,这时差别就出来了:通过之前的案例我们已经知道,即使在多核CPU中,多线程同一时刻也只有一个线程在运行,这样不仅不能利用多核CPU的优势,反而由于每个线程在多个CPU上是交替执行的,导致在不同CPU上切换时造成资源的浪费,反而会更慢。即原因是一个进程只存在一把gil锁,当在执行多个线程时,内部会争抢gil锁,这会造成当某一个线程没有抢到锁的时候会让cpu等待,进而不能合理利用多核cpu资源。

但是在使用多线程抓取网页内容时,遇到IO阻塞时,正在执行的线程会暂时释放GIL锁,这时其它线程会利用这个空隙时间,执行自己的代码,因此多线程抓取比单线程抓取性能要好,所以我们还是要使用多线程的。

GIL对多线程Python程序的影响

程序的性能受到计算密集型(CPU)的程序限制和I/O密集型的程序限制影响,那什么是计算密集型和I/O密集型程序呢?

计算密集型:要进行大量的数值计算,例如进行上亿的数字计算、计算圆周率、对视频进行高清解码等等。这种计算密集型任务虽然也可以用多任务完成,但是花费的主要时间在任务切换的时间,此时CPU执行任务的效率比较低。

IO密集型:涉及到网络请求(time.sleep())、磁盘IO的任务都是IO密集型任务,这类任务的特点是CPU消耗很少,任务的大部分时间都在等待IO操作完成(因为IO的速度远远低于CPU和内存的速度)。对于IO密集型任务,任务越多,CPU效率越高,但也有一个限度。

当然为了避免GIL对我们程序产生影响,我们也可以使用,线程锁。

Lock&RLock

常用的资源共享锁机制:有Lock、RLock、Semphore、Condition等,简单给大家分享下Lock和RLock。

Lock

特点就是执行速度慢,但是保证了数据的安全性

RLock

使用锁代码操作不当就会产生死锁的情况。

什么是死锁

死锁:当线程A持有独占锁a,并尝试去获取独占锁b的同时,线程B持有独占锁b,并尝试获取独占锁a的情况下,就会发生AB两个线程由于互相持有对方需要的锁,而发生的阻塞现象,我们称为死锁。即死锁是指多个进程因竞争资源而造成的一种僵局,若无外力作用,这些进程都将无法向前推进。

所以,在系统设计、进程调度等方面注意如何不让这四个必要条件成立,如何确定资源的合理分配算法,避免进程永久占据系统资源。

死锁代码

python线程间通信

如果各个线程之间各干各的,确实不需要通信,这样的代码也十分的简单。但这一般是不可能的,至少线程要和主线程进行通信,不然计算结果等内容无法取回。而实际情况中要复杂的多,多个线程间需要交换数据,才能得到正确的执行结果。

python中Queue是消息队列,提供线程间通信机制,python3中重名为为queue,queue模块块下提供了几个阻塞队列,这些队列主要用于实现线程通信。

在 queue 模块下主要提供了三个类,分别代表三种队列,它们的主要区别就在于进队列、出队列的不同。

简单代码演示

此时代码会阻塞,因为queue中内容已满,此时可以在第四个queue.put('苹果')后面添加timeout,则成为 queue.put('苹果',timeout=1)如果等待1秒钟仍然是满的就会抛出异常,可以捕获异常。

同理如果队列是空的,无法获取到内容默认也会阻塞,如果不阻塞可以使用queue.get_nowait()。

在掌握了 Queue 阻塞队列的特性之后,在下面程序中就可以利用 Queue 来实现线程通信了。

下面演示一个生产者和一个消费者,当然都可以多个

使用queue模块,可在线程间进行通信,并保证了线程安全。

协程

协程,又称微线程,纤程。英文名Coroutine。

协程是python个中另外一种实现多任务的方式,只不过比线程更小占用更小执行单元(理解为需要的资源)。为啥说它是一个执行单元,因为它自带CPU上下文。这样只要在合适的时机, 我们可以把一个协程 切换到另一个协程。只要这个过程中保存或恢复 CPU上下文那么程序还是可以运行的。

通俗的理解:在一个线程中的某个函数,可以在任何地方保存当前函数的一些临时变量等信息,然后切换到另外一个函数中执行,注意不是通过调用函数的方式做到的,并且切换的次数以及什么时候再切换到原来的函数都由开发者自己确定。

在实现多任务时,线程切换从系统层面远不止保存和恢复 CPU上下文这么简单。操作系统为了程序运行的高效性每个线程都有自己缓存Cache等等数据,操作系统还会帮你做这些数据的恢复操作。所以线程的切换非常耗性能。但是协程的切换只是单纯的操作CPU的上下文,所以一秒钟切换个上百万次系统都抗的住。

greenlet与gevent

为了更好使用协程来完成多任务,除了使用原生的yield完成模拟协程的工作,其实python还有的greenlet模块和gevent模块,使实现协程变的更加简单高效。

greenlet虽说实现了协程,但需要我们手工切换,太麻烦了,gevent是比greenlet更强大的并且能够自动切换任务的模块。

其原理是当一个greenlet遇到IO(指的是input output 输入输出,比如网络、文件操作等)操作时,比如访问网络,就自动切换到其他的greenlet,等到IO操作完成,再在适当的时候切换回来继续执行。

模拟耗时操作:

如果有耗时操作也可以换成,gevent中自己实现的模块,这时候就需要打补丁了。

使用协程完成一个简单的二手房信息的爬虫代码吧!

以下文章来源于Python专栏 ,作者宋宋

文章链接:https://mp.weixin.qq.com/s/2r3_ipU3HjdA5VnqSHjUnQ

6. python异步有哪些方式

yield相当于return,他将相应的值返回给调用next()或者send()的调用者,从而交出了CPU使用权,而当调用者再次调用next()或者send()的时候,又会返回到yield中断的地方,如果send有参数,还会将参数返回给yield赋值的变量,如果没有就和next()一样赋值为None。但是这里会遇到一个问题,就是嵌套使用generator时外层的generator需要写大量代码,看如下示例:
注意以下代码均在Python3.6上运行调试

#!/usr/bin/env python# encoding:utf-8def inner_generator():
i = 0
while True:
i = yield i if i > 10: raise StopIterationdef outer_generator():
print("do something before yield")
from_inner = 0
from_outer = 1
g = inner_generator()
g.send(None) while 1: try:
from_inner = g.send(from_outer)
from_outer = yield from_inner except StopIteration: breakdef main():
g = outer_generator()
g.send(None)
i = 0
while 1: try:
i = g.send(i + 1)
print(i) except StopIteration: breakif __name__ == '__main__':
main()041

为了简化,在Python3.3中引入了yield from

yield from

使用yield from有两个好处,

1、可以将main中send的参数一直返回给最里层的generator,
2、同时我们也不需要再使用while循环和send (), next()来进行迭代。

我们可以将上边的代码修改如下:

def inner_generator():
i = 0
while True:
i = yield i if i > 10: raise StopIterationdef outer_generator():
print("do something before coroutine start") yield from inner_generator()def main():
g = outer_generator()
g.send(None)
i = 0
while 1: try:
i = g.send(i + 1)
print(i) except StopIteration: breakif __name__ == '__main__':
main()

执行结果如下:

do something before coroutine start123456789101234567891011

这里inner_generator()中执行的代码片段我们实际就可以认为是协程,所以总的来说逻辑图如下:

我们都知道Python由于GIL(Global Interpreter Lock)原因,其线程效率并不高,并且在*nix系统中,创建线程的开销并不比进程小,因此在并发操作时,多线程的效率还是受到了很大制约的。所以后来人们发现通过yield来中断代码片段的执行,同时交出了cpu的使用权,于是协程的概念产生了。在Python3.4正式引入了协程的概念,代码示例如下:

import asyncio# Borrowed from http://curio.readthedocs.org/en/latest/[email protected] countdown(number, n):
while n > 0:
print('T-minus', n, '({})'.format(number)) yield from asyncio.sleep(1)
n -= 1loop = asyncio.get_event_loop()
tasks = [
asyncio.ensure_future(countdown("A", 2)),
asyncio.ensure_future(countdown("B", 3))]
loop.run_until_complete(asyncio.wait(tasks))
loop.close()12345678910111213141516

示例显示了在Python3.4引入两个重要概念协程和事件循环,
通过修饰符@asyncio.coroutine定义了一个协程,而通过event loop来执行tasks中所有的协程任务。之后在Python3.5引入了新的async & await语法,从而有了原生协程的概念。

async & await

在Python3.5中,引入了aync&await 语法结构,通过”aync def”可以定义一个协程代码片段,作用类似于Python3.4中的@asyncio.coroutine修饰符,而await则相当于”yield from”。

先来看一段代码,这个是我刚开始使用async&await语法时,写的一段小程序。

#!/usr/bin/env python# encoding:utf-8import asyncioimport requestsimport time


async def wait_download(url):
response = await requets.get(url)
print("get {} response complete.".format(url))


async def main():
start = time.time()
await asyncio.wait([
wait_download("http://www.163.com"),
wait_download("http://www.mi.com"),
wait_download("http://www.google.com")])
end = time.time()
print("Complete in {} seconds".format(end - start))


loop = asyncio.get_event_loop()
loop.run_until_complete(main())

这里会收到这样的报错:

Task exception was never retrieved
future: <Task finished coro=<wait_download() done, defined at asynctest.py:9> exception=TypeError("object Response can't be used in 'await' expression",)>
Traceback (most recent call last):
File "asynctest.py", line 10, in wait_download
data = await requests.get(url)
TypeError: object Response can't be used in 'await' expression123456

这是由于requests.get()函数返回的Response对象不能用于await表达式,可是如果不能用于await,还怎么样来实现异步呢?
原来Python的await表达式是类似于”yield from”的东西,但是await会去做参数检查,它要求await表达式中的对象必须是awaitable的,那啥是awaitable呢? awaitable对象必须满足如下条件中其中之一:

1、A native coroutine object returned from a native coroutine function .

原生协程对象

2、A generator-based coroutine object returned from a function decorated with types.coroutine() .

types.coroutine()修饰的基于生成器的协程对象,注意不是Python3.4中asyncio.coroutine

3、An object with an await method returning an iterator.

实现了await method,并在其中返回了iterator的对象

根据这些条件定义,我们可以修改代码如下:

#!/usr/bin/env python# encoding:utf-8import asyncioimport requestsimport time


async def download(url): # 通过async def定义的函数是原生的协程对象
response = requests.get(url)
print(response.text)


async def wait_download(url):
await download(url) # 这里download(url)就是一个原生的协程对象
print("get {} data complete.".format(url))


async def main():
start = time.time()
await asyncio.wait([
wait_download("http://www.163.com"),
wait_download("http://www.mi.com"),
wait_download("http://www.google.com")])
end = time.time()
print("Complete in {} seconds".format(end - start))


loop = asyncio.get_event_loop()
loop.run_until_complete(main())27282930

好了现在一个真正的实现了异步编程的小程序终于诞生了。
而目前更牛逼的异步是使用uvloop或者pyuv,这两个最新的Python库都是libuv实现的,可以提供更加高效的event loop。

uvloop和pyuv

pyuv实现了Python2.x和3.x,但是该项目在github上已经许久没有更新了,不知道是否还有人在维护。
uvloop只实现了3.x, 但是该项目在github上始终活跃。

它们的使用也非常简单,以uvloop为例,只需要添加以下代码就可以了

import asyncioimport uvloop
asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())123

7. python多线程只第一个while循环

Python 多线程只执行第一个 while 循环的原因是因为 Python 的全局锁 (GIL) 的存在。GIL 是为了保证多线程操作时不会出现数据竞争和死锁的问题,它会确保在任意时刻只有一个线程在执行 Python 代码。虽然多线程在 Python 中可以提高程序的并发性,但是由于 GIL 的存在,导致 Python 的多线程无法真正地实现并行计算。因此,在 Python 中,多线程适合于 IO 密集型任务,而不适合于 CPU 密集型任务。

对于如何解决多线程只执行第一个 while 循环的问题,可以使用多进程和协程来代替多线程。多进程可以在不同的进程中运行 Python 代码,每个进程都有自己的 GIL,因此可以实现真正的并行计算。而协程则是一种轻量级的线程,它不需要像线程一样占用系统资源,只需要在程序内部切换来实现并发计算皮渣。悔睁因此,在 Python 中,多进程和协程都是比较好的并发编程方式。

需要注意的是,多线程虽然存在 GIL 的限制,但对于一些 IO 密集型任务,多线程仍然可以提高程序的并发能力,因为在 IO 操作时,线程会释放 GIL,从而可以让其他线程进入运行状态。因此,在实际编程中,需要燃前悄根据具体的任务需求,选择合适的并发编程方式。

8. python培训入门教程怎样入门呢_如何学python入门

送你一份学习python的路线图

一、Python的普及入门

1.1Python入门学习须知和书本配套学习建议

1.2Python简史

1.3Python的市场需求及职业规划

1.4Python学习是选择2.0还是3.0?

二、Python的学谨念习环境安装

1.在Windows安装Python的教程

2.在Linux上安装python

3.搭建Python多版本共存管理工具Pyenv

4.Python开发环境配置

三、开启你的Python之路

1.Python世界的开端:helloworld

2.Python世界的开端:四则运算

3.Python流程控制语句深度解读

4.Python循环

四、Python中级进阶

1.Python数据类型详解

2.Python列表及元组详解

3.Python字符串操作深度解析

4.Python函数式编程指南:函数

5.Python函数式编程指南:迭代器

6.Python函数式编程指南:生成器

7.Python装饰器详解

五、Python高级技巧

1.装饰器深度解析

2.深入Python字典

3.Python线程技术

4.Python的异步IO:Asyncio简介

5.Python实现线程安全队列

六、Python常用工具

1.2017最受欢迎的15大Python库

2.5个高效Python库

3.Django官方教程

4.PythonDjango的正确学习方法

5.Python自然语逗晌烂言处理工具小结

6.数据科学常用Python工具

七、Python实战练习

1.Python破解斗地主残局

2.python实现爬虫功能

4.使用Python_PCA分析进行金融数据分析

5.用python制作游戏外挂吗?

6.运用爬虫抓取网易云音乐评论生成词云

7.使用Scrapy爬起点网的完本小说

8.TensorFlow计算加速

八、其他

1.选择学习编程,为什么一定首推Python?

2.为什么Python这么火?

3.Python如何快速入门?

4.Python入门之学习资料推荐

5.Python必备的19个编程资山漏源

6.Python入门知识点总结

7.Python学不好怎么办?

8.Python学习有哪些阶段?

9.参加Python培训会有前景吗?

10.Python培训班真的有效吗?

11.参加Python培训前应该做哪些准备?

12.11道Python基本面试题|深入解答

13.Python求职怎么拿到Offer

9. python主要是做什么

在我看来,Python 可以做任何事情。无论是从入门级选手到专业级选手都在做的爬虫,还是Web 程序开发、桌面程序开发还是科学计
算、图像处理,Python都可以胜任。
Python为我们提供了非常完善的基础代码库,覆盖了网络、文件、GUI、数据库、文本等大量内容,被形象地称作“内置电池(Batteries
included)”。用Python开发,许多功能不必从零编写,直接使用现成的即可。
除了内置的库外,Python还有大量的第三方库,也就是别人开发的,供你直接使用的东西。当然,如果你开发的代码通过很好的封装,
也可以作为第三方库给别人使用。
许多大型网站就是用Python开发的,例如YouTube、Instagram,还有国内的豆瓣。很多大公司,包括Google、Yahoo等,甚至
NASA(美国航空航天局)都大量地使用Python。
龟叔给Python的定位是“优雅”、“明确”、“简单”,所以Python程序看上去总是简单易懂,初学者学Python,不但入门容易,而且
将来深入下去,可以编写那些非常非常复杂的程序。
总的来说,Python的哲学就是简单优雅,尽量写容易看明白的代码,尽量写少的代码。如果一个资深程序员向你炫耀他写的晦涩难懂、
动不动就几万行的代码,你可以尽情地嘲笑他。
python学习网,免费的python学习网站,欢迎在线学习!

10. Python异步编程7:异步迭代器

迭代器:在其内部实现yield方法和next方法的对象。可迭代对象:在类内部实现一个iter方法,并返回一个迭代器。

异步迭代器:实现了__aiter__()和__anext__()方法的对象,必须返回一个awaitable对象。async_for支持处理异步迭代器的

__anext__()方法返回的可等侍春待对象,直到引发一个stopAsyncIteration异常谨乎,这个改动由PEP 492引入。

异步可迭代对象:可在async_for语句中被使用的对象,必须通过它的__aiter__()方法老晌耐返回一个asynchronous_iterator(异步迭代器).  这个改动由PEP 492引入。

示例: 不能直接写在普通方法或者暴露在外面。必须写在协程函数,任意协程函数均可。

热点内容
linuxshellif 发布:2024-05-04 17:09:47 浏览:15
算法精英挑战赛 发布:2024-05-04 17:09:08 浏览:738
河南电力公众号绑定密码是多少 发布:2024-05-04 17:08:55 浏览:331
手机上怎么打开压缩文件 发布:2024-05-04 17:03:57 浏览:171
word加密文件如何解密 发布:2024-05-04 17:02:57 浏览:289
php源码本地测试 发布:2024-05-04 16:57:17 浏览:800
c语言编译exe 发布:2024-05-04 16:57:16 浏览:974
国密算法获取 发布:2024-05-04 16:38:24 浏览:70
脚本精灵荒野乱斗 发布:2024-05-04 16:28:33 浏览:520
刚到的笔记本怎么看配置 发布:2024-05-04 16:26:58 浏览:4