Why is the Neo4j Bolt Driver inconsistent between shell and IDE?

iam.Carrot Source

I see a strange behavior with the neo4j-bolt-driver. When I use Pycharm to run my code it works perfectly well and for a single query to neo4j I get the below response:

type: neo4j.node    # I pulled out the type of the element.
<Node id=3820 labels={'city'} properties={'ID': 'xddy', 'name': 'california'}>

Now when I package my code and create an .egg out of it, and then use the terminal to run the script for the same input to the same database I get the below response:

type: neo4j.node    # I pulled out the type of the element.
(_3820:city {ID: 'xddy', name: 'california'})

Now have a look at the difference in the responses, the type is the same just the keys to the object are missing.

And this leads to an AttributeError. Worse is I have to manually parse the data into a dict so that I can process it.


Side Effects:

try:
    props = node[admin].properties
    node_chain[list(node[admin].labels)[0]] = props
    address.append(props['name'])
except AttributeError:

    # try to convert (_3820:city {ID: 'xddy', name: 'california'})
    # to {'ID': 'xddy', 'name': 'california'}
    # and add it to an existing dict with the key `city`

    string_rep = str(node[admin])
    splitted = string_rep.split('{')
    label = splitted[0].split(':')[-1].strip()
    payload_string = "{ " + splitted[1][:-1]
    clean = payload_string.replace("'", " ").replace(":", "':'").replace(",", "','")\
        .replace("{", "{'").replace("}", "'}")
    temp_dict = ast.literal_eval(clean)
    payload_dict = {k.strip(): v.strip() for k, v in temp_dict.items()}
    address.append(payload_dict['name'])
    node_chain[label] = payload_dict

I am looking for two answers:

  • Is there an issue in the bolt driver or is it just my code when run from an egg
  • Is there a better way to parse the invalid content into a dict?
python-3.xneo4jneo4j-driver

Answers

answered 6 months ago Rebecca Nelson #1

You have a discrepancy in your execution environments.

Even though you are using the same virtual environment for both shell execution and the PyCharm project interpreter, when executing an .egg the execution environment may be modified to pull in fresh copies of all the libraries, which are not necessarily installed to the "global" module path ("global" here meaning either system-wide when not using a virtualenv, or in the python modules of the virtualenv).

Your PyCharm notes that it is using version 1.5.3 of the neo4j-driver module, but the version that pip pulled in to your .egg executation environment is 1.6.0a, the latest at the time of dependency resolution. And so, when executing it from the shell, you are using a different version of neo4j-driver.

That in and of itself wouldn't be so bad, but...

There are currently breaking changes between 1.5.3 and 1.6.0 of neo4j-driver.

1.6.0 changed the paths of some of the modules, so specific imports might break. It seems it also changed the format of some of its data objects, as you've seen in your example.

At first it would seem that this is just a consequence of using an unstable tag of the version, but it's very possible that these changes might be here to stay, as it is a new version.

To ensure the same version is installed by pip/setuptools, pin the version number.

1.6.0 drastically changed the API in some respects. Since you were developing against 1.5.3, you will have to either change your API to handle both versions (and possibly risk it breaking again when future updates are released), or pin it to a particular version.

To pin it, wipe out any existing versions of neo4j-driver by removing all binaries from your build dir, uninstall it with pip, then update your setup.py or other dependency management tool to point to the specific version you are developing with.

For setup.py, add ==1.5.3 to the end of the name of the library in the install_requires, tests_require or other relevant sections.

comments powered by Disqus