gpt4 book ai didi

python - 使用 Nginx 和 uWsgi 的 Cherrypy 项目中的 SQLAlchemy 出现 UnboundExecutionError

转载 作者:行者123 更新时间:2023-12-01 05:43:25 26 4
gpt4 key购买 nike

我目前在我的 Cherrypy 项目中使用 SQLAlchemy 作为 ORM。当我在cherrypy嵌入式网络服务器上时,不会发生我遇到的错误,但仅来 self 的Nginx部署。

在带有 Nginx 1.2.1 的 Debian Wheezy 上,但这并不重要,因为我已经在带有 Nginx 1.2.8 和 1.4 的 Sqeeze 上进行了测试 - 相同的结果!

因此,我使用 Nginx 和 uWsgi 部署我的项目。我的 wsgi_handler.py 与我的 devserver 启动脚本没有什么不同,但无论如何我在开发模式下没有错误。

项目结构:

testproj:
- models.py
- root.py
- tools.py //this is a cherrypy tool that I found to bind sqlalchemy session to cherrypy requests
- devserver.py

//the production mode files
- wsgi_handler.py
- uwsgi.ini

以下是满足我的应用程序要求的 Web 项目的最小配置:

模型.py:

# -*- coding: utf-8 -*-
import logging
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column
from sqlalchemy.types import String, Integer

logging.basicConfig()
logging.getLogger('sqlalchemy.engine').setLevel(logging.CRITICAL)

Base = declarative_base()


class User(Base):
__tablename__ = 'user'
id = Column(Integer, primary_key=True)
firstname = Column(String)
lastname = Column(String)

def __init__(self, firstname, lastname):
self.firstname = firstname
self.lastname = lastname

工具.py:

# -*- coding: utf-8 -*-
import os
import cherrypy

from sqlalchemy import create_engine
from sqlalchemy.orm import scoped_session, sessionmaker

from models import *


class SAEnginePlugin(cherrypy.process.plugins.SimplePlugin):
def __init__(self, bus, dburi):
"""
The plugin is registered to the CherryPy engine and therefore
is part of the bus (the engine *is* a bus) registery.

We use this plugin to create the SA engine. At the same time,
when the plugin starts we create the tables into the database
using the mapped class of the global metadata.

Finally we create a new 'bind' channel that the SA tool
will use to map a session to the SA engine at request time.
"""
cherrypy.process.plugins.SimplePlugin.__init__(self, bus)
self.sa_engine = None
self.bus.subscribe("bind", self.bind)
self.dburi = dburi

def start(self):
db_path = os.path.abspath(os.path.join(os.curdir, self.dburi))
self.sa_engine = create_engine('sqlite:///%s' % db_path, echo=True)
Base.metadata.create_all(self.sa_engine)

def stop(self):
if self.sa_engine:
self.sa_engine.dispose()
self.sa_engine = None

def bind(self, session):
session.configure(bind=self.sa_engine)


class SATool(cherrypy.Tool):
def __init__(self):
"""
The SA tool is responsible for associating a SA session
to the SA engine and attaching it to the current request.
Since we are running in a multithreaded application,
we use the scoped_session that will create a session
on a per thread basis so that you don't worry about
concurrency on the session object itself.

This tools binds a session to the engine each time
a requests starts and commits/rollbacks whenever
the request terminates.
"""
cherrypy.Tool.__init__(self, 'on_start_resource', self.bind_session, priority=20)

self.session = scoped_session(sessionmaker(autoflush=True, autocommit=False))

def _setup(self):
cherrypy.Tool._setup(self)
cherrypy.request.hooks.attach('on_end_resource', self.commit_transaction, priority=80)

def bind_session(self):
cherrypy.engine.publish('bind', self.session)
cherrypy.request.db = self.session

def commit_transaction(self):
cherrypy.request.db = None
try:
self.session.commit()
except:
self.session.rollback()
raise
finally:
self.session.remove()

root.py:

# -*- coding: utf-8 -*-
import cherrypy
from models import User

class Root(object):
def index(self):
"""
List users from the DB & add new if no users
"""
user = cherrypy.request.db.query(User).filter_by(firstname='John').first()
if user is None:
user = User('John', 'Doe')
cherrypy.request.db.add(user)
return 'Created user: %s %s' % (user.firstname, user.lastname)
return 'Found user: %s %s' % (user.firstname, user.lastname)
index.exposed = True

这是有趣的部分,我的 devserver.py 与我的 wsgi_handler.py 没有太大区别

devserver.py:

# -*- coding: utf-8 -*-
import os, cherrypy
from tools import SAEnginePlugin, SATool
from root import Root

basedir = os.path.abspath(os.path.dirname(__file__))

config = {
'DEFAULT': {
basedir : basedir,
},

'global': {
'server.socket_port' : 8000,
'server.socket_host' : "127.0.0.1",

'tools.encode.on' : True,
'tools.encode.encoding' : 'utf-8',

'request.show_tracebacks' : True,
},

'/': {
'tools.db.on' : True,
},
}


if __name__ == "__main__":
SAEnginePlugin(cherrypy.engine, '/tmp/data.db3').subscribe()

cherrypy.tools.db = SATool()

cherrypy.quickstart(Root(), config=config)

wsgi_handler.py:

# -*- coding: utf-8 -*-
import os, cherrypy
from tools import SAEnginePlugin, SATool
from root import Root

basedir = os.path.abspath(os.path.dirname(__file__))

config = {
'DEFAULT': {
basedir : basedir,
},

'global': {
'server.socket_port' : 80,
'server.socket_host' : "127.0.0.1",

'tools.encode.on' : True,
'tools.encode.encoding' : 'utf-8',

'request.show_tracebacks' : True,
},

'/': {
'tools.db.on' : True,
},
}


def application(environ, start_response):
SAEnginePlugin(cherrypy.engine, '/tmp/data.db3').subscribe()

cherrypy.tools.db = SATool()

cherrypy.tree.mount(Root(), script_name='/', config=config)
return cherrypy.tree(environ, start_response)

uwsgi.ini:

[uwsgi]
thread=3
master=1
uid = www-data
gid = www-data
wsgi-file = /var/www/testproj/wsgi_handler.py
chdir = /var/www/testproj
socket = /tmp/uwsgi.sock
logto = /var/log/uwsgi.log

安装应用程序堆栈

sudo apt-get install python-dev python-setuptools nginx
sudo easy_install pip
sudo pip install CherryPy==3.2.2 SQLAlchemy==0.7.10 uWSGI==1.9.11

启动开发服务器

python devserver.py

localhost:8000 gives me the first & the last name of the registered user in my database. If it does not exist, I create it & display it.

使用 python uWsgi 在 Nginx 上部署项目:

sudo mkdir -p /var/www
sudo cp -r testproj /var/www/
sudo chown -R www-data:www-data /var/www/testproj

创建nginx配置文件:

/etc/nginx/sites-available/default:

server {
server_name 127.0.0.1;

listen 80;

charset UTF-8;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;

location / {
uwsgi_pass unix:///tmp/uwsgi.sock;
include uwsgi_params;
}
}

重新启动 Nginx 并启动 uwsgi 守护进程:

sudo service nginx restart
uwsgi --enable-threads --ini /var/www/testproj/uwsgi.ini

这就是区别。

On localhost:8000 I get the expected output:

Found user: John Doe

然后

127.0.0.1/

我得到:

UnboundExecutionError:无法找到在映射器Mapper|User|用户、SQL 表达式或此 session 上配置的绑定(bind)

我不明白为什么在开发模式下 session 会按其应有的范围进行限制!

最佳答案

您的 SAEnginePlugin.subscribe() 永远不会触发 start() 方法,因为没有启动cherrypy引擎。

wsgi_handler.py 的结尾应如下所示:

SAEnginePlugin(cherrypy.engine, '/tmp/data.db3').subscribe()
cherrypy.tools.db = SATool()
cherrypy.tree.mount(Root(), script_name='/', config=config)

cherrypy.engine.start()

application = cherrypy.tree

关于python - 使用 Nginx 和 uWsgi 的 Cherrypy 项目中的 SQLAlchemy 出现 UnboundExecutionError,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16876667/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com