Provides a way of interfacing with a Python backend by sending commands as JSON.
Project description
Liaison
Liaison provides a way of interfacing with a Python backend by sending commands as JSON.
History
Liaison was built by Open Science Tools Ltd. to provide an interface between the PsychoPy Studio app (a frontend built in Electron/Svelte) and the PsychoPy Python library. Owing to the general usefulness of being able to interface with Python via JSON commands, we decided to release it as its own package, for general use. Liaison is distributed under an MIT License.
While Liaison is designed to allow support for other communication methods to be added in future, and could hypothetically support any method over which a JSON string can be sent, it presently only supports sending/receiving messages over websocket as this is the implementation it was built for.
Liaison is not a generic data structure tool. It's a system for sending simple instructions to a Python instance and doing some basic namespace management. If you are interested in the exchange of serialised strcutured data, check out Google's Protocol Buffers or Cap'n Proto.
Getting started with Websocket Liaison
Installing
To use Liaison with websockets, you will need to install with the optional websocket dependencies:
pip install liaison-backend[websocket]
Then make sure you have something setup on your application frontend which can make command line calls, such as Node's child_process module.
Getting constants
Liaison uses a few constant values to communicate when it's started and stopped. While you could hardcode these, you can also get them from Liaison via command line:
python -m liaison.constants
which will return a JSON string:
{"START_MARKER": "LIAISON:CONNECTED", "STOP_MARKER": "LIAISON:DISCONNECTED"}
When Liaison starts, it will send the START_MARKER, and will send the STOP_MARKER when it stops, so looking out for these values lets you keep track of the life cycle of the Liaison backend.
Starting Liaison
To start a Liaison backend on a particular websocket address, just call:
python -m liaison.websocket <address>
This will run continuously until told to stop, listening for messages on the given websocket address. It will send the START_MARKER constant to its stdout upon starting, and will send the STOP_MARKER constant upon stopping.
Example: Starting a Liaison backend from a Node (JavaScript) app
import proc from "child_process";
// binary decoder for websocket messages
const decoder = new TextDecoder();
// choose an address to open the websocket on
const address = "localhost:8003";
// get liaison constants
const liaisonConstants = JSON.parse(
proc.execSync(
"python -m liaison.constants"
)
);
// start process running liaison
const liaisonProcess = proc.spawn(
`python -m liaison.websocket ${address}`
);
// wait for started message
var liaisonStarted = Promise.withResolvers()
liaisonProcess.stdout.on("data", evt => {
// if message indicates liaison has started, resolve promise
if (decoder.decode(evt) === `${liaisonConstants.START_MARKER}@${address}`) {
liaisonStarted.resolve(evt)
}
})
await liaisonStarted.promise
// create websoket to send messages over
let liaisonSocket = new WebSocket(`ws://${address}`);
Companion object
Each instance of Liaison creates an instance of Companion; this is an object with its own namespace, whose methods Liaison can call, giving access to Python through them. Objects in the Companion's namespace can be used as an argument to any given function by prepending them with $. Companion objects have the following methods:
get
Get the value from this Companion's namespace which a string points to.
Parameters
target <string>A string of attribute/key references starting with a name in this Companion's namespace or an importable package.
Returns
<any>The value of the given target
exists
Check whether a target exists, either as a name in this Companion's namespace or as part of an installed Python module.
Parameters
target <string>A string of attribute/key references starting with a name in this Companion's namespace or an importable package.
Returns
<boolean>true/false according to whether the target exists
init
Initialize an object and store it in this Companion's namespace
Parameters
name <string>Name to store the created object bycls <string>Resolvable string pointing to the class to initialise (or a callable to use as a constructor)args <array>Positional arguments to supply to the constructorkwargs <object>Named arguments to supply to the constructor
Returns
<string>The name the object was registered to
run
Call the given function
Parameters
fcn <string>Resolvable path to the functionargs <array>Positional arguments to pass to the functionkwargs <object>Named arguments to pass to the function
Returns
<any>Output from the function
try
The same as run, but called within a try:except statement
Parameters
fcn <string>Resolvable path to the functionargs <array>Positional arguments to pass to the functionkwargs <object>Named arguments to pass to the function
Returns
<object>Object with a key "success" indicating whether the method executed successfully, and a key "result" containing either the output of the function or the caught error
register
Register something resolvable (e.g. a module, class or method) under a particular name
Parameters
name <string>Name to register astarget <string>Resolvable string pointing to object to register
Returns
<string>Name the object was registered as
store
Store an arbitrary value in this Companion's namespace
Parameters
name <string>Name to register asvalue <string>Value to store
Returns
<string>Name the value was registered as
ping
Returns the word "pong". Useful for testing whether a Liaison is still alive, or send routine messages to keep a connection open.
Sending messages
Once you have both a Liaison process and a websocket setup, you can send messages to Liaison which will be executed by its Companion object. Liason has access to any Python modules present in the python environment it was executed from. The syntax of these messages is as follows:
command <object>command <string>Companion method to execute, see above for options and inputs for eachargs <array>Array of positional arguments to pass to the Companion methodkwargs <object>Object of key:value pairs indicating the keyword arguments to be passed to the Companion method
id <string>An arbitrary ID; when the function returns, any output will be sent back as a websocket message with the same ID
Example: Performing a T-Test in scipy over Liaison
// define some data to do a T-Test on
let a = [0.5982758 , 0.67019733, 0.68617796, 0.28764011]
let b = [0.41138649, 1.67023998, 1.0420896 , 1.49671732]
// create the command to send
let cmd = {
command: {
command: 'run',
args: [
"scipy.stats:ttest_ind", a, b
],
kwargs: {
equal_var: false
}
},
id: crypto.randomUUID()
}
// send the command as a JSON string
liaisonSocket.send(
JSON.stringify(cmd)
)
// wait for a reply (optional)
let replied = Promise.withResolvers()
let lsnr = evt => {
// parse message
let data = JSON.parse(evt.data)
// if message is a reply to our command...
if (data.evt.id !== cmd.id) {
// stop listening
liaisonSocket.removeEventListener("message", lsnr)
// resolve/reject promise
if (data.response) {
replied.resolve(data.response)
} else {
replied.reject(data)
}
}
}
liaisonSocket.addEventListener("message", lsnr)
// get response
let resp = await replied.promise
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file liaison_py-1.0.0.tar.gz.
File metadata
- Download URL: liaison_py-1.0.0.tar.gz
- Upload date:
- Size: 12.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ee91fa920e1f0d6b47d1ff78a6e4a032edc99ee8da607a2584eb1ac442122433
|
|
| MD5 |
807d5639f1ebb0b32cd2919a28957f56
|
|
| BLAKE2b-256 |
44bd690fb9183244f05087bb585e97e10a65de8bb3be02922f94b819ae93939d
|
Provenance
The following attestation bundles were made for liaison_py-1.0.0.tar.gz:
Publisher:
pypi.yml on psychopy/liaison
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
liaison_py-1.0.0.tar.gz -
Subject digest:
ee91fa920e1f0d6b47d1ff78a6e4a032edc99ee8da607a2584eb1ac442122433 - Sigstore transparency entry: 948975055
- Sigstore integration time:
-
Permalink:
psychopy/liaison@e777a08f4e4b0e025afa330c7265271516de46a4 -
Branch / Tag:
refs/tags/1.0.0 - Owner: https://github.com/psychopy
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
pypi.yml@e777a08f4e4b0e025afa330c7265271516de46a4 -
Trigger Event:
push
-
Statement type:
File details
Details for the file liaison_py-1.0.0-py3-none-any.whl.
File metadata
- Download URL: liaison_py-1.0.0-py3-none-any.whl
- Upload date:
- Size: 11.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
642d0fdd962465920caf298074e87cdcbcd9011c46676c3623e8613003f5d766
|
|
| MD5 |
cad3d67434137ee9149956833233290b
|
|
| BLAKE2b-256 |
ec4b27f37191c9e66c7433b6165c4cc65bf35491976eeaba74526eddaa3f40b2
|
Provenance
The following attestation bundles were made for liaison_py-1.0.0-py3-none-any.whl:
Publisher:
pypi.yml on psychopy/liaison
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
liaison_py-1.0.0-py3-none-any.whl -
Subject digest:
642d0fdd962465920caf298074e87cdcbcd9011c46676c3623e8613003f5d766 - Sigstore transparency entry: 948975092
- Sigstore integration time:
-
Permalink:
psychopy/liaison@e777a08f4e4b0e025afa330c7265271516de46a4 -
Branch / Tag:
refs/tags/1.0.0 - Owner: https://github.com/psychopy
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
pypi.yml@e777a08f4e4b0e025afa330c7265271516de46a4 -
Trigger Event:
push
-
Statement type: