【问题标题】:How do I use Neo4j-embedded for Python (threads) in Flask microframework?如何在 Flask 微框架中使用 Neo4j 嵌入的 Python(线程)?
【发布时间】:2011-11-03 17:47:12
【问题描述】:

我正在关注 Flask 教程 (Flaskr),以便尝试使用 Neo4j 嵌入的 Python。这是在虚拟环境中。这是我的“主要”应用代码:

import os
import jpype
from neo4j import GraphDatabase
from flask import Flask, request, session, g, redirect, url_for, abort, render_template, flash

app = Flask(__name__)
app.config.from_pyfile(os.environ['APP_SETTINGS'])


def connectDB(): 
    return GraphDatabase(app.config['DATABASE'])


def initDB():
    db = connectDB()

    with db.transaction:
        users = db.node()
        roles = db.node()

        db.reference_node.USERS(users)
        db.reference_node.ROLES(roles)

        userIndex = db.node.indexes.create('users')

        user = db.node(name=app.config['ADMIN'])
        user.INSTANCE_OF(users)
        userIndex['name'][app.config['ADMIN']] = user

        role = db.node(type='superadmin')
        role.INSTANCE_OF(roles)

        role.ASSIGN_TO(user)

    db.shutdown()

    print "Database initialized."


def testDB():
    db = connectDB()

    with db.transaction:
        userIndex = db.node.indexes.get('users')
        user = userIndex['name'][app.config['ADMIN']].single
        username = user['name']

    db.shutdown()

    print "Admin username is '%s'. Database exists." % username


@app.before_request
def before_request():
    jpype.attachThreadToJVM()
    g.db = connectDB()


@app.teardown_request
def teardown_request(exception):
    g.db.shutdown()


@app.route('/')
def index():

    with g.db.transaction:
        userIndex = g.db.node.indexes.get('users')
        user = userIndex['name'][app.config['ADMIN']].single
        username = user['name']

    fields = dict(username=username)
    return render_template('index.html', fields=fields)


if os.path.exists(app.config['DATABASE']) == False:
    initDB()
else:
    testDB()

initDB() 和 testDB() 工作得非常好——没有 Gremlin、PyLucene 等——只有 jpype 和 neo4j 嵌入。最初,当我请求 index() 时,JVM 会失败并且应用程序会终止。我搜索了网络以了解我需要将“jpype.attachThreadToJVM()”行添加到 before_request() 中,以通过 python 线程化 JVM 来解决该问题,并且应用程序不会终止。然而,这立即导致另一个问题:

Traceback (most recent call last):
  File "/ht/dev/envFlask/lib/python2.7/site-packages/flask/app.py", line 1518, in __call__
    return self.wsgi_app(environ, start_response)
  File "/ht/dev/envFlask/lib/python2.7/site-packages/flask/app.py", line 1506, in wsgi_app
    response = self.make_response(self.handle_exception(e))
  File "/ht/dev/envFlask/lib/python2.7/site-packages/flask/app.py", line 1504, in wsgi_app
    response = self.full_dispatch_request()
  File "/ht/dev/envFlask/lib/python2.7/site-packages/flask/app.py", line 1264, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "/ht/dev/envFlask/lib/python2.7/site-packages/flask/app.py", line 1262, in full_dispatch_request
    rv = self.dispatch_request()
  File "/ht/dev/envFlask/lib/python2.7/site-packages/flask/app.py", line 1248, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File "/ht/dev/apps/evobox/evobox/__init__.py", line 68, in index
    userIndex = g.db.node.indexes.get('users')
  File "/ht/dev/envFlask/lib/python2.7/site-packages/neo4j/index.py", line 36, in get
    return self._index.forNodes(name)
java.lang.RuntimeExceptionPyRaisable: java.lang.IllegalArgumentException: No index provider 'lucene' found. Maybe the intended provider (or one more of its dependencies) aren't on the classpath or it failed to load.

整个最后一行的谷歌搜索没有去任何地方。只是搜索“java.lang.IllegalArgumentException:找不到索引提供程序'lucene'。”在 python 的上下文中不会导致任何结果。

neo4j messages.log 似乎显示数据库已打开 3 次(initDB()、testDB() 和 index())。每个实例的类路径都相同:

Class Path: /ht/dev/envFlask/local/lib/python2.7/site-packages/neo4j/javalib/neo4j-jmx-1.5.M02.jar:/ht/dev/envFlask/local/lib/python2.7/site-packages/neo4j/javalib/neo4j-lucene-index-1.5.M02.jar:/ht/dev/envFlask/local/lib/python2.7/site-packages/neo4j/javalib/neo4j-graph-matching-1.5.M02.jar:/ht/dev/envFlask/local/lib/python2.7/site-packages/neo4j/javalib/neo4j-1.5.M02.jar:/ht/dev/envFlask/local/lib/python2.7/site-packages/neo4j/javalib/neo4j-kernel-1.5.M02.jar:/ht/dev/envFlask/local/lib/python2.7/site-packages/neo4j/javalib/geronimo-jta_1.1_spec-1.1.1.jar:/ht/dev/envFlask/local/lib/python2.7/site-packages/neo4j/javalib/lucene-core-3.1.0.jar:/ht/dev/envFlask/local/lib/python2.7/site-packages/neo4j/javalib/neo4j-graph-algo-1.5.M02.jar:/ht/dev/envFlask/local/lib/python2.7/site-packages/neo4j/javalib/neo4j-udc-1.5.M02.jar:/ht/dev/envFlask/local/lib/python2.7/site-packages/neo4j/javalib/neo4j-cypher-1.5.M02.jar:/ht/dev/envFlask/local/lib/python2.7/site-packages/neo4j/javalib/scala-library-2.9.0-1.jar

我还直接将 index() 修改为 connectDB 和 attachThreadToJVM,就像 initDB() 和 testDB() 一样,没有使用 'g' 全局 - 这导致完全相同的错误。

让 neo4j 嵌入和 jpype 处理线程请求,而不仅仅是在“主”应用程序中,我可能遗漏/忽略了什么?

注意:我知道使用 py2neo 或 Rexster/Bulbs 的 RESTful Web 服务解决方案,但我现在想避免这种情况。

编辑:使用 JPype-0.5.4.2、Neo4j-embedded-1.5.b2、Java-6-openjdk

【问题讨论】:

    标签: python flask neo4j


    【解决方案1】:

    这种模式的一个问题是,您可能会启动指向同一位置的多个数据库,这会导致问题。您需要的是遵循应用程序整个生命周期的单个数据库实例。

    为什么找不到 lucene 提供程序是一个更难的问题。索引提供程序是使用 java 服务加载器加载的,这意味着 JPype 不应该影响它。只要 JVM 启动正常,并且 lucene-index 实现 jar 在类路径上,它应该可以工作。

    它可能与线程有关,我目前正在编写一个修复程序来自动处理“attachThreadToJVM()”调用。我将添加一个测试用例,以确保从单独的线程读取索引也能按预期工作。

    线程工作目前在此邮件列表线程中保持更新:

    http://neo4j-community-discussions.438527.n3.nabble.com/Neo4j-Python-embedding-problems-with-shutdown-and-threads-td3476163.html

    【讨论】:

    • 感谢邮件列表线程的链接;我看到有更新。我也会尝试不同的模式。
    • 这就是模式!我根据 Flask 的教程(为 SQLite 编写)使用了该模式。在每次交易后执行 shutdown() 并重新连接新交易是问题所在。我现在只连接一次。我使用邮件列表中的响应中的脚本(atexit)来确保关闭正确。
    【解决方案2】:

    尝试使用标准 java 默认路径使用全新安装 neo4j、flask 和 jpipe 来复制错误。无法生成该日志。 但我得到了一个错误

    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "teststack.py", line 27, in initDB
        userIndex = db.node.indexes.create('users')
     File "/usr/local/lib/python2.7/dist-packages/neo4j/index.py", line 32, in create
       return self._index.forNodes(name, to_java(config))
     jpype._jexception.RuntimeExceptionPyRaisable: java.lang.IllegalArgumentException:      Supplied index configuration:
    {}
    doesn't match stored config in a valid way:
    {provider=lucene, type=exact}
    for 'users'
    

    当使用initDB

    固定
    userIndex = db.node.indexes.create(users)
    

    【讨论】:

    • 我创建了一个新的 venv,针对 java-6-openjdk 重建了 Jpype,并进行了全新安装,但仍然出现相同的错误。您能否详细说明“标准 java 默认路径”的含义?我已经设置了 JAVA_HOME=/usr/lib/jvm/java-6-openjdk。与此同时,我将看看旧版本的 JPype 是否会有所作为。
    猜你喜欢
    • 2013-01-13
    • 2011-09-05
    • 1970-01-01
    • 2014-03-15
    • 2020-04-16
    • 1970-01-01
    • 2011-03-10
    • 2014-08-02
    • 2016-07-13
    相关资源
    最近更新 更多