本文介绍了如何在Flask微框架中为Python(线程)使用Neo4j-embedded?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在关注Flask教程(Flaskr),以便尝试使用Python的Neo4j-embedded。这是一个虚拟世界。这里是我的'主'应用程序代码:

  import os 
从neo4j导入jpype
导入GraphDatabase
from flask import烧瓶,请求,会话,g,重定向,url_for,abort,render_template,flash
$ b app = Flask(__ name__)
app.config.from_pyfile(os.environ ['APP_SETTINGS'])


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

$ b $ ():
db = connectDB()

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

db.reference_node.USERS(users)
db.reference_node.ROLES(roles)
$ b $ 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(用户)

db.shutdown()

打印数据库已初始化。

$ b 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()

printAdmin username is'%s'。Database exists。 %username

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


@ app.teardown_request
def teardown_request(例外):
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']
$ b $ fields = dict(username = username )
返回render_template('index.html',fields = fields)

$ b $如果os.path.exists(app.config ['DATABASE'])== False:
initDB()
else:
testDB()

initDB ()和testDB()工作得很好 - 没有Gremlin,PyLucene等 - 只是jpype和neo4j嵌入。最初,JVM会失败,应用程序将终止,当我要求索引()。我搜遍了网络,了解到我需要将jpype.attachThreadToJVM()行添加到before_request()中,以解决使用python线程化JVM的问题,并且应用程序不会终止。但是,这会立即导致另一个问题:
$ b $ pre code $ Traceback最近一次调用最后一个
文件/ ht / dev / envFlask / lib / python2.7 / site-packages / flask / app.py,行1518,在__call__
返回self.wsgi_app(environ,start_response)
文件/ ht / dev / envFlask / lib / python2.7 / site-packages / flask / app.py,行1506,位于wsgi_app
response = self.make_response(self.handle_exception(e))
文件/ ht / dev / envFlask / lib / python2.7 / site-packages / flask / app.py,行1504,位于wsgi_app
response = self.full_dispatch_request()
文件/ ht / dev / envFlask / lib / python2.7 / site-packages / flask / app.py,第1264行,在full_dispatch_request
rv = self.handle_user_exception(e)
文件/ ht / dev / envFlask / lib / python2 .7 / site-packages / flask / app.py,第1262行,在full_dispatch_request
rv = self.dispatch_request()
文件/ht/dev/envFlask/lib/python2.7/site -packages / flask / app.py,第1248行,在dispatch_request
中返回self.view_f unify [rule.endpoint](** req.view_args)
在索引
userIndex = g.db中的文件/ht/dev/apps/evobox/evobox/__init__.py,第68行。 node.indexes.get('users')
文件/ht/dev/envFlask/lib/python2.7/site-packages/neo4j/index.py,第36行,获取
返回self._index.forNodes(name)
java.lang.RuntimeExceptionPyRaisable:java.lang.IllegalArgumentException:未找到索引提供程序lucene。也许预期的提供者(或者它的一个依赖关系)不在类路径上,或者加载失败。

整个最后一行的Google搜索没有任何地方。只搜索java.lang.IllegalArgumentException:找不到索引提供程序lucene。导致在python的上下文中没有任何东西。

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

 类路径:/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 /站点包/ 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 0.7 /站点包/ Neo4j的/ javalib / Lucene的核心-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 /站点包/ 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'global - 导致完全相同的错误。 b

我可能错过/忽略了neo4j-embedded和jpype在一个线程请求中工作,而不是在main应用程序中?



编辑:使用JPype-0.5 .4.2,Neo4j-embedded-1.5.b2,Java-6-openjdk
解决方案

启动多个数据库的风险指向相同的位置,这将导致问题。你会想要的是一个单一的数据库实例,跟随你的应用程序的整个生命周期。

为什么没有找到lucene提供者是一个更难的问题。索引提供者使用java服务加载器加载,这意味着JPype不应该影响它。只要JVM启动好了,lucene-index实现jar就在classpath中,它应该可以工作。

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



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


I'm following the Flask Tutorial (Flaskr) in order to experiment with using Neo4j-embedded for Python. This is in a virtualenv. Here is my 'main' app code:

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() and testDB() work perfectly fine - without Gremlin, PyLucene, etc. - just jpype and neo4j-embedded. Initially, the JVM would fail and the app would terminate when I would request index(). I scoured the net to learn that I needed to add the line "jpype.attachThreadToJVM()" into before_request() to solve that issue with python threading the JVM and the app does not terminate. However, this leads immediately to another issue:

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.

Google search of the entire last line didn't go anywhere. Just searching "java.lang.IllegalArgumentException: No index provider 'lucene' found." lead to nothing in the context of python.

The neo4j messages.log seems to show the database was opened 3 times (initDB(), testDB(), and index()). The classpath is the same for each instance:

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

I also modified index() to connectDB and attachThreadToJVM directly like initDB() and testDB() without using the 'g' global - this resulted in exact same error.

What am I possibly missing/overlooking to get neo4j-embedded and jpype working on a threaded request and not just in the 'main' app?

Note: I'm aware of the RESTful Web Service solutions with py2neo or Rexster/Bulbs, but I want avoid that for now.

EDIT: Using JPype-0.5.4.2, Neo4j-embedded-1.5.b2, Java-6-openjdk

解决方案

One issue with this pattern is that you run the risk of starting multiple databases pointed at the same location, which will lead to problems. What you would want is a single instance of the database that follows the full lifecycle of your application.

Why it's not finding the lucene provider is a harder question.. The index provider is loaded using java service loader, which means that JPype should not affect it. As long as the JVM start alright, and the lucene-index implementation jar is on the classpath, it should work.

It may be related to threading somehow, I'm currently writing a fix to automaitcally handle the "attachThreadToJVM()" calls. I'll add a test case to make sure reading indexes from a separate thread works as expected as well.

The threading work is currently kept updated in this mailing list thread:

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

这篇关于如何在Flask微框架中为Python(线程)使用Neo4j-embedded?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

11-03 11:33