API запущен, db убит, db запущен, peewee.InterfaceError соединение уже закрыто
Запустить 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())}
1 ответ
Обновить:
Я полагаю, что проблема заключается в том, как вы структурировали свой импорт и как 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