Py2neo is a client library and toolkit for working with Neo4j from within Python

Overview

Py2neo

PyPI version PyPI Downloads License Coverage Status

Py2neo is a client library and toolkit for working with Neo4j from within Python applications. The library supports both Bolt and HTTP and provides a high level API, an OGM, admin tools, a Cypher lexer for Pygments, and many other bells and whistles.

Command line tooling has been removed from the library in py2neo 2021.2. This functionality now exists in the separate ipy2neo project.

As of version 2021.1, py2neo contains full support for routing, as exposed by a Neo4j cluster. This can be enabled using a neo4j://... URI or by passing routing=True to a Graph constructor.

Installation & Compatibility

To install the latest release of py2neo, simply use:

$ pip install py2neo

The following versions of Python and Neo4j (all editions) are supported:

Neo4j Python 3.5+ Python 2.7
4.3 GitHub workflow status for tests against Neo4j 4.3 using py35+ GitHub workflow status for tests against Neo4j 4.3 using py27
4.2 GitHub workflow status for tests against Neo4j 4.2 using py35+ GitHub workflow status for tests against Neo4j 4.2 using py27
4.1 GitHub workflow status for tests against Neo4j 4.1 using py35+ GitHub workflow status for tests against Neo4j 4.1 using py27
4.0 GitHub workflow status for tests against Neo4j 4.0 using py35+ GitHub workflow status for tests against Neo4j 4.0 using py27
3.5 GitHub workflow status for tests against Neo4j 3.5 using py35+ GitHub workflow status for tests against Neo4j 3.5 using py27
3.4 GitHub workflow status for tests against Neo4j 3.4 using py35+ GitHub workflow status for tests against Neo4j 3.4 using py27

Note that py2neo is developed and tested under Linux using standard CPython distributions. While other operating systems and Python distributions may work, support for these is not available.

Quick Example

To run a query against a local database is straightforward:

>>> from py2neo import Graph
>>> graph = Graph("bolt://localhost:7687", auth=("neo4j", "password"))
>>> graph.run("UNWIND range(1, 3) AS n RETURN n, n * n as n_sq")
   n | n_sq
-----|------
   1 |    1
   2 |    4
   3 |    9

Releases & Versioning

As of 2020, py2neo has switched to Calendar Versioning, using a scheme of YYYY.N.M. Here, N is an incrementing zero-based number for each year, and M is a revision within that version (also zero-based).

No compatibility guarantees are given between versions, but as a general rule, a change in M should require little-to-no work within client applications, whereas a change in N may require some work. A change to the year is likely to require a more significant amount of work to upgrade.

Note that py2neo is developed on a rolling basis, so patches are not made to old versions. Users will instead need to install the latest release to adopt bug fixes.

More

For more information, read the handbook.

Comments
  • Known bug in WeakValueDictionary's setdefault() causes issues in Node,Rel and Relationship caches in multithreaded environments

    Known bug in WeakValueDictionary's setdefault() causes issues in Node,Rel and Relationship caches in multithreaded environments

    WeakValueDictionary.setdefault() and WeakValueDictionary.pop() will sometimes return None in multithreaded environments, as explained here http://bugs.python.org/issue19542. The patch is pending review.

    I've been able to reproduce the problem by running the test case x.py that's linked in the bug report using both python 2.7.9 and python 3.4.3.

    I have also encountered the problem during development of a Flask app that uses py2neo. This app is run on Apache using mod_wsgi-express (prefork, 1 process, 5 threads).

    Anyhow, since Node.cache, Rel.cache, and Relationship.cache all inherit from WeakValueDictionary and have methods that call setdefault(), I've been seeing NoneType errors in my Flask app.

    For instance, this snippet in Rel#hydrate() in core.py:

            if inst is None:
                new_inst = cls()
                new_inst.__stale.update({"properties"})
                inst = cls.cache.setdefault(self, new_inst)
    
            cls.cache[self] = inst
    

    Will intermittently produce:

        File "/Users/fallonchen/.virtualenvs/ul06/lib/python2.7/site-packages/py2neo/core.py", line 912, in match
        for result in results:
        File "/Users/fallonchen/.virtualenvs/ul06/lib/python2.7/site-packages/py2neo/cypher/core.py", line 453, in next
        return self.__next__()
        File "/Users/fallonchen/.virtualenvs/ul06/lib/python2.7/site-packages/py2neo/cypher/core.py", line 450, in __next__
        return next(self.__response_item)
        File "/Users/fallonchen/.virtualenvs/ul06/lib/python2.7/site-packages/py2neo/cypher/core.py", line 443, in __response_iterator
        yield producer.produce(self.graph.hydrate(assembled(record_data)))
        File "/Users/fallonchen/.virtualenvs/ul06/lib/python2.7/site-packages/py2neo/core.py", line 839, in hydrate
        return type(data)(map(self.hydrate, data))
        File "/Users/fallonchen/.virtualenvs/ul06/lib/python2.7/site-packages/py2neo/core.py", line 806, in hydrate
        return Relationship.hydrate(data)
        File "/Users/fallonchen/.virtualenvs/ul06/lib/python2.7/site-packages/py2neo/core.py", line 2421, in hydrate
        Rel.hydrate(data),
        File "/Users/fallonchen/.virtualenvs/ul06/lib/python2.7/site-packages/py2neo/core.py", line 1769, in hydrate
        cls.cache[self] = inst
        File "/usr/local/Cellar/python/2.7.8_1/Frameworks/Python.framework/Versions/2.7/lib/python2.7/weakref.py", line 103, in __setitem__
        self.data[key] = KeyedRef(value, self._remove, key)
        File "/usr/local/Cellar/python/2.7.8_1/Frameworks/Python.framework/Versions/2.7/lib/python2.7/weakref.py", line 267, in __new__
        self = ref.__new__(type, ob, callback)
        TypeError: cannot create weak reference to 'NoneType' object
    
    

    I've found that you can get around the problem by replacing setdefault() with:

            if self not in cls.cache:
                 cls.cache[self] = new_inst
             inst = cls.cache[self]
    

    Is this a good approach? I haven't looked too deeply into whether or not pop() is called, but I assume that it would also have to be patched.

    bug 
    opened by fallonchen 26
  • SyntaxError: The old parameter syntax `{param}` is no longer supported

    SyntaxError: The old parameter syntax `{param}` is no longer supported

    Using neo4j 4.0.0

    Using py2neo v4

    g.nodes.match(U, _id=3125349375).first()

    yields:

    ClientError: SyntaxError: The old parameter syntax `{param}` is no longer supported. 
    Please use `$param` instead (line 1, column 30 (offset: 29))
    "MATCH (_:USER) WHERE _._id = {1} RETURN _"
    
    opened by msramalho 18
  • Node object has no attribute __metadata__

    Node object has no attribute __metadata__

    @nigelsmall - Using version 1.6.4, neo4j 2.1.3 and python 3.3, when I try the following

    graph_db = neo4j.GraphDatabaseService("http://localhost:7474/db/data/")
    n = graph_db.node(100)
    n["username"]="Nigel"
    

    I get:

    AttributeError("'Node' object has no attribute 'metadata'",)

    could this be a bug with using a later version of Neo4j?

    opened by gmjordan 16
  • On development of this project

    On development of this project

    It's obvious that you are still working on this project @technige, but it's kind of disappointing that are not many responses to the open issues. Perhaps many of the issues can be closed as simple misunderstandings. For myself, I would like to contribute but I need some guidance. I also learn a lot about a project by responses and activity in issues. I think more activity in the issues could help reduce the bus factor and be an overall benefit to the project. This is just a suggestion, as I enjoy working with this project and want to see it continue to improve

    opened by wgwz 15
  • Individual status codes in http batch response

    Individual status codes in http batch response

    Hi Nigel,

    We have been porting neomodel to py2neo 1.6, we have come across one issue. The individual http response status codes seem to be no longer accessible in a batch response.

    I am aware this was never part of your public API, however it was used internally by neomodel to aid it safely simulating the create_or_fail index feature on neo4j versions where its not available (such as 1.8 used on heroku).

    Setting a key, value in an index returns 200 if it already existed and 201 if its new entry. As these codes are no longer available in py2neo / httpstream we can't capture and report this condition: https://github.com/robinedwards/neomodel/blob/master/neomodel/exception.py#L13

    Do you know if theres any way I can monkey patch / subclass the current batch system to return them?

    bug 
    opened by robinedwards 14
  • py2neo.wiring.WireError: Broken

    py2neo.wiring.WireError: Broken

    When i run the program in a timed task, this problem occurred. I use flask_apscheduler and py2neo, hoping to update the data in an hour. But this error will happen every once in a while. I don't know how this error is caused. Who knows can tell me what is going on. Thank you very much!

    undiagnosable third-party disconnections 
    opened by zhangyukuo 13
  • 1.6 performance vs 1.5

    1.6 performance vs 1.5

    I'm aware that 1.6 is not yet final but I have been testing it in order to use labels and the new schema indexes in a project I am working on. In this project batches of 20-1000 statements are sent and tests are taking approx. 14 times longer on 1.6 than on 1.5, even without assigning any labels (straight swap of the library with same app code). It seems as though there is a delay between streamed requests ending and starting. Is this something you are aware of, if so then cool, but I just wanted to point out my findings in case not.

    opened by millar 12
  • Getting 'OverflowError: mktime argument out of range' while importing the database module from latest version of py2neo

    Getting 'OverflowError: mktime argument out of range' while importing the database module from latest version of py2neo

    Hello All, Initially I was using a py2neo's version 2021.1.5 within my project and the database module was getting successfully imported in the code. But, when I have updated the py2neo version to the latest one i.e. 2021.2.0 and then I was trying to import the database module from the py2neo I was getting an OverFlow error mentioning 'OverflowError: mktime argument out of range'. May I know the reason for the same ? Why the database module was getting successfully imported with the older version of py2neo? Thank you in advance.

    bug no windows maintainer 
    opened by psomesh94 11
  • py2neo has a version conflict in the list of requirements

    py2neo has a version conflict in the list of requirements

    I had an issue while installing a package of mine (pyramid application), which depended on py2neo.

    Issue:

    in py2neo setup.py file we have: prompt_toolkit==1.0.15

    however, py2neo also depends on (found in setup.py): jupyter_console

    in jupyter_console setup.py file we have:

    prompt_toolkit>=2.0.0,<2.1.0

    This can lead to potential conflict, which will not be explicitly shown when you install py2neo. However, when you use something like pyramid, which utilizes pkg_resources, it can lead to: pkg_resources.ContextualVersionConflict

    opened by nikist97 11
  • OGM request: provide more control when saving/loading objects

    OGM request: provide more control when saving/loading objects

    The OGM would be more useful if some hook would be provided so that the user has more control on how objects are saved and loaded.

    Example use case: I'd like to save an object and have the object's class name as a label. Since the store.save will only store the object's attrs as node properties I have to resort to 1) save object 2) reload object 3) set object.node.labels. 4) save object again. Yuck.

    PS1 the store.save method seems to use a deprecated function set_properties. PS2 it seems that passing a newly created node (see use case above; I wanted to pass the label) as a kwarg in the store.save(obj, node=mynewnode) does not work. I get a 500 server error. Did not explore further.

    opened by mjmare 11
  • Upgrading to Neo4j 2.1.7 breaks the test suite

    Upgrading to Neo4j 2.1.7 breaks the test suite

    For some reason tests are broken with Neo4j 2.1.7, even though they are passing with Neo4j 2.1.6 and 2.2.0-M03.

    Looks related to Cypher transactions not returning expected uris, but I don't see any reasons for this in Neo4j release notes.

    If I can help with this, please give me some hint.

    opened by jlirochon 11
  • TypeError: Cypher literal values of type interchange.geo.WGS84Point are not supported

    TypeError: Cypher literal values of type interchange.geo.WGS84Point are not supported

    py2neo version: 2021.2.3 python version: 3.9.15

    I created a database with nodes that include coordinates and am able to retrieve them using the basic GUI with this query:

    match (n) return n limit 1; Screenshot from 2023-01-03 09-17-02

    However, when I attempt the same thing using py2neo like this:

    graph.run("match (n) return n limit 1;")

    I get the following error:

    TypeError: Cypher literal values of type interchange.geo.WGS84Point are not supported.

    Are there plans to include WGS84Point support? If not, is there perhaps a work-around?

    opened by suciokhan 0
  • RuntimeError: Can't begin a new transaction

    RuntimeError: Can't begin a new transaction

    Traceback (most recent call last): File "/Users/KGQA_Version.Amme/QASystemOnMedicalKG-AmmeRevision/build_medicalgraph.py", line 346, in handler.create_graphnodes(); File "/Users/KGQA_Version.Amme/QASystemOnMedicalKG-AmmeRevision/build_medicalgraph.py", line 250, in create_graphnodes self.create_diseases_nodes(disease_infos) File "/Users/KGQA_Version.Amme/QASystemOnMedicalKG-AmmeRevision/build_medicalgraph.py", line 237, in create_diseases_nodes self.g.create(node) File "/Users/anaconda3/envs/torch107/lib/python3.7/site-packages/py2neo/database.py", line 362, in create with self.begin() as tx: File "/Users/anaconda3/envs/torch107/lib/python3.7/site-packages/py2neo/database.py", line 353, in begin return Transaction(self, autocommit) File "/Users/anaconda3/envs/torch107/lib/python3.7/site-packages/py2neo/database.py", line 781, in init self.transaction = self.connector.begin() File "/Users/anaconda3/envs/torch107/lib/python3.7/site-packages/py2neo/internal/connectors.py", line 398, in begin raise RuntimeError("Can't begin a new transaction") RuntimeError: Can't begin a new transaction

    Process finished with exit code 1

    how can I solve it ? thank you!

    opened by wbcai-wmh 0
  • Compatibility with neo4j version 5

    Compatibility with neo4j version 5

    Hi everyone, We are working with the new version of neo4j (version 5). Are you working in the adaptation of py2neo package for this new version?? Thanks

    opened by bioinformaticaInta 0
  • Failed to read message exception

    Failed to read message exception

    I use the latest py2neo version and in the server logs I can see this error message keeps appearing (not always). It affects the users of the application sometimes. Failed to read message

    I tried to debug the issue. I am using bolt connection inside an azure app service. This happens when the graph.run(query).data() is executed and after few minutes (usually 3 - 4 minutes) this throws the'Failed to read message' exception. It seems this is thrown inside the Wire read. Screenshot 2022-12-10 at 14 30 18 I have seen a similar issue reported here #844 Any solution or workaround is highly appreciated.

    opened by ErangaD 2
  • `Subgraph.__db_create__` doesn't create multiple relationships between the same nodes

    `Subgraph.__db_create__` doesn't create multiple relationships between the same nodes

    Issue

    Description

    from py2neo import Graph, Node
    graph = Graph(NEO4J_URI, user=NEO4J_USER, password=NEO4J_PASSWORD)
    node_a = Node("Node", name="A")
    node_b = Node("Node", name="B")
    
    graph_tx = graph.begin()
    for node in (node_a, node_b):
        graph_tx.create(node)
    graph.commit(graph_tx)
    
    relationship_1 = Relationship(node_a, "REL", node_b, id_overwritten=6)
    relationship_2 = Relationship(node_a, "REL", node_b, id_overwritten=7)
    
    graph_tx = graph.begin()
    for node in (node_a, node_b):
        graph_tx.create(node)
    graph.commit(graph_tx)
    
    graph_tx = graph.begin()
    for relationship in (relationship_1, relationship_2):
        graph_tx.create(relationship)
    graph.commit(graph_tx)
    

    Expected behavior

    Given that relationship_2 has a different id_overwritten, a new relationship should be created.

    (A) -[REL {"id_overwritten": 6}]-> (B)
    (A) -[REL {"id_overwritten": 7}]-> (B)
    

    Actual behavior

    relationship_1 is replaced with relationship_2

    (A) -[REL {"id_overwritten": 7}]-> (B)
    

    Cause

    This is due to the fact that Subgraph.__db_create__ has no option for CREATEing instead of MERGEing

    https://github.com/py2neo-org/py2neo/blob/2e46bbf4d622f53282e796ffc521fc4bc6d0b60d/py2neo/data.py#L209

    >>> print(pq[0])
    
    UNWIND $data AS r
    MATCH (a) WHERE id(a) = r[0]
    MATCH (b) WHERE id(b) = r[2]
    MERGE (a)-[_:REL]->(b)
    SET _ += r[1]
    

    Workaround

    ...
    pq = unwind_merge_relationships_query(data, r_type)
    
    import re
    
    # Pardon my regex
    pq = (
        re.sub(
            (
                r"(.*)?"
                r"(MERGE )(\(a\)-\[_:\w+\]->\(b\))"
                r"(.*)"
            ),
            (
                r"\g<1>"
                r"CREATE "
                r"\g<3>"
                r"\g<4>"
            ),
            pq[0],
        ),
        *pq[1:],
    )
    ...
    

    so that

    >>> print(pq[0])
    
    UNWIND $data AS r
    MATCH (a) WHERE id(a) = r[0]
    MATCH (b) WHERE id(b) = r[2]
    CREATE (a)-[_:REL]->(b)
    SET _ += r[1]
    
    opened by alfredo-f 0
  • fix(sec): upgrade pygments to 2.7.4

    fix(sec): upgrade pygments to 2.7.4

    What happened?

    There are 1 security vulnerabilities found in pygments 2.0.0

    What did I do?

    Upgrade pygments from 2.0.0 to 2.7.4 for vulnerability fix

    What did you expect to happen?

    Ideally, no insecure libs should be used.

    The specification of the pull request

    PR Specification from OSCS

    opened by 645775992 0
Releases(2021.2.3)
Owner
py2neo.org
At the intersection of Python and Neo4j
py2neo.org
Example Python codes that works with MySQL and Excel files (.xlsx)

Python x MySQL x Excel by Zinglecode Example Python codes that do the processes between MySQL database and Excel spreadsheet files. YouTube videos MyS

Potchara Puttawanchai 1 Feb 07, 2022
pandas-gbq is a package providing an interface to the Google BigQuery API from pandas

pandas-gbq pandas-gbq is a package providing an interface to the Google BigQuery API from pandas Installation Install latest release version via conda

Google APIs 348 Jan 03, 2023
SAP HANA Connector in pure Python

SAP HANA Database Client for Python Important Notice This public repository is read-only and no longer maintained. The active maintained alternative i

SAP Archive 299 Nov 20, 2022
a small, expressive orm -- supports postgresql, mysql and sqlite

peewee Peewee is a simple and small ORM. It has few (but expressive) concepts, making it easy to learn and intuitive to use. a small, expressive ORM p

Charles Leifer 9.7k Dec 30, 2022
Apache Libcloud is a Python library which hides differences between different cloud provider APIs and allows you to manage different cloud resources through a unified and easy to use API

Apache Libcloud - a unified interface for the cloud Apache Libcloud is a Python library which hides differences between different cloud provider APIs

The Apache Software Foundation 1.9k Dec 25, 2022
dbd is a database prototyping tool that enables data analysts and engineers to quickly load and transform data in SQL databases.

dbd: database prototyping tool dbd is a database prototyping tool that enables data analysts and engineers to quickly load and transform data in SQL d

Zdenek Svoboda 47 Dec 07, 2022
Redis Python Client - The Python interface to the Redis key-value store.

redis-py The Python interface to the Redis key-value store. Installation | Contributing | Getting Started | Connecting To Redis Installation redis-py

Redis 11k Jan 08, 2023
aiopg is a library for accessing a PostgreSQL database from the asyncio

aiopg aiopg is a library for accessing a PostgreSQL database from the asyncio (PEP-3156/tulip) framework. It wraps asynchronous features of the Psycop

aio-libs 1.3k Jan 03, 2023
Dlsite-doujin-renamer - Dlsite doujin renamer tool with python

dlsite-doujin-renamer Features 支持深度查找带有 RJ 号的文件夹 支持手动选择文件夹或拖拽文件夹到软件窗口 支持在 config

111 Jan 02, 2023
A simple wrapper to make a flat file drop in raplacement for mongodb out of TinyDB

Purpose A simple wrapper to make a drop in replacement for mongodb out of tinydb. This module is an attempt to add an interface familiar to those curr

180 Jan 01, 2023
edaSQL is a library to link SQL to Exploratory Data Analysis and further more in the Data Engineering.

edaSQL is a python library to bridge the SQL with Exploratory Data Analysis where you can connect to the Database and insert the queries. The query results can be passed to the EDA tool which can giv

Tamil Selvan 8 Dec 12, 2022
Making it easy to query APIs via SQL

Shillelagh Shillelagh (ʃɪˈleɪlɪ) is an implementation of the Python DB API 2.0 based on SQLite (using the APSW library): from shillelagh.backends.apsw

Beto Dealmeida 207 Dec 30, 2022
A library for python made by me,to make the use of MySQL easier and more pythonic

my_ezql A library for python made by me,to make the use of MySQL easier and more pythonic This library was made by Tony Hasson , a 25 year old student

3 Nov 19, 2021
Implementing basic MongoDB CRUD (Create, Read, Update, Delete) queries, using Python.

MongoDB with Python Implementing basic MongoDB CRUD (Create, Read, Update, Delete) queries, using Python. We can connect to a MongoDB database hosted

MousamSingh 4 Dec 01, 2021
SQL for Humans™

Records: SQL for Humans™ Records is a very simple, but powerful, library for making raw SQL queries to most relational databases. Just write SQL. No b

Ken Reitz 6.9k Jan 03, 2023
Micro ODM for MongoDB

Beanie - is an asynchronous ODM for MongoDB, based on Motor and Pydantic. It uses an abstraction over Pydantic models and Motor collections to work wi

Roman 993 Jan 03, 2023
Motor - the async Python driver for MongoDB and Tornado or asyncio

Motor Info: Motor is a full-featured, non-blocking MongoDB driver for Python Tornado and asyncio applications. Documentation: Available at motor.readt

mongodb 2.1k Dec 26, 2022
Find graph motifs using intuitive notation

d o t m o t i f Find graph motifs using intuitive notation DotMotif is a library that identifies subgraphs or motifs in a large graph. It looks like t

APL BRAIN 45 Jan 02, 2023
Python PostgreSQL adapter to stream results of multi-statement queries without a server-side cursor

streampq Stream results of multi-statement PostgreSQL queries from Python without server-side cursors. Has benefits over some other Python PostgreSQL

Department for International Trade 6 Oct 31, 2022
Pystackql - Python wrapper for StackQL

pystackql - Python Library for StackQL Python wrapper for StackQL Usage from pys

StackQL Studios 6 Jul 01, 2022