Search
ctrl+/
Ask AI
ctrl+.
Light
Dark
System
Sign in

Python

gel-python is the official Gel driver for Python. It provides both blocking IO and asyncio implementations.

Install the client package from PyPI using your package manager of choice.

pip
uv
Copy
$ 
pip install gel
Copy
$ 
uv add gel

To start using Gel in Python, create an gel.Client instance using gel.create_client() or gel.create_async_client() for AsyncIO. This client instance manages a pool of connections to the database which it discovers automatically from either being in a gel project init directory or being provided connection details via Environment Variables. See the environment section of the connection reference for more details and options.

If you're using Gel Cloud to host your development instance, you can use the gel cloud login command to authenticate with Gel Cloud and then use the gel project init --server-instance <instance-name> command to create a local project-linked instance that is linked to an Gel Cloud instance. For more details, see the Gel Cloud guide.

Blocking
AsyncIO
Copy
import datetime
import gel

client = gel.create_client()

client.query("""
    INSERT User {
        name := <str>$name,
        dob := <cal::local_date>$dob
    }
""", name="Bob", dob=datetime.date(1984, 3, 1))

user_set = client.query(
    "SELECT User {name, dob} FILTER .name = <str>$name", name="Bob")
# *user_set* now contains
# Set{Object{name := 'Bob', dob := datetime.date(1984, 3, 1)}}

client.close()
Copy
import asyncio
import datetime
import gel

client = gel.create_async_client()

async def main():
    await client.query("""
        INSERT User {
            name := <str>$name,
            dob := <cal::local_date>$dob
        }
    """, name="Bob", dob=datetime.date(1984, 3, 1))

    user_set = await client.query(
        "SELECT User {name, dob} FILTER .name = <str>$name", name="Bob")
    # *user_set* now contains
    # Set{Object{name := 'Bob', dob := datetime.date(1984, 3, 1)}}

    await client.aclose()

asyncio.run(main())

For server-type applications that handle frequent requests and need the database connection for a short period of time while handling a request, you will want to use a connection pool. Both gel.Client and gel.AsyncIOClient come with such a pool.

For gel.Client, all methods are thread-safe. You can share the same client instance safely across multiple threads, and run queries concurrently. Likewise, AsyncIOClient is designed to be shared among different asyncio.Task/coroutines for concurrency.

Below is an example of a web API server running fastapi:

Copy
import asyncio
import gel
from fastapi import FastAPI, Query

app = FastAPI()

@app.on_event("startup")
async def startup_event():
    """Initialize the database client on startup."""
    app.state.client = gel.create_async_client()
    # Optional: explicitly start up the connection pool
    await app.state.client.ensure_connected()

@app.get("/users")
async def handle(
  name: str = Query(None)
):
    """Handle incoming requests."""
    client = app.state.client

    # Execute the query on any pool connection
    if name:
      result = await client.query_single(
          '''
              SELECT User {first_name, email, bio}
              FILTER .name = <str>$username
          ''', username=name)
    else:
      result = await client.query(
          '''
              SELECT User {first_name, email, bio}
          ''')
    return result

if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app, host="0.0.0.0", port=8000)

Note that the client instance itself is created synchronously. Pool connections are created lazily as they are needed. If you want to explicitly connect to the database in startup_event(), use the ensure_connected() method on the client.

For more information, see API documentation of the blocking client and the asynchronous client.

To create a transaction use the transaction() method on the client instance:

Example:

Blocking
AsyncIO
Copy
for tx in client.transaction():
    with tx:
        tx.execute("INSERT User {name := 'Don'}")
Copy
async for tx in client.transaction():
    async with tx:
        await tx.execute("INSERT User {name := 'Don'}")

When not in an explicit transaction block, any changes to the database will be applied immediately.

For more information, see API documentation of transactions for the blocking client and the AsyncIO client.

The gel-python package exposes a command-line tool to generate typesafe functions from *.edgeql files, using dataclasses for objects primarily.

queries/get_user_by_name.edgeql
Copy
with
    name := <str>$name,
select User { first_name, email, bio }
filter .name = name;
Copy
$ 
gel-py
# or
Copy
$ 
python -m gel.codegen
Copy
import gel
from .queries import get_user_by_name_sync_edgeql as get_user_by_name_qry

client = gel.create_async_client()

async def main():
  result = await get_user_by_name_qry.get_user_by_name(client, name="John")
  print(result)

asyncio.run(main())