我正在使用gevent来处理基于Django的Web系统上的API I / O.
我用猴子修补了:
import gevent.monkey; gevent.monkey.patch_socket()
我使用以下方法修补了psychopg:
import psycogreen; psycogreen.gevent.patch_psycopg()
尽管如此,某些Django调用因此Model.save()失败并出现错误:“异步连接失败”。我是否需要做其他事情才能在Django环境中制作postgres greenlet-safe?还有其他我想念的东西吗?
答案 0 :(得分:5)
这个问题上有一个article,不幸的是它是用俄语写的。让我引用最后一部分:
所有连接都存储在django.db.connections中 django.db.utils.ConnectionHandler的实例。每次ORM 即将发出查询,它通过调用请求数据库连接 连接[ '缺省'] 。反过来, ConnectionHandler .__ getattr __ 检查是否存在连接 ConnectionHandler._connections,如果是,则创建一个新的 空。
使用后应关闭所有打开的连接。有一个信号 request_finished,由...运行 django.http.HttpResponseBase.close。 Django关闭数据库连接 在最后一刻,当没有人可以再使用它 - 而且它 似乎很合理。
然而,关于ConnectionHandler如何存储数据库有一些棘手的部分 连接。它使用threading.local,成为 monkeypatching后gevent.local.local。宣布一次,这个 结构就像它在每个greenlet中都是独一无二的一样。调节器 * some_view *在一个greenlet中开始工作,现在我们在* ConnectionHandler._connections *中有一个连接。然后我们创造了一些 更多的greenlets,并得到一个空的 * ConnectionHandlers._connections *,他们从池中获得了connectinos。新的greenlets完成后,他们的本地()的内容消失了, 并且数据库连接与它们一起消失而没有返回池中。在 有些时候,游泳池变空了
开发Django + gevent你应该始终牢记并关闭它 通过调用django.db.close_connection来建立数据库连接。它 也应该在异常中调用,你可以使用装饰器 那就像:
class autoclose(object):
def __init__(self, f=None):
self.f = f
def __call__(self, *args, **kwargs):
with self:
return self.f(*args, **kwargs)
def __enter__(self):
pass
def __exit__(self, exc_type, exc_info, tb):
from django.db import close_connection
close_connection()
return exc_type is None