基于回调的异步编程模式,其中最大的不满是关于 “堆栈撕裂stack ripping”:当一个回调抛出异常,它的堆栈回溯通常是毫无用处的。它只显示出事件循环运行了它,而没有说为什么。那么协程怎么样?以下是小编为你整理的python从入门到实践epub
读优秀的开源项目源码。这个过程中不断的反思和积累各种经验。有了问题就要google stackoverflow github 去找。
看别人的博客。但是要掌握一些过滤不好信息的技巧。有些订阅列表 我在专栏中也有写。大家有空可以去看看。我还订阅了python社区的一些邮件列表,说实话很烦。但是有时候你们看到一些社区开发者讨论,甚至是激烈讨论。我喜欢静静的看他们,学习他们对一些事情的看法,和思考的角度。
多看书,视频。
[图片0]
这不是一本常规意义上Python的入门书。这本书中没有Python关键字和for循环的使用,也没有细致入微的标准库介绍,而是完全从实战的角度出发,对构建一个完整的Python应用所需掌握的知识进行了系统而完整的介绍。更为难得的是,本书的作者是开源项目OpenStack的PTL(项目技术负责人)之一,因此本书结合了Python在OpenStack中的应用进行讲解,非常具有实战指导意义。
《Python Cookbook(第3版)中文版》介绍了Python应用在各个领域中的一些使用技巧和方法,其主题涵盖了数据结构和算法,字符串和文本,数字、日期和时间,迭代器和生成器,文件和I/O,数据编码与处理,函数,类与对象,元编程,模块和包,网络和Web编程,并发,实用脚本和系统管理,测试、调试以及异常,C语言扩展等。
python简介
python(蟒蛇)是一门面向对象的脚本解释语言,是一个叫Guido van Rossum的荷兰人在1989年发明的,第一个公开发行版发行于1991年。
python是自由软件,源代码和解释器都遵循GPL开源协议。
python是一门计算机语言。非专业的你只需要知道这一点,python是一个用来编程写程序的一套规则或者说一套开发软件。
专业的你还需要知道,python是开源的,也就是说你可以传播python解释器的源代码,修改并研究它,面向对象编程,并且是一种非编译型的解释性语言。
python的优势
python编写简单、拥有丰富的库。
代码易读,易维护。(python规定强制用空白符作为语句缩进)
有一个在美国工作的朋友对我说,美国的六岁小孩子都在用python编程。足见python的简单性。
库方面很丰富,有成千上万的python库,甚至简单要写爬虫只需要一个wget
学python能从业什么工作?
unix/linux网络运维
数据挖掘/数据运维
web开发
在国内,绝大部分是作为linux管理,或者数据运维
python能做什么?
web开发,系统管理,游戏开发,网络程序开发,最出名的是python爬数据
等等...
python的版本
目前常用的是python2和python3
但是需要注意一点python3向下兼容并不好,也就是说python2的代码,可能在python3上不能运行。但是python3的代码却绝对可以在python2上兼容。
Python解释器
Python是一门具有强类型(即变量类型是强制要求的)、动态性、隐式类型(不需要做变量声明)、大小写敏感(var和VAR代表了不同的变量)以及面向对象(一切皆为对象)等特点的编程语言。
你可以很容易的通过Python解释器获取帮助。如果你想知道一个对象(object)是如何工作的,那么你所需要做的就是调用help()!另外还有一些有用的方法,dir()会显示该对象的所有方法,还有.__doc__会显示其文档:
[图片1]
Python中没有强制的语句终止字符,且代码块是通过缩进来指示的。缩进表示一个代码块的开始,逆缩进则表示一个代码块的结束。声明以冒号(:)字符结束,并且开启一个缩进级别。单行注释以井号字符(#)开头,多行注释则以多行字符串的形式出现。赋值(事实上是将对象绑定到名字)通过等号(“=”)实现,双等号(“==”)用于相等判断,”+=”和”-=”用于增加/减少运算(由符号右边的值确定增加/减少的值)。这适用于许多数据类型,包括字符串。你也可以在一行上使用多个变量。例如:
Python具有列表(list)、元组(tuple)和字典(dictionaries)三种基本的数据结构,而集合(sets)则包含在集合库中(但从版本开始正式成为Python内建类型)。列表的特点跟一维数组类似(当然你也可以创建类似多维数组的“列表的列表”),字典则是具有关联关系的数组(通常也叫做哈希表),而元组则是不可变的一维数组(Python中“数组”可以包含任何类型的元素,这样你就可以使用混合元素,例如整数、字符串或是嵌套包含列表、字典或元组)。数组中第一个元素索引值(下标)为0,使用负数索引值能够从后向前访问数组元素,-1表示最后一个元素。数组元素还能指向函数。
多线程提取子协程
>>> def gen_fn(): ... raise Exception('my error') >>> caller = caller_fn() >>> (None) Traceback (most recent call last): File "input", line 1, in File "input", line 3, in caller_fn File "input", line 2, in gen_fn Exception: my error
这还是非常有用的,当异常抛出时,堆栈回溯显示出 caller_fn 委派了 gen_fn。令人更欣慰的是,你可以在一次异常处理器中封装这个调用到一个子过程中,像正常函数一样:
>>> def gen_fn(): ... yield 1 ... raise Exception('uh oh') ... >>> def caller_fn(): ... try: ... yield from gen_fn() ... except Exception as exc: ... print('caught {}'.format(exc)) ... >>> caller = caller_fn() >>> (None) 1 >>> ('hello') caught uh oh
所以我们可以像提取子过程一样提取子协程。让我们从 fetcher 中提取一些有用的子协程。我们先写一个可以读一块数据的协程 read:
def read(sock): f = Future() def on_readable(): ((4096)) ((), EVENT_READ, on_readable) chunk = yield f # Read one chunk. (()) return chunk
在 read 的基础上,read_all 协程读取整个信息:
def read_all(sock): response = [] # Read whole response. chunk = yield from read(sock) while chunk: (chunk) chunk = yield from read(sock) return b''.join(response)
如果你换个角度看,抛开 yield form 语句的话,它们就像在做阻塞 I/O 的普通函数一样。但是事实上,read 和 read_all 都是协程。yield from read 暂停 read_all 直到 I/O 操作完成。当 read_all 暂停时,asyncio 的事件循环正在做其它的工作并等待其他的 I/O 操作。read 在下次循环中当事件就绪,完成 I/O 操作时,read_all 恢复运行。
最终,fetch 调用了 read_all:
class Fetcher: def fetch(self): # ... connection logic from above, then: (('ascii')) = yield from read_all(sock)
神奇的是,Task 类不需要做任何改变,它像以前一样驱动外部的 fetch 协程:
Task(()) loop()
当 read yield 一个 future 时,task 从 yield from 管道中接收它,就像这个 future 直接从 fetch yield 一样。当循环解决一个 future 时,task 把它的结果送给 fetch,通过管道,read 接受到这个值,这完全就像 task 直接驱动 read 一样:
Figure - Yield From
为了完善我们的协程实现,我们再做点打磨:当等待一个 future 时,我们的代码使用 yield;而当委派一个子协程时,使用 yield from。不管是不是协程,我们总是使用 yield form 会更精炼一些。协程并不需要在意它在等待的东西是什么类型。
在 Python 中,我们从生成器和迭代器的高度相似中获得了好处,将生成器进化成 caller,迭代器也可以同样获得好处。所以,我们可以通过特殊的实现方式来迭代我们的 Future 类:
# Method on Future class. def __iter__(self): # Tell Task to resume me here. yield self return
future 的 __iter__ 方法是一个 yield 它自身的一个协程。当我们将代码替换如下时:
# f is a Future. yield f
以及……:
# f is a Future. yield from f
……结果是一样的!驱动 Task 从它的调用 send 中接收 future,并当 future 解决后,它发回新的结果给该协程。