存档

‘python’ 分类的存档

Build Emacs As A Python IDE

2014年12月30日 没有评论

众所周知在很久很久以前, 初学者要把 Emacs 搭建成比较容易上手的环境, 需要 一点精力和耐心, 但这恰恰是 Emacs 的魅力所在(超高度的可定制化), 但对初学者来说, 由于 el-get包管理器 的出现, 情况变得越来越好了. 比如要马上开始用 Emacs 来作为开发 Python 的工具, 现在已经很简单了.

安装 el-get

将下列配置写入到 .emacs 中

(add-to-list 'load-path "~/.emacs.d/el-get/el-get")
(unless (require 'el-get nil 'noerror)
  (with-current-buffer
      (url-retrieve-synchronously
       "https://raw.github.com/dimitri/el-get/master/el-get-install.el")
    (let (el-get-master-branch)
      (goto-char (point-max))
      (eval-print-last-sexp))))
 
(el-get 'sync)

just it! 启动 emacs 的时候会自动初始化 el-get 需要的配置信息

jedi

jedi 主要是一个自动补全的插件, Emacs 已经有一个名为 auto-complete 的强大的 补全插件了, 通吃所有语言. 没错, jedi 的自动补全就是利用该插件作为后端了, 不仅如此, 他还可以在编写代码的时候实时查看函数的成员信息, 函数的参数信息和文档信息等, 总之很强大.

使用 el-get-install 回车, 输出 jedi 安装, 借助 el-get 的强大, 所有的依赖都会 自动安装(.e.g. auto-complete, epc)

M-x el-get-install

在 .emacs 里加入 jedi 的配置

add-hook 'python-mode-hook 'jedi:setup)
(setq jedi:complete-on-dot t)

ropemacs

ropemacs 是借助 rope, pymacs 来做 python 的工程管理的东西, 在它面前, 神马 代码重构, 代码跳转, 自动模块导入, 类成员补全神马都是浮云. (注意, 所有代码 补全我都使用 jedi 来做, 不用到这里的功能)

安装也很方便, 直接 el-get-install 然后回车输入 ropemacs 就可以了

安装完成在 .emacs 里加入

(pymacs-load "ropemacs" "rope-")
(setq ropemacs-enable-autoimport t)
 
(autoload 'pymacs-apply "pymacs")
(autoload 'pymacs-call "pymacs")
(autoload 'pymacs-eval "pymacs" nil t)
(autoload 'pymacs-exec "pymacs" nil t)
(autoload 'pymacs-load "pymacs" nil t)

flycheck

该插件是一个实时代码检查的工具, 也就是在编代码的过程中, 会根据改语言的编码 规范, 实时检查和提示源代码的错误, 然后给出警告, 比如语法错误, 编码规范 等. 该插件也是通吃所有语言, 这里我们只关注 python 相关的

直接 el-get-install 然后回车输入 flycheck 安装.

在 .emacs 里面加入

(add-hook 'after-init-hook #'global-flycheck-mode)

注意, flycheck 需要一个检查语法的后端程序, 如果是 python 的话, 推荐 pylink,

# pip install pylink

后记

不考虑其他的配置, 什么强大的 ido, ibuffer, 按键绑定配置, 窗口配置等等, 一个 标准的 python IDE 就配置好了, 就这么简单.

附上所有的 .emacs 配置

(add-to-list 'load-path "~/.emacs.d/el-get/el-get")
(unless (require 'el-get nil 'noerror)
  (with-current-buffer
      (url-retrieve-synchronously
       "https://raw.github.com/dimitri/el-get/master/el-get-install.el")
    (let (el-get-master-branch)
      (goto-char (point-max))
      (eval-print-last-sexp))))
 
(el-get 'sync)
(add-hook 'python-mode-hook 'jedi:setup)
(setq jedi:complete-on-dot t)
 
(add-hook 'after-init-hook #'global-flycheck-mode)
 
(pymacs-load "ropemacs" "rope-")
(setq ropemacs-enable-autoimport t)
 
(autoload 'pymacs-apply "pymacs")
(autoload 'pymacs-call "pymacs")
(autoload 'pymacs-eval "pymacs" nil t)
(autoload 'pymacs-exec "pymacs" nil t)
(autoload 'pymacs-load "pymacs" nil t)

分类: Emacs, python 标签: ,

python paste.deploy 探索

2014年10月15日 没有评论

简介

Paste Deployment 是一个用来查找和配置 WSGI 应用的系统. 只需要利用它提供的一个 简单的入口 loadapp, 就可以从配置文件或者 python EGG 里加载 WSGI 应用. 用户 所要做的, 仅仅是调用 loadapp 接口, 不需要暴露程序内部的实现细节.

配置文件说明

配置文件是 INI 格式 的, 被分为不同的段, 每个段的段名由 [类型:名字] 组成, 类型包括以下几种:

app

app 接受的参数(environ, start_response), app 需要完成的任务是响应 envrion 中的请求, 准备好响应头和消息体, 然后交给 start_response 处理, 并返回响应消息体. 这个比较好理解, 就是 WSGI 直接调用 app 指定的对象.

filter

filter 是过滤器, 和 python 中的装饰器是一个路子, 它接受一个 app 对象作为参数, 返回一个封装后的 app. 在一般的应用中, 可能在运行到最后一个 app 时候, 前面需要先 处理其他 filter, 如果在处理某一个 filter 的时候, 某些判断条件未通过, filter 有权直接返回, 不交由下面的模块继续处理, 比如认证未通过等.

filter-app

也是一个过滤器, 在某个应用只需要一个过滤器的时候, 一般用该类型, 它需要一个 next 字段指定这个 filter 应用到哪个应用上.

pipeline

如果需要使用多个 filter 过滤一个应用, 需要使用 pipeline 的方式, 他的配置就是一个 名为 pipeline 的 key, value 是以多个 filter和最后的一个应用结尾的列表: 如

[pipeline:main]
pipeline = filter1 filter2 filter3 app

composite

用来完成将将一个请求调度定向(dispatched)到多个(多种)应用上. 比如应用有 v1, v2 的版本, 就可以用 composite 来做调度. composite 其实像是 app, 但是实际上是由 多个应用组成. 比如下面是 openstack glance 的使用

[composite:rootapp]
paste.composite_factory = glance.api:root_app_factory
/: apiversions
/v1: apiv1app
/v2: apiv2app

使用示例

app

下面的例子展示了一个只有名为 blog 的app, 配置文件指定了 app_factory 为 Blog.factory, 这个工厂函数会创建一个 Blog 的实例, 当然你需要实现该类的 __call__ 方法, 这样 wsgi 就会在适当的使用调用你完成你想要做的.

# file: app.ini
[app:blog]
paste.app_factory = app:Blog.factory
# use = call:app:blog_app
#!/usr/bin/python
#encoding: utf-8
 
# file: app.py
 
import os
import eventlet
from eventlet import wsgi, listen
from paste import deploy
 
cfg_file = 'app.ini'
 
 
class Blog(object):
    def __init__(self):
        pass
 
    # 工厂函数, ini 配置文件中指定的值会找到这个函数来创建该 app 的实例
    @classmethod
    def factory(cls, global_conf, **local_conf):
        return cls()
 
    # python 的对象调用机制, 简单的来讲就是 python 中对象分为可调用的和不可调用的
    # 有 __call__ 方法的可以调用, 这样 ini 中指定的配置项的值调用的时候就直接调用到
    # 这个函数了
    def __call__(self, environ, start_response):
        # start_response 把用户传递的 HTTP status 和 headers 记录然后返回
        start_response('200 OK', {("Content-type", "text/plain")})
        return 'welcome to my blog\n'
blog_app = Blog.factory
 
if __name__ == '__main__':
    socket = listen(('0.0.0.0', 8000))
    # paste 提供的入口函数
    app = deploy.loadapp('config:%s' % os.path.abspath(cfg_file), 'blog')
    server = eventlet.spawn(wsgi.server, socket, app)
    server.wait()

一个复杂的例子

下面是一个复杂的例子, 先来看他的 ini 文件:

[composite:wiki]
use = egg:Paste#urlmap
/: home
/v1: wikiv1
 
[filter-app:home]
paste.filter_factory = app:WikiFilter.factory
next = homeapp
 
[app:homeapp]
paste.app_factory = app:Wiki.factory
 
 
[pipeline:wikiv1]
pipeline = logip logmethod v1
 
[filter:logip]
paste.filter_factory = app:LogIPFilter.factory
 
[filter:logmethod]
paste.filter_factory = app:LogMethodFilter.factory
 
[app:v1]
paste.app_factory = app:V1.factory

app 名为 wiki, 首先它是一个 composite 的类型, 根据前面说的(egg.Paste 这个是一个 app), 它会根据 url 对应不同的应用, 比如如果是 http://localhost/ 它就到 home, http://localhost/v1, 就到 wikiv1

home 是只有一个 filter 过滤的 app, filter 对应的工厂函数为 Wiki.factory, 它过滤后 在调用 homeapp, 这个 homeapp 就和前面的 blog一样只是一个简单的 app

wikiv1 是一个 pipeline, 它经过 logip(记录对方 IP), logmethod(记录 HTTP medhod) 这两个 filter, 然后到 v1 的 app

相关代码如下:

class Wiki(object):
    def __init__(self):
        pass
 
    @classmethod
    def factory(cls, global_conf, **local_conf):
        return cls()
 
    def __call__(self, environ, start_response):
        start_response('200 OK', {("Content-type", "text/plain")})
        return 'welcome to my wiki\n'
 
 
class Middleware(object):
    def __init__(self, app):
        self.app = app
 
    @classmethod
    def factory(cls, global_conf, **kwargs):
        def filter(app):
            return cls(app)
        return filter
 
 
class WikiFilter(Middleware):
    def __init__(self, app):
        super(WikiFilter, self).__init__(app)
 
    def __call__(self, environ, start_response):
        req = Request(environ)
        if req.method == 'PUT':
            start_response('200 OK', {("Content-type", "text/plain")})
            return 'Bad request\n'
        else:
            return self.app(environ, start_response)
 
 
class LogIPFilter(Middleware):
    def __init__(self, app):
        super(LogIPFilter, self).__init__(app)
 
    def __call__(self, environ, start_response):
        print 'request IP is: %s' % environ['REMOTE_ADDR']
        return self.app(environ, start_response)
 
 
class LogMethodFilter(Middleware):
    def __init__(self, app):
        super(LogMethodFilter, self).__init__(app)
 
    def __call__(self, environ, start_response):
        print 'request method is: %s' % environ['REQUEST_METHOD']
        return self.app(environ, start_response)
 
 
class V1(object):
    @classmethod
    def factory(cls, global_conf, **local_conf):
        return cls()
 
    def __call__(self, environ, start_response):
        start_response('200 OK', {("Content-type", "text/plain")})
        return 'welcome to my V1 wiki\n'

Resources

完整的代码点击 这里, 配置文件请点击 这里

分类: programming, python 标签: ,

python Route 简单使用笔记

2014年10月15日 没有评论

Routes is a Python re-implementation of the Rails routes system for mapping URLs to application actions, and conversely to generate URLs. Routes makes it easy to create pretty and concise URLs that are RESTful with little effort.

Routes 其实就是 Python 版本的 Rails 的 routes. 它用来将用户的不同 URLs 自动匹配 到不同的应用上, 对于开发 RESTful 的 API 和其他 web 的应用非常方便.

例如下面根据官网上的例子修改的, 简单明了:

>>> from routes import Mapper
>>> map = Mapper()
>>> map.connect(None, "/error/{action}/{id}", controller="error")
>>> map.connect("home", "/", controller="main", action="index")
>>> print map
Route name Methods Path                
                   /error/{action}/{id}
home               /                   
>>> print map.match('/error/myapp/4')
{'action': u'myapp', 'controller': u'error', 'id': u'4'}
>>> print map.match('/')
{'action': u'index', 'controller': u'main'}

简单来讲, routes 的使用有以下简单的几步:

  1. 创建一个用来响应用户请求的控制器 C
  2. 创建一个 Mapper m
  3. 用 m.connect(或者 resource) 连接需要解析的 URLs 到 Controller 上
  4. 使用 routes.middleware.RoutesMiddleware 自动化 URLs 到 Controller 的处理

下面是一个例子

import webob.dec
import eventlet
from eventlet import wsgi, listen
from routes import Mapper, middleware
 
 
# 控制器
# 只有两个动作: index 和 add
class controller(object):
    def index(self):
        return "do index()"
 
    def add(self):
        return "do show()"
 
 
# WSGI App, 详情请参考我前面的文章 python paste.deploy 探索
class App(object):
    def __init__(self):
        # 上面提到的 1, 2, 3, 4
        self.controller = controller()
        m = Mapper()
        m.connect('blog', '/blog/{action}/{id}', controller=controller,
                  conditions={'method': ['GET']})
        self.router = middleware.RoutesMiddleware(self.dispatch, m)
 
    @webob.dec.wsgify
    def dispatch(self, req):
        # RoutesMiddleware 会根据接收到的 url, 自动调用 map.match(), 做路由匹配,
        # 然后调用第一个参数, 这里即是 self.dispatch()
        match = req.environ['wsgiorg.routing_args'][1]
        if not match:
            return 'error url: %s' % req.environ['PATH_INFO']
 
        # 根据用户的请求动作, 调用相应的 action 处理函数(index/add)
        action = match['action']
        if hasattr(self.controller, action):
            func = getattr(self.controller, action)
            ret = func()
            return ret
        else:
            return "has no action:%s" % action
 
    @webob.dec.wsgify
    def __call__(self, req):
        return self.router
 
if __name__ == '__main__':
    socket = listen(('0.0.0.0', 8000))
 
    server = eventlet.spawn(wsgi.server, socket, App())
    server.wait()

Table of Contents

其它

关于使用 Mapper.resource() 来批量创建 RESTful API, 这里不介绍了, 详情请到 官网 查看

分类: programming, python 标签: ,

下载 mp3 的脚本

2011年5月24日 2 条评论

一直都是用虾米听的音乐, 但是有时候听到比较好听的歌, 想要下载下来保存在电脑上或者手机里, 就比较麻烦. 我一般都是记在一个文档里面, 然后集中起来到公司的xp上用kugoo下载(鄙视我吧,). 以前曾考也虑过用网上别人实现的baidump3下载, 但是找到了几个, 没有一个能用的. 还有一个google music倒是可以用, 虽说google出品, 歌曲质量比较高, 但就是google的歌太少了.

想来想去, 正好这段时间在学习python, 正好顺手写了一个解析baidu url的app, 前端的ui hack 了 ubuntu中文论坛上的实现, 代码使用 quick and dirty 的方式一气呵成, 至少我的需求是满足了. 需要进一步完善的可以自己 hack. ^_^

附件: baidump3.zip

分类: python, 我的程序 标签: ,