0

启动 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 便于克隆。

4

1 回答 1

0

更新:

我相信问题在于您如何构建导入以及 python 在 sys.path 中加载和缓存模块的方式。

我认为您的模块之一被导入和加载两次,并且代码库的不同部分使用模块的不同实例。

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

而不是from __init__,尝试from test_case import bottle_api什么?这是一个让我觉得可能是罪魁祸首的 import 语句。


我将以下内容添加到您的代码中,以便可以从命令行运行它:

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

于 2015-05-20T01:18:35.653 回答