导航:首页 > 编程语言 > python添加异步函数

python添加异步函数

发布时间:2022-04-18 23:57:33

python 异步是什么意思

异步是计算机多线程的异步处理。与同步处理相对,异步处理不用阻塞当前线程来等待处理完成,而是允许后续操作,直至其它线程将处理完成,并回调通知此线程。

㈡ python里怎么实现异步调用

本文实例讲述了python使用multiprocessing模块实现带回调函数的异步调用方法。分享给大家供大家参考。具体分析如下:
multipressing模块是python 2.6版本加入的,通过这个模块可以轻松实现异步调用
from multiprocessing import Pool
def f(x):
return x*x
if __name__ == '__main__':
pool = Pool(processes=1)
# Start a worker processes.
result = pool.apply_async(f, [10], callback)
# Evaluate "f(10)" asynchronously calling callback when finished.
希望本文所述对大家的Python程序设计有所帮助。

㈢ 如何看待 Python 3.5支持Async/Await异步编程

根据Python增强提案(PEP) 第0492号, Python 3.5将通过async和await语法增加对协程的支持。该提案目的是使协程成为Python语言的原生特性,并“建立一种普遍、易用的异步编程思维模型。”

这个新提议中声明一个协程的语法如下:

async def read_data(db):
pass

async是明确将函数声明为协程的关键字,即便没有使用await表达式。这样的函数执行时会返回一个协程对象。

在协程函数内部,可在某个表达式之前使用await关键字来暂停协程的执行,以等待某进程完成:

async def read_data(db):
data = await db.fetch('SELECT ...')
...

由于增强版生成器的存在,Python中其实早已有了协程的形式,例如当yield或yield from声明在Python生成器内部出现,该生成器就会被当作协程。

以下示例展示基于生成器的协程的用法:

>>> def createGenerator():
... mylist = range(3)
... for i in mylist:
... yield i*i
...
>>> mygenerator = createGenerator()
>>> for i in mygenerator:
... print(i)
0
1
4

以上代码中,每当生成器在for循环中被调用,该生成器中的for循环就会返回一个新的值。

关于await用法的更多示例请参见上文提到的PEP #0492.

这个关于协程的新提案想明确地把生成器与协程区分开,这么做有如下好处:

㈣ python2.7怎么实现异步

改进之前
之前,我的查询步骤很简单,就是:
前端提交查询请求 --> 建立数据库连接 --> 新建游标 --> 执行命令 --> 接受结果 --> 关闭游标、连接
这几大步骤的顺序执行。
这里面当然问题很大:
建立数据库连接实际上就是新建一个套接字。这是进程间通信的几种方法里,开销最大的了。
在“执行命令”和“接受结果”两个步骤中,线程在阻塞在数据库内部的运行过程中,数据库连接和游标都处于闲置状态。
这样一来,每一次查询都要顺序的新建数据库连接,都要阻塞在数据库返回结果的过程中。当前端提交大量查询请求时,查询效率肯定是很低的。
第一次改进
之前的模块里,问题最大的就是第一步——建立数据库连接套接字了。如果能够一次性建立连接,之后查询能够反复服用这个连接就好了。
所以,首先应该把数据库查询模块作为一个单独的守护进程去执行,而前端app作为主进程响应用户的点击操作。那么两条进程怎么传递消息呢?翻了几天Python文档,终于构思出来:用队列queue作为生产者(web前端)向消费者(数据库后端)传递任务的渠道。生产者,会与SQL命令一起,同时传递一个管道pipe的连接对象,作为任务完成后,回传结果的渠道。确保,任务的接收方与发送方保持一致。
作为第二个问题的解决方法,可以使用线程池来并发获取任务队列中的task,然后执行命令并回传结果。
第二次改进
第一次改进的效果还是很明显的,不用任何测试手段。直接点击页面链接,可以很直观地感觉到反应速度有很明显的加快。
但是对于第二个问题,使用线程池还是有些欠妥当。因为,CPython解释器存在GIL问题,所有线程实际上都在一个解释器进程里调度。线程稍微开多一点,解释器进程就会频繁的切换线程,而线程切换的开销也不小。线程多一点,甚至会出现“抖动”问题(也就是刚刚唤醒一个线程,就进入挂起状态,刚刚换到栈帧或内存的上下文,又被换回内存或者磁盘),效率大大降低。也就是说,线程池的并发量很有限。
试过了多进程、多线程,只能在单个线程里做文章了。
Python中的asyncio库
Python里有大量的协程库可以实现单线程内的并发操作,比如Twisted、Gevent等等。Python官方在3.5版本里提供了asyncio库同样可以实现协程并发。asyncio库大大降低了Python中协程的实现难度,就像定义普通函数那样就可以了,只是要在def前面多加一个async关键词。async def函数中,需要阻塞在其他async def函数的位置前面可以加上await关键词。
import asyncio
async def wait():
await asyncio.sleep(2)
async def execute(task):
process_task(task)
await wait()
continue_job()
async def函数的执行稍微麻烦点。需要首先获取一个loop对象,然后由这个对象代为执行async def函数。
loop = asyncio.get_event_loop()
loop.run_until_complete(execute(task))
loop.close()
loop在执行execute(task)函数时,如果遇到await关键字,就会暂时挂起当前协程,转而去执行其他阻塞在await关键词的协程,从而实现协程并发。
不过需要注意的是,run_until_complete()函数本身是一个阻塞函数。也就是说,当前线程会等候一个run_until_complete()函数执行完毕之后,才会继续执行下一部函数。所以下面这段代码并不能并发执行。
for task in task_list:
loop.run_until_complete(task)
对与这个问题,asyncio库也有相应的解决方案:gather函数。
loop = asyncio.get_event_loop()
tasks = [asyncio.ensure_future(execute(task))
for task in task_list]
loop.run_until_complete(asyncio.gather(*tasks))
loop.close()
当然了,async def函数的执行并不只有这两种解决方案,还有call_soon与run_forever的配合执行等等,更多内容还请参考官方文档。
Python下的I/O多路复用
协程,实际上,也存在上下文切换,只不过开销很轻微。而I/O多路复用则完全不存在这个问题。
目前,linux上比较火的I/O多路复用API要算epoll了。Tornado,就是通过调用C语言封装的epoll库,成功解决了C10K问题(当然还有Pypy的功劳)。
在Linux里查文档,可以看到epoll只有三类函数,调用起来比较方便易懂。
创建epoll对象,并返回其对应的文件描述符(file descriptor)。
int epoll_create(int size);
int epoll_create1(int flags);
控制监听事件。第一个参数epfd就对应于前面命令创建的epoll对象的文件描述符;第二个参数表示该命令要执行的动作:监听事件的新增、修改或者删除;第三个参数,是要监听的文件对应的描述符;第四个,代表要监听的事件。
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
等候。这是一个阻塞函数,调用者会等候内核通知所注册的事件被触发。
int epoll_wait(int epfd, struct epoll_event *events,
int maxevents, int timeout);
int epoll_pwait(int epfd, struct epoll_event *events,
int maxevents, int timeout,
const sigset_t *sigmask);
在Python的select库里:
select.epoll()对应于第一类创建函数;
epoll.register(),epoll.unregister(),epoll.modify()均是对控制函数epoll_ctl的封装;
epoll.poll()则是对等候函数epoll_wait的封装。
Python里epoll相关API的最大问题应该是在epoll.poll()。相比于其所封装的epoll_wait,用户无法手动指定要等候的事件,也就是后者的第二个参数struct epoll_event *events。没法实现精确控制。因此只能使用替代方案:select.select()函数。
根据Python官方文档,select.select(rlist, wlist, xlist[, timeout])是对Unix系统中select函数的直接调用,与C语言API的传参很接近。前三个参数都是列表,其中的元素都是要注册到内核的文件描述符。如果想用自定义类,就要确保实现了fileno()方法。
其分别对应于:
rlist: 等候直到可读
wlist: 等候直到可写
xlist: 等候直到异常。这个异常的定义,要查看系统文档。
select.select(),类似于epoll.poll(),先注册文件和事件,然后保持等候内核通知,是阻塞函数。
实际应用
Psycopg2库支持对异步和协程,但和一般情况下的用法略有区别。普通数据库连接支持不同线程中的不同游标并发查询;而异步连接则不支持不同游标的同时查询。所以异步连接的不同游标之间必须使用I/O复用方法来协调调度。
所以,我的大致实现思路是这样的:首先并发执行大量协程,从任务队列中提取任务,再向连接池请求连接,创建游标,然后执行命令,并返回结果。在获取游标和接受查询结果之前,均要阻塞等候内核通知连接可用。
其中,连接池返回连接时,会根据引用连接的协程数量,返回负载最轻的连接。这也是自己定义AsyncConnectionPool类的目的。
我的代码位于:bottle-blog/dbservice.py
存在问题
当然了,这个流程目前还一些问题。
首先就是每次轮询拿到任务之后,都会走这么一个流程。
获取连接 --> 新建游标 --> 执行任务 --> 关闭游标 --> 取消连接引用
本来,最好的情况应该是:在轮询之前,就建好游标;在轮询时,直接等候内核通知,执行相应任务。这样可以减少轮询时的任务量。但是如果协程提前对应好连接,那就不能保证在获取任务时,保持各连接负载均衡了。
所以这一块,还有工作要做。
还有就是epoll没能用上,有些遗憾。
以后打算写点C语言的内容,或者用Python/C API,或者用Ctypes包装共享库,来实现epoll的调用。
最后,请允许我吐槽一下Python的epoll相关文档:简直太弱了!!!必须看源码才能弄清楚功能。

㈤ python 异步请求的时候怎么添加代理

有几种方法。一种是设置环境变量http_proxy,它会自动访问这个。 另外一种是你使用urllib2的时候,在参数里加上代理。还有一个是urllib上指定。

比如
import urllib
urllib.urlopen(某网站,proxyes={'http:':"某代理IP地址:代理的端口"})

使用QT时,它的浏览器设置代理要在浏览器初始化参数里指定。

㈥ python 多线程 怎么改成异步

python使用multiprocessing模块实现带回调函数的异步调用方法。分享给大家供大家参考。具体分析如下:
multipressing模块是python 2.6版本加入的,通过这个模块可以轻松实现异步调用
from multiprocessing import Pool
def f(x):
return x*x
if __name__ == '__main__':
pool = Pool(processes=1)
# Start a worker processes.
result = pool.apply_async(f, [10], callback)
# Evaluate "f(10)" asynchronously calling callback when finished.
希望本文所述对大家的Python程序设计有所帮助。

㈦ 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

㈧ 如何利用python asyncio编写异步爬虫

不兼容 最明显的是print变成了函数 最重要的变化一是python2里的str变为了python3里的byte,而str由unicode str取代,因此一些网络编程,hash加密的函数需要将参数encode处理。 第二点是大量的python2库没有被移植到python3,以request为例

㈨ Ppython await是什么

await的解释:

await用来声明程序挂起。

比如异步程序执行到某一步时需要等待的时间很长,就将此挂起,去执行其他的异步程序。

await 后面只能跟异步程序或有__await__属性的对象,因为异步程序与一般程序不同。

程序解释:

假设有两个异步函数async a,async b,a中的某一步有await,

当程序碰到关键字await b()后,异步程序挂起后去执行另一个异步b程序,就是从函数内部跳出去执行其他函数,

当挂起条件消失后,不管b是否执行完,要马上从b程序中跳出来,回到原程序执行原来的操作。

如果await后面跟的b函数不是异步函数,那么操作就只能等b执行完再返回,无法在b执行的过程中返回。

如果要在b执行完才返回,也就不需要用await关键字了,直接调用b函数就行。

所以这就需要await后面跟的是异步函数了。

在一个异步函数中,可以不止一次挂起,也就是可以用多个await。

更多Python知识,请关注:Python自学网!!

㈩ python 开发经验怎么xie

当我开始学习Python的时候,有些事我希望我一早就知道。我花费了很多时间才学会这些东西。我想要把这些重点都编纂到一篇文章当中。这篇文章的目标读者,是刚刚开始学习Python语言的有经验的程序员,想要跳过前几个月研究Python使用的那些他们已经在用的类似工具。包管理和标准工具这两节对于初学者来说同样很有帮助。
我的经验主要基于Python 2.7,但是大多数的工具对任何版本都有效。
如果你从来没有使用过Python,我强烈建议你阅读Python introction,因为你需要知道基本的语法和类型。
包管理
Python世界最棒的地方之一,就是大量的第三方程序包。同样,管理这些包也非常容易。按照惯例,会在 requirements.txt 文件中列出项目所需要的包。每个包占一行,通常还包含版本号。这里有一个例子,本博客使用Pelican:

1
2
3

pelican==3.3
Markdown
pelican-extended-sitemap==1.0.0

Python 程序包有一个缺陷是,它们默认会进行全局安装。我们将要使用一个工具,使我们每个项目都有一个独立的环境,这个工具叫virtualenv。我们同样要安装一个更高级的包管理工具,叫做pip,他可以和virtualenv配合工作。
首先,我们需要安装pip。大多数python安装程序已经内置了easy_install(python默认的包管理工具),所以我们就使用easy_install pip来安装pip。这应该是你最后一次使用easy_install 了。如果你并没有安装easy_install ,在linux系统中,貌似从python-setuptools 包中可以获得。
如果你使用的Python版本高于等于3.3, 那么Virtualenv 已经是标准库的一部分了,所以没有必要再去安装它了。
下一步,你希望安装virtualenv和virtualenvwrapper。Virtualenv使你能够为每个项目创造一个独立的环境。尤其是当你的不同项目使用不同版本的包时,这一点特别有用。Virtualenv wrapper 提供了一些不错的脚本,可以让一些事情变得容易。

1

sudo pip install virtualenvwrapper

当virtualenvwrapper安装后,它会把virtualenv列为依赖包,所以会自动安装。
打开一个新的shell,输入mkvirtualenv test 。如果你打开另外一个shell,则你就不在这个virtualenv中了,你可以通过workon test 来启动。如果你的工作完成了,可以使用deactivate 来停用。

IPython
IPython是标准Python交互式的编程环境的一个替代品,支持自动补全,文档快速访问,以及标准交互式编程环境本应该具备的很多其他功能。
当你处在一个虚拟环境中的时候,可以很简单的使用pip install ipython 来进行安装,在命令行中使用ipython 来启动

另一个不错的功能是”笔记本”,这个功能需要额外的组件。安装完成后,你可以使用ipython notebook,而且会有一个不错的网页UI,你可以创建笔记本。这在科学计算领域很流行。

测试
我推荐使用nose或是py.test。我大部分情况下用nose。它们基本上是类似的。我将讲解nose的一些细节。
这里有一个人为创建的可笑的使用nose进行测试的例子。在一个以test_开头的文件中的所有以test_开头的函数,都会被调用:

1
2

def test_equality():
assert True == False

不出所料,当运行nose的时候,我们的测试没有通过。

1
2
3
4
5
6
7
8
9
10
11
12
13

(test)jhaddad@jons-mac-pro ~VIRTUAL_ENV/src$ nosetests
F
======================================================================
FAIL: test_nose_example.test_equality
----------------------------------------------------------------------
Traceback (most recent call last):
File "/Users/jhaddad/.virtualenvs/test/lib/python2.7/site-packages/nose/case.py", line 197, in runTest
self.test(*self.arg)
File "/Users/jhaddad/.virtualenvs/test/src/test_nose_example.py", line 3, in test_equality
assert True == False
AssertionError
----------------------------------------------------------------------

nose.tools中同样也有一些便捷的方法可以调用

1
2
3

from nose.tools import assert_true
def test_equality():
assert_true(False)

如果你想使用更加类似JUnit的方法,也是可以的:

1
2
3
4
5
6
7
8
9
10

from nose.tools import assert_true
from unittest import TestCase
class ExampleTest(TestCase):
def setUp(self): # setUp & tearDown are both available
self.blah = False
def test_blah(self):
self.assertTrue(self.blah)

开始测试:

1
2
3
4
5
6
7
8
9
10
11
12
13
14

(test)jhaddad@jons-mac-pro ~VIRTUAL_ENV/src$ nosetests
F
======================================================================
FAIL: test_blah (test_nose_example.ExampleTest)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/Users/jhaddad/.virtualenvs/test/src/test_nose_example.py", line 11, in test_blah
self.assertTrue(self.blah)
AssertionError: False is not true
----------------------------------------------------------------------
Ran 1 test in 0.003s
FAILED (failures=1)

卓越的Mock库包含在Python 3 中,但是如果你在使用Python 2,可以使用pypi来获取。这个测试将进行一个远程调用,但是这次调用将耗时10s。这个例子显然是人为捏造的。我们使用mock来返回样本数据而不是真正的进行调用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14

import mock
from mock import patch
from time import sleep
class Sweetness(object):
def slow_remote_call(self):
sleep(10)
return "some_data" # lets pretend we get this back from our remote api call
def test_long_call():
s = Sweetness()
result = s.slow_remote_call()
assert result == "some_data"

当然,我们的测试需要很长的时间。

1
2
3
4
5

(test)jhaddad@jons-mac-pro ~VIRTUAL_ENV/src$ nosetests test_mock.py
Ran 1 test in 10.001s
OK

太慢了!因此我们会问自己,我们在测试什么?我们需要测试远程调用是否有用,还是我们要测试当我们获得数据后要做什么?大多数情况下是后者。让我们摆脱这个愚蠢的远程调用吧:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

import mock
from mock import patch
from time import sleep
class Sweetness(object):
def slow_remote_call(self):
sleep(10)
return "some_data" # lets pretend we get this back from our remote api call
def test_long_call():
s = Sweetness()
with patch.object(s, "slow_remote_call", return_value="some_data"):
result = s.slow_remote_call()
assert result == "some_data"

好吧,让我们再试一次:

1
2
3
4
5
6

(test)jhaddad@jons-mac-pro ~VIRTUAL_ENV/src$ nosetests test_mock.py
.
----------------------------------------------------------------------
Ran 1 test in 0.001s
OK

好多了。记住,这个例子进行了荒唐的简化。就我个人来讲,我仅仅会忽略从远程系统的调用,而不是我的数据库调用。
nose-progressive是一个很好的模块,它可以改善nose的输出,让错误在发生时就显示出来,而不是留到最后。如果你的测试需要花费一定的时间,那么这是件好事。
pip install nose-progressive 并且在你的nosetests中添加--with-progressive
调试
iPDB是一个极好的工具,我已经用它查出了很多匪夷所思的bug。pip install ipdb 安装该工具,然后在你的代码中import ipdb; ipdb.set_trace(),然后你会在你的程序运行时,获得一个很好的交互式提示。它每次执行程序的一行并且检查变量。

python内置了一个很好的追踪模块,帮助我搞清楚发生了什么。这里有一个没什么用的python程序:

1
2
3

a = 1
b = 2
a = b

这里是对这个程序的追踪结果:

1
2
3
4
5
6
7

(test)jhaddad@jons-mac-pro ~VIRTUAL_ENV/src$ python -m trace --trace tracing.py 1 ?
--- molename: tracing, funcname: <mole>
tracing.py(1): a = 1
tracing.py(2): b = 2
tracing.py(3): a = b
--- molename: trace, funcname: _unsettrace
trace.py(80): sys.settrace(None)

当你想要搞清楚其他程序的内部构造的时候,这个功能非常有用。如果你以前用过strace,它们的工作方式很相像
在一些场合,我使用pycallgraph来追踪性能问题。它可以创建函数调用时间和次数的图表。

最后,objgraph对于查找内存泄露非常有用。这里有一篇关于如何使用它查找内存泄露的好文。
Gevent
Gevent 是一个很好的库,封装了Greenlets,使得Python具备了异步调用的功能。是的,非常棒。我最爱的功能是Pool,它抽象了异步调用部分,给我们提供了可以简单使用的途径,一个异步的map()函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

from gevent import monkey
monkey.patch_all()
from time import sleep, time
def fetch_url(url):
print "Fetching %s" % url
sleep(10)
print "Done fetching %s" % url
from gevent.pool import Pool
urls = ["http://test.com", "http://bacon.com", "http://eggs.com"]
p = Pool(10)
start = time()
p.map(fetch_url, urls)
print time() - start

非常重要的是,需要注意这段代码顶部对gevent monkey进行的补丁,如果没有它的话,就不能正确的运行。如果我们让Python连续调用 fetch_url 3次,通常我们期望这个过程花费30秒时间。使用gevent:

1
2
3
4
5
6
7
8

(test)jhaddad@jons-mac-pro ~VIRTUAL_ENV/src$ python g.py
Fetching http://test.com
Fetching http://bacon.com
Fetching http://eggs.com
Done fetching http://test.com
Done fetching http://bacon.com
Done fetching http://eggs.com
10.001791954

如果你有很多数据库调用或是从远程URLs获取,这是非常有用的。我并不是很喜欢回调函数,所以这一抽象对我来说效果很好。

阅读全文

与python添加异步函数相关的资料

热点内容
php如何选中相同的进行修改 浏览:623
工行app个人怎么给企业账户转账 浏览:149
汇编与程序员 浏览:666
压缩包解码器下载 浏览:130
爱旅行的预备程序员 浏览:111
安卓qq浏览器怎么转换到ios 浏览:292
不同编译器的库可以调用吗 浏览:455
灰度信托基金加密 浏览:421
宿迁程序员兼职网上接单 浏览:924
电视编译器怎么设置 浏览:276
手机如何解压汉字密码的压缩包 浏览:701
为什么很多程序员爱用vim 浏览:828
安卓手机怎么连接宝华韦健音响 浏览:555
12星座制作解压球 浏览:867
java调用oracle数据 浏览:827
怎么在服务器上上传小程序源码 浏览:304
空中加油通达信指标公式源码 浏览:38
分卷解压只解压了一部分 浏览:760
php网站自动登录 浏览:705
合肥凌达压缩机招聘 浏览:965