Executing Commands and Managing Connections

After a connection is established, you can use exec() to execute DolphinDB scripts, call() to call server-side functions, and upload() to upload Python data to the server. run() is retained as a compatible entry point and can still be used for script execution and function calls. After using the connection, call close() to release resources.

Commands on the same connection are executed in call order. If multiple threads issue commands on the same connection at the same time, later calls wait for the current command to complete. To execute commands concurrently, use a connection pool. When using block reads, you must read the current result set to the end or explicitly discard the remaining data before executing subsequent commands on the same connection.

exec: Execute scripts

Use exec() to execute a DolphinDB script and return the script execution result.

def exec(
    self,
    script,
    *,
    clear_memory=False,
    table_to_list=False,
    priority=4,
    parallelism=64,
    fetch_size=None,
    disable_decimal=False,
) -> object: ...

Script parameter script

  • script: required. Specifies the DolphinDB script to be executed. It can be an expression, a query statement, or multiple statements separated by semicolons.

conn.exec("x = 1..10")
print(conn.exec("sum(x)"))
# output: 55

Memory parameter clear_memory

  • clear_memory: optional, bool, default False. Specifies whether to release variables created by this request in the session after the request is completed.

Set it to True when executing scripts whose intermediate variables do not need to be reused in later requests.

conn.exec("temporary = 1..100", clear_memory=True)

Table conversion parameter table_to_list

  • table_to_list: optional, bool, default False. Specifies whether to convert table results to a list by column. It is valid only for the DDB and PICKLE protocols.

Note: Under the DDB protocol, if a table contains an array vector column, that is, a column whose elements are vectors, enabling this option converts the column to a two-dimensional array. This requires all row vectors in that column to have exactly the same length; otherwise, conversion fails.

columns = conn.exec(
    "table(1..3 as id, `A`B`C as sym)",
    table_to_list=True,
)
print(columns[0])
# output: [1 2 3]

Job parameters priority, parallelism

  • priority: optional, int, default 4. Specifies the job priority. The value ranges from 0 to 9, the bigger the value, the higher the priority.

  • parallelism: optional, int, default 64. Specifies the maximum number of threads for executing the job's subtasks on a single data node. The value must be greater than 0.

The actual value of priority does not exceed the upper limit set by setMaxJobPriority on the server. The actual value of parallelism does not exceed the upper limit set by setMaxJobParallelism on the server.

result = conn.exec(
    "sum(1..1000000)",
    priority=7,
    parallelism=16,
)

Block read parameter fetch_size and the BlockReader interface

  • fetch_size: optional, int, default None. Specifies the number of records returned in each block during block reads. It should be an integer not less than 8192.

After this parameter is specified, exec() returns a BlockReader instead of returning the complete result at once. This parameter is used only for scripts that return tables.

Each block of table data read in this mode is returned as a pandas.DataFrame. The result is not converted according to the Arrow or PICKLE protocol specified at construction. Currently, table_to_list and disable_decimal are not applied either. Use a regular query if these conversion options are required.

conn.exec("testblock = table(1..20000 as id)")
block = conn.exec("select * from testblock", fetch_size=8192)

total = 0
try:
    for data in block:
        total += len(data)
finally:
    block.skip_all()

print(total)
# output: 20000
BlockReader interface Description
read() Reads the next block of data. After all data is read, the connection's block read state is automatically cleared.
has_next Checks whether there is still unread data.
hasNext() Compatible method for has_next.
skip_all() Discards all unread data and clears the connection's block read state.
skipAll() Compatible method for skip_all().

Before all data is read, no other command can be executed on the same connection. If the remaining data is no longer needed, call skip_all():

block = conn.exec("select * from testblock", fetch_size=8192)
first_block = block.read()
block.skip_all()

print(conn.exec("1 + 1"))
# output: 2

Note:

  • When using fetch_size for block reads, fetch_size must be greater than or equal to 8192, and the execution result must be a table. Do not specify fetch_size in asynchronous mode.

  • If an exception occurs before obtaining a BlockReader (such as invalid parameters or mismatched result types), the connection cannot be used for subsequent operations. In this case, close the connection via close() and establish a new one rather than reusing it.

DECIMAL conversion parameter disable_decimal

  • disable_decimal: optional, bool, default False. Controls whether DECIMAL columns in the result table are converted to DOUBLE.

When set to True, DECIMAL columns in the result table are converted to DOUBLE. This parameter must be used with DolphinDB 2.00.12.3, 3.00.1, or later. The client does not check the server version in advance. For details, see Common Methods of Session.

result = conn.exec(
    "table(decimal32([1.23, 2.345], 3) as value)",
    disable_decimal=True,
)
print(result.dtypes)
# value    float64

exec return values and exceptions

  • If fetch_size is not specified, exec() returns the script execution result. The specific Python type depends on the DolphinDB data form and the current protocol.

  • When fetch_size is specified in synchronous mode, a BlockReader is returned for block reads of table results.

  • When asynchronous mode is enabled (enable_async=True), the request does not wait for the server response after being sent, and None is returned.

  • If priority is outside the range of 0 to 9, parallelism is not a positive integer, fetch_size is smaller than 8192, or server-side script execution fails, RuntimeError is usually thrown.

  • If the previous BlockReader has not been fully read and skip_all() has not been called to discard the remaining data, continuing to call exec(), call(), run(), or upload(), or reading is_alive on the same connection, usually throws RuntimeError.

call: Call functions

Use call() to call DolphinDB built-in functions or functions already defined on the server.

def call(
    self,
    func,
    *args,
    clear_memory=False,
    table_to_list=False,
    priority=4,
    parallelism=64,
    disable_decimal=False,
) -> object: ...
  • func: required. Specifies the name of the DolphinDB built-in function or user-defined function to call.

  • args: optional. Positional arguments passed to the server-side function in order.

The remaining parameters have the same meanings as the parameters with the same names in exec(). call() does not support fetch_size and cannot be used for block reads.

print(conn.call("sum", [1, 2, 3]))
print(conn.call("add", 1, 2))
# output: 6
# output: 3

To call a function with no arguments, call conn.call("functionName") directly without passing extra parameters:

conn.exec("def answer(){ return 42; }")
print(conn.call("answer"))
# output: 42

If the function does not exist, server-side parameter validation fails, permission is denied, or function execution fails, RuntimeError is usually thrown. If the Python call signature does not match, TypeError is thrown.

run: Unified execution entry point

run() is a compatible entry point. It dispatches the request to exec() or call() depending on whether function arguments are passed.

  • script: required. Specifies the script to execute, or the name of the server-side function to call when function arguments are passed.

  • args: optional. Specifies the positional arguments passed to the server-side function, and determines the call mode of run().

  • kwargs: optional. Keyword arguments with the same names supported by exec() or call().

def run(self, script, *args, **kwargs) -> object: ...
  • If args is not passed, it is equivalent to exec(script, **kwargs).

  • If one or more args are passed, it is equivalent to call(script, *args, **kwargs).

print(conn.run("1 + 1"))
print(conn.run("add", 1, 2))
# output: 2
# output: 3

fetch_size applies only to script execution mode where args is not passed. If fetch_size is passed in function call mode, TypeError is thrown.

To call a function with no arguments, use call("functionName") or exec("functionName()"). run("functionName") executes the function name as script content and does not call the function automatically.

upload: Upload data

Use upload() to upload Python objects to the current DolphinDB session and create variables with the same names on the server.

def upload(self, objs): ...
  • objs: required. Specifies the set of variables to upload. It must be a dictionary.

The keys of the dictionary are server-side variable names and must comply with DolphinDB variable naming rules. The values are the data to upload, and can be supported Python objects such as scalars, strings, lists, dictionaries, sets, pandas.DataFrame, and numpy.ndarray. A pandas.DataFrame is uploaded as a DolphinDB table.

conn.upload({"a": 8, "b": "abc"})
print(conn.run("a"))
# output: 8

After the upload succeeds, the variables are stored in the current server-side session and can be used directly in subsequent scripts or function calls. In synchronous mode, a successful upload returns the server-side object address. If an empty dictionary is passed or asynchronous mode is enabled, the current implementation returns -1. If a variable name is invalid, an object type is unsupported, or the server rejects the upload, RuntimeError is usually thrown.

login: Log in or switch users

Use login() to log in to the DolphinDB server on an established connection, or to switch to another user. If no login information is provided during connection establishment, or if you need to switch users later, call this method.

def login(self, userid, password, enable_encryption=True) -> None: ...
  • userid: required. Specifies the DolphinDB user name.

  • password: required. Specifies the login password for the user.

  • enable_encryption: optional, bool, default True. Specifies whether to encrypt user credentials during transmission.

Note: enable_encryption is currently a reserved parameter and individual credential encryption is not yet implemented. To secure data transmission and protect login credentials, enable SSL encryption by setting enable_ssl=True with proper server-side SSL configuration.

conn = ddb.DBConnection()
conn.connect("localhost", 8848)
conn.login("admin", "your_password")

If login succeeds, None is returned. If authentication fails, the connection is unavailable, or the server rejects the login, RuntimeError is usually thrown.

close: Close the connection

Use close() to close the current connection and release related network resources. Explicitly call this method when the connection is no longer needed.

def close(self) -> None: ...

close() can be called repeatedly. The object destructor also attempts to close the connection, but you should not rely on Python garbage collection to release resources in a timely manner. Use try...finally to ensure that the connection is eventually closed.

Before closing a connection, ensure that the current command has finished and that block read results have been fully read or the remaining data has been discarded by calling skip_all(). Avoid calling close() while the connection is still being used by another thread.

conn = ddb.DBConnection()
try:
    if not conn.connect("localhost", 8848):
        raise RuntimeError("Failed to connect to DolphinDB")
    print(conn.exec("1 + 1"))
finally:
    conn.close()