# Limitations of embedded q

When q is run embedded within a Python process (as opposed to over IPC), it does not have the main loop or timers that one would expect from a typical q process, and has some limitations as a result.

For example, PyKX cannot be used to respond to q IPC requests as a server. Callback functions such as .z.pg defined within a Python process will not work as expected.

Do not use PyKX as an IPC server

Attempting to connect to a Python process running PyKX over IPC from another process will hang indefinitely.

In a Python process, start a q IPC server:

>>> import pykx as kx
>>> kx.q('\\p 5001')
pykx.Identity(pykx.q('::'))
>>>

Then in a Python or q process, attempt to connect to it:

>>> import pykx as kx
>>> q = kx.QConnection(port=5001) # Attempt to create a q connection to a pykx embedded q instance
# Will hang indefinitely since the embedded q process cannot respond to IPC requests
// Attempting to create an IPC connection to a PyKX embedded q instance
// will hang indefinitely since the embedded q process cannot respond to IPC requests
q)h: hopen ::5001

Timers also do not work within PyKX. For example:

>>> import pykx as kx
>>> kx.q('\t 1000') # Set timer to tick every 1000ms
pykx.LongAtom(pykx.q('1000'))
>>> kx.q('.z.ts:{0N!x}') # Set callback function to be ran on timer tick
pykx.Identity(pykx.q('::')) # No output follows because the timer doesn't actually tick when within
# a Python process
>>> kx.q.z.ts # Trying to use the timer callback functions directly within PyKX will raise an AttributeError
AttributeError: ts: .z.ts is not exposed through the context interface because the main loop is inactive in PyKX.`