Entries Category “Python”

Wed 18 May 2016

Greenlet: 轻量级并发编程

动机 greenlet这个包拆分自Stackless。Stackless是一个CPython的版本,实现并支持一种叫做tasklets的微线程。Tasklets会以一种伪并发的方式运行(通常运行在单个或者一些系统级的线程中),它们之间通过channels来同步数据。 一个greenlet,从另一方面来说,依然是一种很原始的没有隐式调度的微线程。换句话说,就是协程(coroutine)。这在你想要完全控制代码的运行时是非常有用的。你可以在greenlet之上构建采用自定义调度方式的微线程。然而,使用greenlet来制作先进的控制流结构是很有用的。举个例子,我们可以重新创造生成器。和Python自带的生成器所不同的是,我们的生成器可以调用网状的方法,而且这些网状的方法也可以yield出值。(另外,你不需要再使用yield这个关键词了) 举例 我们来思考一个程序,用户可以在一个类终端控制台中输入命令来控制该程序。假设命令是一个字符一个字符的输入。在这样一个系统中,通常会存在如下一个循环: def process_commands(*args): while True: line = '' while not line.endswith('\n'): line += read_next_char() if line == 'quit\n': print ... read more
Tue 26 April 2016

Python单例模式的实现

由于实现的方式很多,先来3种。 1. 类实例实现的单例装饰器 import functools class Singleton(object): def __init__(self): self.instances = {} def __call__(self, cls): @functools.wraps(cls) def wrapper(*args, **kwargs) if not self.instances.get(cls): self.instances[cls] = cls(*args, **kwargs) return self.instances[cls] return wrapper singleton = Singleton() # 用法 @singleton class Test(object ... read more
Sun 27 March 2016

Python yield小记

yeild yield 一般搭配函数来定义一个Generator(生成器) 一个简单的例子: def f(): print "Today is 7.21" yield 6 f() 将会返回一个Generator, 而非像普通函数一样执行。想要使用生成器的话(比如 i)需要使用i.next() (与next(i)等效) 和i.send(value)。 >>> i = f() >>> i >>> i.next() Today is 7.21 6 >>> i.next() Traceback (most recent call last ... read more
Sun 27 March 2016

Python中一些容易被忽视的东西

旨在记录Python标准库中好像很厉害的模块或功能。 1. functools.partial(func[,args][, *keywords]) 2. globals() and locals() functools.partial(func[,args][, *keywords]) 为func的参数指定默认值后返回一个新的函数。比如: # disable print as the statement from __future__ import print_function from functools import partial from StringIO import StringIO f = StringIO.StringIO() print = partial(print, file=f) print("This will print to f) # stdout ... read more
Sun 27 March 2016

使用Python制作自定义终端命令

介绍 首先,拿pip举个例子,pip是我们使用较多的python包管理工具。当我们安装pip之后,直接在终端中就可以使用pip这个命令。那你有没有想过这是如何实现的? 其实,pip这个命令最终调用了python所在文件夹bin目录的pip文件。为什么说最终?因为使用系统默认的python安装pip时,可能会在/usr/local/bin或者/usr/bin下创建软链接。如果使用了virtualenv,那么pip文件就在env/bin下。那么pip文件到底是什么呢?答案就是,是一个具有执行权限的python文件,只不过去掉了.py的后缀. 也许你会兴高采烈的去尝试一发,在bin文件下创建xxx.py,打上一句 print “hello world”, 然后去掉.py的后缀, 再使用chmod a+x xxx来赋予它执行的权限。打开终端,敲下xxx。最后你只会得到print: command not found的错误提示。为什么?因为操作系统不知道这是一个py文件。思考一下,我们平时运行py文件都需要打上python xxx.py形式的命令 ... read more
Sun 27 March 2016

supervisor+celery+celerybeat的简单使用

1. 提前准备 略去相关工具的安装过程,其实都挺简单的! celery作为异步任务队列, 需要一个中间人来协助celery存放和消耗任务信息。我们选择rabbitmq来做消息代理人。使用celery之前, 需要使用创建一个rabbitmq的管理员账号和一个能让该账号访问的vhost. Rabbitmq的安装配置以及网页管理插件 假设准备的rabbitmq的信息如下: SETTINGS = { 'user': 'www-data', 'password': 'www-data', 'host': '127.0.0.1', 'port': '5672', 'vhost': 't_celery' } 示例项目结构 test.celery/ |- env/ |- src/ |- __init__.py |- app.py |- task.py 2. celery实例及任务 2.1 生成实例 # -*- coding: utf-8 -*- # filename: app.py from celery import Celery ... read more
Sun 27 March 2016

终端进度条的简单原理

进度条 每次使用pip安装一些第三方库时,总会在终端或者命令行中看到进度条,能够让用户等待时得到当前任务的进度。今天偶然在知乎看到一个帖子中提到了这个有趣的功能。 实现方式 一般情况下命令行和终端的输出总是由上往下一行一行输出。如果我们需要实现进度条的效果的效果的话,就需要每次输出都在同一行上,不断地用后来的输出去覆盖之前的输出,从而模拟出一种动态变化的效果。那究竟怎样实现呢?答案就是使用反杠r。 反杠n是换行,反杠r就只是把输出光标移到行首,而不换行。根据这个思路,我们先做个倒计时来玩玩。 import time import sys def CountDown(total_sec): for i in xrange(10, -1, -1): # 不能换行哈 print '%4d\\r' % i, sys.stdout.flush() time.sleep(1) # 防止输出被之后的输出覆盖 print CountDown(10 ... read more
Sat 26 March 2016

Python单层装饰器小记

解释器什么时候处理装饰器? 答: Python解释器加载代码的时候. 例如, sleep.py 代码如下 import functools import time def timer(func): print("handle decorator") @functools.wraps(func) def wrapper(*args, **kwargs): start = time.time() rtn = func(*args, **kwargs) cost = time.time() - start print("cost %f s") % cost return rtn return wrapper @timer def sleep(seconds): time.sleep ... read more
Sat 26 March 2016

Python的metaclass小记

使用metaclass的时候可以使用metaclass的__new__和__init__去改变所定义的类的相关属性,因为这两个方法是在类定义的时候被调用,他们所需的参数也与使用type(name, bases, dict)动态声明类相同。而使用metaclass的__call__可以影响我们所声明的类产生实例的过程,因为当我们使用class_name()去产生实例的时候,相当于call了这个class,而这个class又是metaclass的实例,所以其实调用了metaclass的__call__ 注意: 通过super来调用父类的__new__时,第一个参数需要是该class,这点是不同于调用__init__等其他父类方法的。因为__new__是个静态方法。还有一个小问题就是当父类是object的时候,也就是调用object.__new__()只传一个cls参数就可以了,至于为什么,请戳here 和here。 如果你重写了__new__而没有重写 ... read more
 

Tags