TypeDB 3.0 is live! Get started for free.

Python driver

The Python driver was developed by the TypeDB team to enable TypeDB support for Python software and developers.

The GitHub repository with the driver’s source code and release notes.

The default package manager’s page about the driver’s package.

Install

See the Version Compatibility table to check what versions of TypeDB and Python driver are compatible.

Supported Python versions: from 3.9 to 3.13. For Linux: the minimum version of glibc is 2.25.0.

To install TypeDB Python driver:

pip install typedb-driver

Checking your installation

You should be able to import the TypeDB driver as follows:

import typedb.driver

On Windows, the import may fail with ImportError: DLL load failed. If it does, it means your system is missing the Microsoft Visual C++ redistributable matching your Python version. To fix the issue, download and install the package.

Quickstart

See below an example of Python code that connects to a local TypeDB server, creates a database, processes driver errors, defines a schema, inserts some data, and then reads that data.

See the quickstart code
from typedb.driver import *


    def typedb_example():
        # Open a driver connection. The connection will be automatically closed on the "with" block exit
        with TypeDB.core_driver(TypeDB.DEFAULT_ADDRESS, Credentials("admin", "password"), DriverOptions()) as driver:
            # Create a database
            driver.databases.create("typedb")
            database = driver.databases.get("typedb")

            # Use "try" blocks to catch driver exceptions
            try:
                # Open transactions of 3 types
                tx = driver.transaction(database.name, TransactionType.READ)

                # Execute any TypeDB query using TypeQL. Wrong queries are rejected with an explicit exception
                result_promise = tx.query("define entity i-cannot-be-defined-in-read-transactions;")

                print("The result is still promised, so it needs resolving even in case of errors!")
                result_promise.resolve()
            except TypeDBDriverException as expected_exception:
                print(f"Once the query's promise is resolved, the exception is revealed: {expected_exception}")
            finally:
                # Don't forget to close the transaction!
                tx.close()

            # Open a schema transaction to make schema changes
            # Use "with" blocks to forget about "close" operations (similarly to connections)
            with driver.transaction(database.name, TransactionType.SCHEMA) as tx:
                define_query = """
                define
                  entity person, owns name, owns age;
                  attribute name, value string;
                  attribute age, value integer;
                """
                answer = tx.query(define_query).resolve()
                if answer.is_ok():
                    print(f"OK results do not give any extra interesting information, but they mean that the query "
                          f"is successfully executed!")

                # Commit automatically closes the transaction. It can still be safely called inside "with" blocks
                tx.commit()

            # Open a read transaction to safely read anything without database modifications
            with driver.transaction(database.name, TransactionType.READ) as tx:
                answer = tx.query("match entity $x;").resolve()

                # Collect concept rows that represent the answer as a table
                rows = list(answer.as_concept_rows())
                row = rows[0]

                # Collect column names to get concepts by index if the variable names are lost
                header = list(row.column_names())

                column_name = header[0]

                # Get concept by the variable name (column name)
                concept_by_name = row.get(column_name)

                # Get concept by the header's index
                concept_by_index = row.get_index(0)

                print(f"Getting concepts by variable names ({concept_by_name.get_label()}) and "
                      f"indexes ({concept_by_index.get_label()}) is equally correct. ")

                # Check if it's an entity type before the conversion
                if concept_by_name.is_entity_type():
                    print(f"Both represent the defined entity type: '{concept_by_name.as_entity_type().get_label()}' "
                          f"(in case of a doubt: '{concept_by_index.as_entity_type().get_label()}')")

                # Continue querying in the same transaction if needed
                answer = tx.query("match attribute $a;").resolve()

                # Concept rows can be used as any other iterator
                rows = [row for row in answer.as_concept_rows()]

                for row in rows:
                    # Same for column names
                    column_names_iter = row.column_names()
                    column_name = next(column_names_iter)

                    concept_by_name = row.get(column_name)

                    # Check if it's an attribute type before the conversion
                    if concept_by_name.is_attribute_type():
                        attribute_type = concept_by_name.as_attribute_type()
                        print(f"Defined attribute type's label: '{attribute_type.get_label()}', "
                              f"value type: '{attribute_type.try_get_value_type()}'")


                    print(f"It is also possible to just print the concept itself: '{concept_by_name}'")

            # Open a write transaction to insert data
            with driver.transaction(database.name, TransactionType.WRITE) as tx:
                insert_query = "insert $z isa person, has age 10; $x isa person, has age 20, has name \"John\";"
                answer = tx.query(insert_query).resolve()

                # Insert queries also return concept rows
                rows = list(answer.as_concept_rows())
                row = rows[0]

                for column_name in row.column_names():
                    inserted_concept = row.get(column_name)
                    print(f"Successfully inserted ${column_name}: {inserted_concept}")
                    if inserted_concept.is_entity():
                        print("This time, it's an entity, not a type!")

                # It is possible to ask for the column names again
                header = [name for name in row.column_names()]

                x = row.get_index(header.index("x"))
                print(
                    "As we expect an entity instance, we can try to get its IID (unique identification): {x.try_get_iid()}. ")
                if x.is_entity():
                    print(f"It can also be retrieved directly and safely after a cast: {x.as_entity().get_iid()}")

                # Do not forget to commit if the changes should be persisted
                tx.commit()

            # Open another write transaction to try inserting even more data
            with driver.transaction(database.name, TransactionType.WRITE) as tx:
                # When loading a large dataset, it's often better not to resolve every query's promise immediately.
                # Instead, collect promises and handle them later. Alternatively, if a commit is expected in the end,
                # just call `commit`, which will wait for all ongoing operations to finish before executing.
                queries = ["insert $a isa person, has name \"Alice\";", "insert $b isa person, has name \"Bob\";"]
                for query in queries:
                    tx.query(query)
                tx.commit()

            with driver.transaction(database.name, TransactionType.WRITE) as tx:
                # Commit will still fail if at least one of the queries produce an error.
                queries = ["insert $c isa not-person, has name \"Chris\";", "insert $d isa person, has name \"David\";"]
                promises = []
                for query in queries:
                    promises.append(tx.query(query))

                try:
                    tx.commit()
                    assert False, "TypeDBDriverException is expected"
                except TypeDBDriverException as expected_exception:
                    print(f"Commit result will contain the unresolved query's error: {expected_exception}")

            # Open a read transaction to verify that the previously inserted data is saved
            with driver.transaction(database.name, TransactionType.READ) as tx:
                # A match query can be used for concept row outputs
                var = "x"
                answer = tx.query(f"match ${var} isa person;").resolve()

                # Simple match queries always return concept rows
                count = 0
                for row in answer.as_concept_rows():
                    x = row.get(var)
                    x_type = x.as_entity().get_type().as_entity_type()
                    count += 1
                    print(f"Found a person {x} of type {x_type}")
                print(f"Total persons found: {count}")

                # A fetch query can be used for concept document outputs with flexible structure
                fetch_query = """
                match
                  $x isa! person, has $a;
                  $a isa! $t;
                fetch {
                  "single attribute type": $t,
                  "single attribute": $a,
                  "all attributes": { $x.* },
                };
                """
                answer = tx.query(fetch_query).resolve()

                # Fetch queries always return concept documents
                count = 0
                for document in answer.as_concept_documents():
                    count += 1
                    print(f"Fetched a document: {document}.")
                    print(f"This document contains an attribute of type: {document['single attribute type']['label']}")
                print(f"Total documents fetched: {count}")

        print("More examples can be found in the API reference and the documentation.\nWelcome to TypeDB!")

For more code examples, see the Tutorial and API reference links below.

Learn more

This tutorial will help you learn how to use the Python driver.

Driver API reference for the Python language.

Any questions about the driver after reading the documentation? Feel free to ask on our Discord community server.

Version Compatibility

Python driver TypeDB TypeDB Community Edition

3.0.0+

3.0.0+

3.0.0+

2.x and 3.x versions are not compatible. Switch to 2.x documentation for even older versions.