API启动,db kill,db启动,peewee.InterfaceError连接已经关闭

时间:2015-05-20 00:45:44

标签: python psycopg2 bottle peewee psycopg

启动app.py,然后终止数据库并点击/api/foo给我:

  

peewee.OperationalError:无法连接到服务器:拒绝连接

重新启动数据库可以让我点击/api/foo给我:

  

peewee.OperationalError:由于管理员而终止连接   命令\ nSSL连接意外关闭\ n

再次点击/api/foo会给我:

  

peewee.InterfaceError:连接已关闭

测试用例

test_case/__init__.py

#!/usr/bin/env python

from os import environ

from bottle import Bottle, request, response
from playhouse.db_url import connect

bottle_api = Bottle()
db = connect(environ['RDBMS_URI'])

from test_case.foo.models import Foo

db.connect()  # Not needed, but do want to throw errors ASAP
db.create_tables([Foo], safe=True)  # Create tables (if they don't exist)

from test_case.foo.routes import foo_api

bottle_api.merge(foo_api)

bottle_api.catchall = False


@bottle_api.hook('before_request')
def _connect_db():
    print 'Connecting to db'
    db.connect()


@bottle_api.hook('after_request')
def _close_db():
    print 'Closing db'
    if not db.is_closed():
        db.close()


def error_catcher(environment, start_response):
    try:
        return bottle_api.wsgi(environment, start_response)
    except Exception as e:
        environment['PATH_INFO'] = '/api/error'
        environment['api_error'] = e
        return bottle_api.wsgi(environment, start_response)


@bottle_api.route('/api/error')
def global_error():
    response.status = 500
    return {'error': (lambda res: res[res.find("'") + 1:res.rfind("'")])(
                      str(request.environ['api_error'].__class__)),
            'error_message': request.environ['api_error'].message}

test_case/__main__.py

from __init__ import bottle_api
# Or `from __init__ import bottle_api`; `from bottle import run`;
# Then `run(error_catcher, port=5555)`

bottle_api.run(port=5555)

test_case/foo/__init__.py

test_case/foo/models.py

from peewee import Model, CharField

from test_case import db

class Foo(Model):
    id = CharField(primary_key=True)

    class Meta(object):
        database = db

test_case/foo/routes.py

from bottle import Bottle
from playhouse.shortcuts import model_to_dict

from test_case.foo.models import Foo

foo_api = Bottle()


@foo_api.get('/api/foo')
def retrieve_foos():
    return {'foos': tuple(model_to_dict(foo) for foo in Foo.select())}

Github gist for easy cloning.

1 个答案:

答案 0 :(得分:0)

更新

我认为问题在于如何构建导入以及python如何在sys.path中加载和缓存模块。

我认为你的一个模块正在导入和加载两次,代码库的不同部分使用不同的模块实例。

因此,foo.routes中的视图正在使用数据库对象的一个​​实例,而连接挂钩正在使用另一个实例。

而不是from __init__,尝试from test_case import bottle_api怎么样?这是一个重要的导入声明,可能是我的罪魁祸首。

我在代码中添加了以下内容,以便我可以从命令行运行它:

if __name__ == '__main__':
    api.run()

然后我向/api/foo提出了请求并查看了一些虚假数据。我停止了Postgresql服务器并得到了这个错误:

Traceback (most recent call last):
  File "/usr/lib64/python2.7/wsgiref/handlers.py", line 85, in run
    self.result = application(self.environ, self.start_response)
  File "/home/charles/tmp/scrap/bottlez/lib/python2.7/site-packages/bottle.py", line 979, in __call__
    return self.wsgi(environ, start_response)
  File "/home/charles/tmp/scrap/bottlez/lib/python2.7/site-packages/bottle.py", line 954, in wsgi
    out = self._cast(self._handle(environ))
  File "/home/charles/tmp/scrap/bottlez/lib/python2.7/site-packages/bottle.py", line 857, in _handle
    self.trigger_hook('before_request')
  File "/home/charles/tmp/scrap/bottlez/lib/python2.7/site-packages/bottle.py", line 640, in trigger_hook
    return [hook(*args, **kwargs) for hook in self._hooks[__name][:]]
  File "bt.py", line 31, in _connect_db
    db.connect()
  File "/home/charles/tmp/scrap/bottlez/src/peewee/peewee.py", line 2967, in connect
    self.initialize_connection(self.__local.conn)
  File "/home/charles/tmp/scrap/bottlez/src/peewee/peewee.py", line 2885, in __exit__
    reraise(new_type, new_type(*exc_value.args), traceback)
  File "/home/charles/tmp/scrap/bottlez/src/peewee/peewee.py", line 2965, in connect
    **self.connect_kwargs)
  File "/home/charles/tmp/scrap/bottlez/src/peewee/peewee.py", line 3279, in _connect
    conn = psycopg2.connect(database=database, **kwargs)
  File "/home/charles/tmp/scrap/bottlez/lib/python2.7/site-packages/psycopg2/__init__.py", line 164, in connect
    conn = _connect(dsn, connection_factory=connection_factory, async=async)
OperationalError: could not connect to server: Connection refused
    Is the server running on host "localhost" (::1) and accepting
    TCP/IP connections on port 5432?
could not connect to server: Connection refused
    Is the server running on host "localhost" (127.0.0.1) and accepting
    TCP/IP connections on port 5432?

当我重新启动服务器并发出后续请求时,我的测试数据得到了正常响应。

所以,简而言之,我不确定我可能会遗漏什么,但代码似乎对我有用。

Postgresql 9.4,psycopg2 2.6,python 2.7.9,peewee 2.6.0