#6 Tornado 1,2,3

2013-10-13

Tornado web server 是使用 Python 编写出來的一个极轻量级、高可伸缩性和非阻塞 IO 的 Web 服务器软件,著名的 Friendfeed 网站就是使用它搭建的。

Tornado 跟其他主流的 Web 服务器框架(主要是 Python 框架)不同是采用 epoll 非阻塞 IO,响应快速,可处理数千并发连接,特别适用用于实时的 Web 服务。

要使用它,必须按照以下套件:

1)Python(建议使用 Python 2.5 / Python 2.6)
2)Simplejson(建议使用 simplejson 2.0.9)
3)cURL(建议使用 curl 7.19.7 或以上版本)
4)Pycurl(建议使用 pycurl 7.16.2.1)
5)Tornado Web Server(这才是主角,版本就照官網上最新的安裝吧)

一个最简单的服务:

import tornado.ioloop
import tornado.web

class MainHandler(tornado.web.RequestHandler):
    def get(self):
        self.write("Hello, world")

application = tornado.web.Application([
    (r"/", MainHandler),
])

if __name__ == "__main__":
    application.listen(8888)
    tornado.ioloop.IOLoop.instance().start()

在 Tornado 中运行 Django

#!/usr/bin/env python
# *-* encoding: utf-8 *-*

import os
import sys
import tornado.web
from tornado import autoreload
from tornado.wsgi import WSGIContainer
from tornado.httpserver import HTTPServer
from tornado.ioloop import IOLoop
from tornado.web import url
from django.conf import settings
from django.core.handlers.wsgi import WSGIHandler

if not os.path.dirname(__file__) in sys.path[:1]:
    sys.path.insert(0, os.path.dirname(__file__))

os.environ['DJANGO_SETTINGS_MODULE'] = 'settings'

class Application(tornado.web.Application):
    def __init__(self):
        handlers = [
            url(r"/static/(.+)", tornado.web.StaticFileHandler, dict(path=settings.MEDIA_ROOT), name='static_path'),
            url(r"/media/(.+)", tornado.web.StaticFileHandler, dict(path=settings.MEDIA_ROOT), name='media_path'),
        ]
        handlers.append(('.*', tornado.web.FallbackHandler, dict(fallback=WSGIContainer(WSGIHandler()))))

tornado.web.Application.__init__(self, handlers)
http_server = HTTPServer(Application())
http_server.listen(8080)
loop = IOLoop.instance()
autoreload.start(loop) #自动加载修改过的代码
loop.start()

#3 Python 可迭代对象

2013-04-30

可迭代对象(Iterable)就是可以用 for 循环遍历的数据结构,包括字符串、元组、列表、字典、集合等内置类型,也可以通过一些方法来是实现自定义可迭代对象。

https://docs.python.org/3/glossary.html#term-iterable
https://docs.python.org/3/glossary.html#term-iterator

迭代协议与序列协议

  • 迭代器协议(Iterator Protocol):如果一个对象包含 __next__ 方法,那就是一个迭代器。

迭代器可以使用 next 函数连续获取数据,内部实现就是调用 __next__ 方法获取一个数据项,如果循环结束,就会抛出 StopIteration

上面讲的是 CPython 实现,实际上 Python 语法规范要求迭代器一定要有 __iter__ 方法。
一般实现中,都有加上 __iter__ 方法,直接 return self

  • 可迭代对象协议(Iterable Protocol):如果一个对象包含 __iter__ 方法(返回一个迭代器对象),那么就是一个可迭代对象,

可以用在 for 循环,zipmapfilter 等需要可迭代对象的场景中。

  • 序列对象协议(Sequence Protocol):如果一个对象包含 __getitem__ 方法(使用 0 开始的整数作为索引),和 __len__ 方法,
    就可以执行一些序列对象的操作,比如...(?)。
    字符串,元组,列表都是序列对象。set 无序,dict 是按 key 索引,所以都不是序列对象。

  • 迭代器协议(Iterator Protocol):如果一个对象包含 __iter__ 方法,和 __next__ 方法,那就是一个迭代器。
    迭代器可以使用 next 函数连续获取数据,内部实现就是调用 __next__ 方法获取一个数据项,如果循环结束,就会抛出 StopIteration
    CPython 没有按照语言规范要求迭代器一定要有 __iter__ 方法。但一般实现中,都是加上 __iter__ 方法,return self

  • https://docs.python.org/3/c-api/abstract.html
  • Iterator Protocol https://docs.python.org/3/c-api/iter.html
  • Sequence Protocol https://docs.python.org/3/c-api/sequence.html

iter

iter(iterable)
iter(callable, sentinel) # sentinel:任意值都行

iter(1)
TypeError: 'int' object is not iterable
iter(1, 1)
TypeError: iter(v, w): v must be callable

iter 用于生成一个迭代器。

  • for 循环遍历的时候,会通过 iter 方法创建一个迭代器。
  • 可以创建迭代器的对象,必须支持 iterable protocol (包含 __iter__() 方法),
    或者支持 sequence protocol (包含 __getitem__() 方法,使用 0 开始的整数作为索引)

原理

迭代器(Iterator)

迭代器是可迭代对象的一种。它是一个具有 __iter__()__next__() 方法的对象,可以逐个返回可迭代对象的元素。
字符串、元组、列表、字典、集合这些内置类型就都不是迭代器。

PEP 234 – Iterators
https://peps.python.org/pep-0234/

自定义可迭代对象

class MyIterable:
    def __init__(self, data):
        self.data = data

    def __iter__(self):
        self.index = 0
        return self

    def __next__(self):
        if self.index < len(self.data):
            result = self.data[self.index]
            self.index += 1
            return result
        else:
            raise StopIteration

a = MyIterable(['apple', 'banana', 'cherry'])
for item in a:
    print(item)

#2 Python 随机模块

2013-04-17

示例

import string
import random

CHARS1 = string.ascii_letters
CHARS2 = string.ascii_letters + string.digits

def get_random_string(len=5, chars=None):
    if not chars:
        chars = CHARS1
    return ''.join(random.choice(chars) for _ in range(len))

# python3
def get_random_bytes(len=5):
    return bytes(bytearray((random.randrange(256) for _ in range(len))))

# python2
def get_random_bytes(len=5):
    return ''.join(chr(random.randrange(256)) for _ in range(len))

其他 随机字节的方法:

import Cryptodome.Random
Cryptodome.Random.get_random_bytes(size)

In [15]: os.getrandom
Out[15]: <function posix.getrandom(size, flags=0)>

In [17]: os.urandom
Out[17]: <function posix.urandom(size, /)>

#1 Python自学 07: set 类型

2013-04-03

声明

a = set() # ps: {} 表示空字典
b = set([1, 2, 3])
c = {1, 2, 3}

方法清单

  • .add(x) 添加元素
  • .clear() 清空集合
  • .copy() 复制集合

  • .difference() 返回两个集合的差集

  • .difference_update() 在主集合中只移除交集部分

  • .discard() 删除集合中的元素

  • .intersection() 返回两个集合的交集

  • .intersection_update() 在主集合中只保留交集部分

  • .isdisjoint() 判断两个集合是否没有公共元素

  • .issubset() 判断一个集合是否是另一个集合的子集
  • .issuperset() 判断一个集合是否是另一个集合的超集
  • .pop() 删除并返回一个随机元素
  • .remove() 删除集合中的元素

  • .symmetric_difference() 返回两个集合的对称差集,即排除所有重复元素之后的合集

  • .symmetric_difference_update() 在主集合中加入其他集合中的元素,然后移除交集部分

  • .union() 返回两个集合的并集

  • .update() 在一个集合中添加另一个集合中的元素