Loading KDB-X Modules¶
This page documents how to load KDB-X q modules into Python with kx.use, the QModule objects returned, and the SearchPath used to locate them.
For a guided introduction with examples of each published module, see Load KDB-X modules. For the list of available modules, see the KDB-X module index.
pykx.module
¶
Loading KDB-X modules.
When pykx.use is called KDB-X will attempt to load a module with the given name.
QModule
¶
QModule(qns, qdict)
A loaded KDB-X q Module.
Example loading the pq module and the pq.t submodule within KDB-X Python.
>>> import pykx as kx
>>> pq = kx.use('kx.pq')
>>> pq
pykx.QModule(pykx.q('
pq| pykx.Lambda
op| pykx.Lambda
rd| pykx.Lambda
'))
>>> len(pq)
3
>>> pq['pq'] # a key reaches the same export as the attribute
pykx.Lambda(pykx.q('locked'))
>>> pq.t = kx.use('kx.pq.t')
>>> pq
pykx.QModule(pykx.q('
pq| pykx.Lambda
op| pykx.Lambda
rd| pykx.Lambda
t | pykx.QModule(pykx.q('
mkT| pykx.Lambda
mkP| pykx.Lambda
tt | pykx.Lambda
mt | pykx.Lambda
fv | pykx.Lambda
'))
'))
Assigning to an exported name writes to the module's private q namespace, which is how a module's own function or configuration variable is patched from Python:
>>> greet = kx.use('kx.greet')
>>> greet.hello = kx.q('{"Hi, ",x,"!"}')
>>> print(greet.hello(b'KDB-X'))
Hi, KDB-X!
Where no q namespace is known, as for a dictionary presented through
wrap, assignment raises TypeError rather than writing
somewhere else.
QNamespaceProxy
¶
QNamespaceProxy(qns, value)
Bases: QModule
A q namespace nested inside a loaded module.
q marks a namespace with an empty-symbol key whose value is ::. A member carrying
that entry is presented as one of these rather than as a
pykx.Dictionary, so its own members are reachable by attribute and
by key, and a write reaches the q namespace behind it where the member really is one.
>>> kafka = kx.use('kx.kafka')
>>> type(kafka.OFFSET)
<class 'pykx.module.QNamespaceProxy'>
>>> kafka.OFFSET['BEGINNING']
pykx.LongAtom(pykx.q('-2'))
>>> kafka.OFFSET.BEGINNING
pykx.LongAtom(pykx.q('-2'))
use ¶
use(module_name, export_argument=None)
Function for loading KDB-X modules.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
module_name |
str
|
The name of the KDB-X module to load as a string. |
required |
export_argument |
object
|
Optional argument to pass to the module export function. Default None. |
None
|
Returns:
| Type | Description |
|---|---|
QModule
|
A loaded QModule instance. |
Examples:
Example loading the pq module and the pq.t submodule within KDB-X Python.
>>> import pykx as kx
>>> from pathlib import Path
>>> pq = kx.module.use('kx.pq')
>>> pq.t = kx.module.use('kx.pq.t')
>>> tab = pq.pq(Path('../types.parquet'))
>>> tab
pykx.VirtualTable(pykx.q('`T!`f`m`t!(k){[f;t;c;b;a;v]g:$[s:-1h=@b;0;#b];(bf;b1):$[g;df[t;0,0b;b];(::;()..'))
>>> tab.select()
pykx.Table(pykx.q('
col0 col1 col2
---------------
1 1 "asd"
1 2 "bsd"
0 3 "csd"
1 4 "asd"
0 5 "bsd"
0 6 "csd"
1 7 "asd"
0 8 "bsd"
0 9 "csd"
'))
wrap ¶
wrap(qdict)
Present a q dictionary of names as an attribute-accessible object.
Some modules expose functionality through a function which returns a dictionary rather
than through their export variable. The KDB-X Logging module is one: its
createLog builds an independent logger and returns it as a dictionary, whose
members would otherwise have to be reached by key. wrap presents such a
dictionary the way a loaded module is presented, with attribute access and
dir support.
The result is not a loaded module and has no q namespace behind it, so attribute
assignment raises TypeError. Use whatever setter the dictionary provides.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
qdict |
Dictionary
|
The q dictionary to wrap. |
required |
Returns:
| Type | Description |
|---|---|
QModule
|
A |
Raises:
| Type | Description |
|---|---|
TypeError
|
If |
Wrap a logger returned by the Logging module's createLog:
>>> import pykx as kx
>>> logger = kx.use('kx.log')
>>> log = kx.module.wrap(logger.createLog())
>>> dir(log)
['add', 'addfmt', 'debug', 'error', 'fatal', 'fmts', 'getfmt', 'getlvl', 'info',
'remove', 'setfmt', 'setlvl', 'sinks', 'trace', 'warn']
>>> log.info(b'Hello World!')
2026.09.04D10:45:45.780488685 info PID[320523] HOST[localhost] Hello World!
>>> log.setlvl('trace')
>>> log.getfmt()
pykx.SymbolAtom(pykx.q('`basic'))
Not every entry is callable. Some are symbols naming a q variable rather than a
function, and q dereferences those when they are applied. Python has no equivalent
overload, so read them with kx.q.get:
>>> log.getlvl
pykx.SymbolAtom(pykx.q('`.m.kx.0log.log.1.lvl'))
>>> kx.q.get(log.getlvl)
pykx.SymbolAtom(pykx.q('`trace'))
unwrap ¶
unwrap(module)
Recover the q dictionary behind a QModule or a QNamespaceProxy.
This is the inverse of wrap. Use it when a member has been
presented as a QNamespaceProxy and you need the
dictionary itself.
A q namespace is identified by an empty-symbol key whose value is ::. A dictionary
can carry that same entry deliberately, as a placeholder which keeps the values a general
list and stops q promoting them to a typed vector. Such a dictionary is indistinguishable
from a namespace, so it is presented as a QNamespaceProxy.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
module |
Union[QModule, QNamespaceProxy]
|
The |
required |
Returns:
| Type | Description |
|---|---|
Dictionary
|
The underlying q dictionary. For a loaded module this is its |
Raises:
| Type | Description |
|---|---|
TypeError
|
If |
A module exporting a dictionary that uses the placeholder entry:
>>> import pykx as kx
>>> mod = kx.use('kx.mymodule')
>>> mod.opts # looks like a namespace, so presented as one
pykx.QNamespaceProxy(pykx.q('
headers| pykx.Dictionary
'))
>>> opts = kx.module.unwrap(mod.opts)
>>> opts['headers']
pykx.Dictionary(pykx.q('
Accept| "a"
X | "b"
'))
A nested member reached by attribute arrives as a
kx.module.QNamespaceProxy, which unwrap
also accepts:
>>> kafka = kx.use('kx.kafka')
>>> type(kafka.OFFSET)
<class 'pykx.module.QNamespaceProxy'>
>>> kx.module.unwrap(kafka.OFFSET)['BEGINNING']
pykx.LongAtom(pykx.q('-2'))
SearchPath ¶
SearchPath(
entry=None, *, add=False, remove=False, prepend=False, strict=False, allow_duplicates=False
)
Manage the module SearchPath.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
entry |
Optional[str]
|
The path string to add or remove. If omitted, the current SearchPath is returned. |
None
|
add |
bool
|
If True, add the entry to the SearchPath. Default False. |
False
|
remove |
bool
|
If True, remove all occurrences of the entry from the SearchPath. Default False. |
False
|
prepend |
bool
|
If True, insert the entry at the front rather than the end. Default False. |
False
|
strict |
bool
|
If True, raise a ValueError when attempting to remove an entry that is not present. Default False. |
False
|
allow_duplicates |
bool
|
If True, allow the same entry to appear more than once in the SearchPath. Default False. |
False
|
Examples:
Retrieve the current SearchPath:
>>> kx.module.SearchPath()
[]
Append and prepend entries:
>>> kx.module.SearchPath("/home/user/.kx/mod", add=True)
>>> kx.module.SearchPath("/home/user/mod", add=True)
>>> kx.module.SearchPath("/other/mod", add=True, prepend=True)
>>> kx.module.SearchPath()
['/other/mod', '/home/user/.kx/mod', '/home/user/mod']
Remove an entry:
>>> kx.module.SearchPath("/other/mod", remove=True)
>>> kx.module.SearchPath()
['/home/user/.kx/mod', '/home/user/mod']