解决peewee的异步非阻塞和多进程问题

前言: 

      熟悉我的朋友大多是知道我喜欢python的peewee orm,因为他的源码简单,api使用简单,可扩展性强。可能这事都传出去,所以这段时间连续有两个老铁问我peewee的问题。我想这两个问题还有些代表性,所以干脆简单总结下发个文章。


该文章后续仍在不断更新中, 请移步到原文地址 http://xiaorui.cc/?p=5023


python peewee是否支持异步库?

       peewee是否支持异步非阻塞 ?  2.7的话,peewee 是可以跟pymysql gevent配合一起用的,  tornado peewee就傻了,各种手段用下来,照样阻塞,话说sqlalchemy也没啥解决方法.  如果你是py 3.5 +,那么可以使用peewee async方案,这样选择的余地就多了, 不管是asyncio、tornado都可以兼容。


python peewee 是否支持多进程 (multiprocessing)

     peewee是否支持多进程 ? 我只能说,官方默认是不支持多进程的,多进程需要自己做lazy load懒惰加载。  为什么peewee多进程呢?  这个跟他的实现有直接的关系,像redis-py他抽象了线程和进程的连接池,根据不同的进程pid取不同的池子,就算你是 copy on write子进程,但是会共用redis-py的对象,但因为父子进程pid不同,所以redis-py帮你做了规避。 再问一嘴,peewee为啥就不支持多进程,作者来了句,不建议在多进程下使用peewee,然后就没有然后了. 

     首先我们要清楚为什么多进程下使用同一个连接对象是有问题的,多一个socket被多个进程去读写send/read buffer,数据会写串,网络两端都是有应用层协议的,你都写串了,还怎么识别包…反之,同理。

     不管是peewee还是其他的连接池库,我们都可以利用多实例的方法让连接池支持多进程。 实现的要点就两点,第一点多实例区分进程pid,  第二点,惰性加载….   不多说,直接扔代码.  这种实现不管是uwsgi,gunicorn,multiprocessing 都是支持的,原理代码已经说清楚了。

# xiaorui.cc

import os

import redis
from peewee import *
from playhouse.shortcuts import RetryOperationalError

from conf.config import mysql_addr, redis_conf


def singleton(cls, *args, **kw):
    instances = {}

    def _singleton():
        key = str(cls) + str(os.getpid())
        if key not in instances:
            instances[key] = cls(*args, **kw)
        return instances[key]

    return _singleton


class MyRetryDB(RetryOperationalError, MySQLDatabase):
    pass


@singleton
class DB(object):
    def __init__(self):
        self.mysql_db = MyRetryDB(host=mysql_addr['host'],
                                  port=mysql_addr['port'],
                                  user=mysql_addr['user'],
                                  passwd=mysql_addr['passwd'],
                                  database=mysql_addr['db'],
                                  charset='utf8mb4',
                                  threadlocals=True)
        self.redis_queue = redis.Redis(host=redis_conf['host'], port=redis_conf['port'], db=redis_conf['db'])

总结,python3 到现在为止还没出一个绝逼好用且支持异步的orm…  gevent + peewee + pymysql 算是无限接近了,可惜python3的时代,再用这组合就显得不伦不类了。


END.


大家觉得文章对你有些作用! 如果想赏钱,可以用微信扫描下面的二维码,感谢!
另外再次标注博客原地址  xiaorui.cc