In Python I use 'with psycopg2.connect() as conn:' for database connections. How do I manage resources in EK9?

← Getting Started · Ref: Q1011

EK9 uses try-with-resource for automatic cleanup, similar to Python's 'with' statement.

Python:

  with psycopg2.connect(connString) as conn:
      cursor = conn.cursor()
      cursor.execute('SELECT ...')
      results = cursor.fetchall()
  # conn automatically closed here

EK9:

  try
    -> connection <- openConnection(connString)
    results <- queryDatabase(connection, sqlQuery)
    processResults(results)
  catch
    -> ex as Exception
    stderr.println(`Database error: ${$ex}`)
  finally
    cleanup()

The try -> resource <- expr() pattern declares a resource that is automatically closed when the try block ends. The -> means 'data flowing in' — the connection is the resource being managed.

The resource type must declare `operator close as pure` (a method simply named close() is an error, E07660, because close is an operator name). EK9 calls that operator automatically when the try statement ends - like Python's __exit__() or Java's AutoCloseable. The resource class also needs `override operator ? as pure`.

Example

defines module qa.gettingstarted.frompythonconnection

  defines class

    Connection
      queryName()
        <- rtn as String: "Database User"

      override operator ? as pure
        <- rtn as Boolean: true

      // Called automatically when the try statement ends
      operator close as pure
        Stdout().println("Connection closed")

  defines function

    buildGreeting() as pure
      -> personName as String
      <- rtn as String: "Hello, " + personName

  defines program

    ConnectionPatternDemo()
      stdout <- Stdout()
      stderr <- Stderr()

      // Pattern: try-with-resource for connection-like objects
      // In Python: with open('file.txt') as f: data = f.read()
      // In EK9: try -> resource <- Resource() ... catch/finally
      // The resource's 'operator close as pure' runs when the try statement ends

      try
        -> connection <- Connection()
        greeting <- buildGreeting(connection.queryName())
        stdout.println(greeting)
      catch
        -> ex as Exception
        stderr.println(`Error: ${ex}`)
      finally
        stdout.println("Cleanup complete")

Common mistakes

E01073 — 'null' does not exist in EK9, so a Python-style 'is not None' check has no equivalent. Use try-with-resource for connections: 'try -> connection <- expr()', where the resource type declares 'operator close as pure'. See ek9 -h E01073.

Incorrect:

      connection <- Connection()
      if connection <> null
        greeting <- buildGreeting(connection.queryName())
        stdout.println(greeting)

Correct:

      try
        -> connection <- Connection()
        greeting <- buildGreeting(connection.queryName())
        stdout.println(greeting)
      catch
        -> ex as Exception
        stderr.println(`Error: ${ex}`)
      finally
        stdout.println("Cleanup complete")
Other ways to ask this
  • What is the EK9 equivalent of Python's context manager for connections?
  • How do I safely open and close a connection in EK9?
  • How does EK9 handle resource cleanup like Python's with statement?

Coming from another language?

Python developers: your 'with X as y:' pattern becomes EK9's 'try -> y <- X'. The resource's `operator close as pure` replaces __exit__ (a finally block is separate and runs its own code). Exception handling uses catch -> ex as Exception.

Keywords: migration, python, connection, with, resource, try, cleanup