Client API¶
This module provides Context for use in interactive and/or multi-threaded environment.
Most methods will block the calling thread until a return is available, or an error occurs.
Alternatives to p4p.client.thread.Context are provided
p4p.client.cothread.Context,
p4p.client.asyncio.Context,
and p4p.client.Qt.Context.
These differ in how blocking for I/O operation is performed,
and the environment in which Monitor callbacks are run.
Note that p4p.client.Qt.Context behaves differently from the others in some respects.
This is described in Qt Client.
Usage¶
Start by creating a client Context.
>>> from p4p.client.thread import Context
>>> Context.providers()
['pva', ....]
>>> ctxt = Context('pva')
Note
The default network configuration taken from the process environment
may be overridden by passing ‘conf=’ to the Context class constructor.
See What is PVAccess? for background on PVAccess protocol.
Get/Put¶
Get and Put operations can be performed on single PVs or a list of PVs.
>>> V = ctxt.get('pv:name')
>>> A, B = ctxt.get(['pv:1', 'pv:2'])
>>> ctxt.put('pv:name', 5)
>>> ctxt.put('pv:name', {'value': 5}) # equivalent to previous
>>> ctxt.put('pv:name', {'field_1.value': 5, 'field_2.value': 5}) # put to multiple fields
By default the values returned by Context.get() are subject to Automatic Value unwrapping.
Monitor¶
Unlike get/put/rpc, the Context.monitor() method does not block.
Instead it accepts a callback function which is called with each
new Value, or Exception.
def cb(V):
print 'New value', V
sub = ctxt.monitor('pv:name', cb)
time.sleep(10) # arbitrary wait
sub.close()
The monitor method returns a Subscription which has a close method
to end the subscription.
By default the values passed to monitor callbacks are subject to Automatic Value unwrapping.
p4p.client.thread.Context Runs callbacks in a worker thread pool.
p4p.client.cothread.Context Runs callbacks in a per-subscription cothread.
p4p.client.asyncio.Context Runs callbacks in a per-subscription coroutine.
In all cases it is safe for a callback to block/yield.
Subsequent updates for a Subscription will not be delivered until the current callback has completed.
However, updates for other Subscriptions may be delivered.
RPC¶
See RPC Server Helpers.
API Reference¶
- class p4p.client.thread.Context(provider, conf=None, useenv=True)[source]¶
- Parameters:
provider (str) – A Provider name. Try “pva” or run
Context.providers()for a complete list.conf (dict) – Configuration to pass to provider. Depends on provider selected.
useenv (bool) – Allow the provider to use configuration from the process environment.
workers (int) – Size of thread pool in which monitor callbacks are run. Default is 4
maxsize (int) – Size of internal work queue used for monitor callbacks. Default is unlimited
nt (dict) – Controls Automatic Value unwrapping. None uses defaults. Set False to disable
unwrap (dict) – Legacy Automatic Value unwrapping.
queue (WorkQueue) – A work queue through which monitor callbacks are dispatched.
The methods of this Context will block the calling thread until completion or timeout
The meaning, and allowed keys, of the configuration dictionary depend on the provider. conf= will override values taken from the process environment. Pass useenv=False to ensure that environment variables are completely ignored.
The “pva” provider understands the following keys:
EPICS_PVA_ADDR_LIST
EPICS_PVA_AUTO_ADDR_LIST
EPICS_PVA_SERVER_PORT
EPICS_PVA_BROADCAST_PORT
- name = ''¶
Provider name string
- get(name, request=None, timeout=5.0, throw=True)[source]¶
Fetch current value of some number of PVs.
- Parameters:
name – A single name string or list of name strings
request – A
p4p.Valueor string to qualify this request, or None to use a default.timeout (float) – Operation timeout in seconds
throw (bool) – When true, operation error throws an exception. If False then the Exception is returned instead of the Value
- Returns:
A p4p.Value or Exception, or list of same. Subject to Automatic Value unwrapping.
When invoked with a single name then returns is a single value. When invoked with a list of name, then returns a list of values
>>> ctxt = Context('pva') >>> V = ctxt.get('pv:name') >>> A, B = ctxt.get(['pv:1', 'pv:2']) >>>
- put(name, values, request=None, timeout=5.0, throw=True, process=None, wait=None, get=True)[source]¶
Write a new value of some number of PVs.
- Parameters:
name – A single name string or list of name strings
values – A single value, a list of values, a dict, a
Value. May be modified by the constructor nt= argument.request – A
p4p.Valueor string to qualify this request, or None to use a default.timeout (float) – Operation timeout in seconds
throw (bool) – When true, operation error throws an exception. If False then the Exception is returned instead of the Value
process (str) – Control remote processing. May be ‘true’, ‘false’, ‘passive’, or None.
wait (bool) – Wait for all server processing to complete.
get (bool) – Whether to do a Get before the Put. If True then the value passed to the builder callable will be initialized with recent PV values. eg. use this with NTEnum to find the enumeration list.
- Returns:
A None or Exception, or list of same
When invoked with a single name then returns is a single value. When invoked with a list of name, then returns a list of values
If ‘wait’ or ‘process’ is specified, then ‘request’ must be omitted or None.
>>> ctxt = Context('pva') >>> ctxt.put('pv:name', 5.0) >>> ctxt.put(['pv:1', 'pv:2'], [1.0, 2.0]) >>> ctxt.put('pv:name', {'value':5}) >>>
The provided value(s) will be automatically coerced to the target type. If this is not possible then an Exception is raised/returned.
Unless the provided value is a dict, it is assumed to be a plain value and an attempt is made to store it in ‘.value’ field.
- monitor(name, cb, request=None, notify_disconnect=False, queue=None)[source]¶
Create a subscription.
- Parameters:
name (str) – PV name string
cb (callable) – Processing callback
request – A
p4p.Valueor string to qualify this request, or None to use a default.notify_disconnect (bool) – In additional to Values, the callback may also be call with instances of Exception. Specifically: Disconnected , RemoteError, or Cancelled
queue (WorkQueue) – A work queue through which monitor callbacks are dispatched.
- Returns:
a
Subscriptioninstance
The callable will be invoked with one argument which is either.
A p4p.Value (Subject to Automatic Value unwrapping)
A sub-class of Exception (Disconnected , RemoteError, or Cancelled)
- rpc(name, value, request=None, timeout=5.0, throw=True)[source]¶
Perform a Remote Procedure Call (RPC) operation
- Parameters:
name (str) – PV name string
value (Value) – Arguments. Must be Value instance
request – A
p4p.Valueor string to qualify this request, or None to use a default.timeout (float) – Operation timeout in seconds
throw (bool) – When true, operation error throws an exception. If False then the Exception is returned instead of the Value
- Returns:
A Value or Exception. Subject to Automatic Value unwrapping.
>>> ctxt = Context('pva') >>> ctxt.rpc('pv:name:add', {'A':5, 'B'; 6}) >>>
The provided value(s) will be automatically coerced to the target type. If this is not possible then an Exception is raised/returned.
Unless the provided value is a dict, it is assumed to be a plain value and an attempt is made to store it in ‘.value’ field.
- class p4p.client.thread.Subscription(ctxt, name, cb, notify_disconnect=False, queue=None)[source]¶
An active subscription.
Returned by
Context.monitor.
- class p4p.client.thread.Disconnected(msg=None)¶
Channel becomes disconected.
- class p4p.client.thread.RemoteError¶
Thrown with an error message which has been sent by a server to its remote client
- class p4p.client.thread.Cancelled(msg=None)¶
Cancelled from client end.
- class p4p.client.thread.Finished(msg=None)¶
Special case of Disconnected when a Subscription has received all updates it will ever receive.
- class p4p.client.thread.TimeoutError¶
Timeout expired.
asyncio Client¶
The asyncio client Context API is simllar to the thread Context, with the get, put, rpc methods become async.
- class p4p.client.asyncio.Context(provider='pva', conf=None, useenv=True, nt=None, unwrap=None)[source]¶
- Parameters:
provider (str) – A Provider name. Try “pva” or run
Context.providers()for a complete list.dict (conf) – Configuration to pass to provider. Depends on provider selected.
useenv (bool) – Allow the provider to use configuration from the process environment.
nt (dict) – Controls Automatic Value unwrapping. None uses defaults. Set False to disable
unwrap (dict) – Legacy Automatic Value unwrapping.
The methods of this Context will block the calling thread until completion or timeout
The meaning, and allowed keys, of the configuration dictionary depend on the provider.
The “pva” provider understands the following keys:
EPICS_PVA_ADDR_LIST
EPICS_PVA_AUTO_ADDR_LIST
EPICS_PVA_SERVER_PORT
EPICS_PVA_BROADCAST_PORT
Timeout and Cancellation¶
All coroutines/Futures returned by Context methods can be cancelled. The methods of Context do not directly implement a timeout. Instead
asyncio.wait_for()should be used. It is suggested perform one overall timeout at a high level rather than multiple timeouts on low-level operations.@timesout() async def dostuff(ctxt): await ctxt.put('msg', 'Working') A, B = await ctxt.get(['foo', 'bar']) await ctxt.put('bar', A+B, wait=True) await ctxt.put('msg', 'Done') async def exec(): with Context('pva') as ctxt: await dostuff(ctxt, timeout=5)
- name¶
- async get(name, request=None)[source]¶
Fetch current value of some number of PVs.
- Parameters:
name – A single name string or list of name strings
request – A
p4p.Valueor string to qualify this request, or None to use a default.
- Returns:
A p4p.Value, or list of same. Subject to Automatic Value unwrapping.
When invoked with a single name then returns is a single value. When invoked with a list of name, then returns a list of values.
with Context('pva') as ctxt: V = await ctxt.get('pv:name') A, B = await ctxt.get(['pv:1', 'pv:2'])
- async put(name, values, request=None, process=None, wait=None, get=True)[source]¶
Write a new value of some number of PVs.
- Parameters:
name – A single name string or list of name strings
values – A single value, a list of values, a dict, a
Value. May be modified by the constructor nt= argument.request – A
p4p.Valueor string to qualify this request, or None to use a default.process (str) – Control remote processing. May be ‘true’, ‘false’, ‘passive’, or None.
wait (bool) – Wait for all server processing to complete.
get (bool) – Whether to do a Get before the Put. If True then the value passed to the builder callable will be initialized with recent PV values. eg. use this with NTEnum to find the enumeration list.
When invoked with a single name then returns is a single value. When invoked with a list of name, then returns a list of values
If ‘wait’ or ‘process’ is specified, then ‘request’ must be omitted or None.
with Context('pva') as ctxt: await ctxt.put('pv:name', 5.0) await ctxt.put(['pv:1', 'pv:2'], [1.0, 2.0]) await ctxt.put('pv:name', {'value':5})
The provided value(s) will be automatically coerced to the target type. If this is not possible then an Exception is raised/returned.
Unless the provided value is a dict, it is assumed to be a plain value and an attempt is made to store it in ‘.value’ field.
- monitor(name, cb, request=None, notify_disconnect=False) Subscription[source]¶
Create a callback subscription.
- Parameters:
name (str) – PV name string
cb (callable) – Processing callback
request – A
p4p.Valueor string to qualify this request, or None to use a default.notify_disconnect (bool) – In additional to Values, the callback may also be called with instances of Exception. Specifically: Disconnected , RemoteError, or Cancelled
- Returns:
a
Subscriptioninstance
The callable will be invoked with one argument which is either.
A p4p.Value (Subject to Automatic Value unwrapping)
A sub-class of Exception (Disconnected , RemoteError, or Cancelled)
- async rpc(name, value, request=None)[source]¶
Perform a Remote Procedure Call (RPC) operation
- Parameters:
- Returns:
A Value. Subject to Automatic Value unwrapping.
For example:
uri = NTURI(['A','B']) with Context('pva') as ctxt: result = await ctxt.rpc('pv:name:add', uri.wrap('pv:name:add', 5, B=6))
The provided value(s) will be automatically coerced to the target type. If this is not possible then an Exception is raised/returned.
Unless the provided value is a dict or Value, it is assumed to be a plain value and an attempt is made to store it in ‘.value’ field.
Qt Client¶
p4p.client.Qt.Context exists to bring the results of network operations into a Qt event loop.
This is done through the native signals and slots mechanism.
Use requires the optional dependency qtpy package.
This dependency is expressed as an extras_require= of “qt”. It may be depended upon accordingly as “p4p[qt]”.
p4p.client.Qt.Context differs from the other Context classes in several respects.
Each Context attempts to minimize the number of subscriptions to each named PV. Multiple calls to monitor() will attempt to share this subscription if possible (subject to request argument).
All monitor() calls must express a desired maximum update rate limit through the limitHz argument.
As a convienence, the objects returned by put() and monitor() do not have to be stored by the caller. The internal references kept by the Context may be cleared through the disconnect() method. This cache extends to a single put and a single monitor subscription per PV. So eg. initiating a put() to a PV will implicitly cancel a previous in-progress put().
- class p4p.client.Qt.Context(provider, conf=None, useenv=True)[source]¶
PyQt aware Context. Methods in the class give notification of completion/update through Qt signals.
- Parameters:
provider (str) – A Provider name. Try “pva” or run
Context.providers()for a complete list.conf (dict) – Configuration to pass to provider. Depends on provider selected.
useenv (bool) – Allow the provider to use configuration from the process environment.
nt (dict) – Controls Automatic Value unwrapping. None uses defaults. Set False to disable
unwrap (dict) – Legacy Automatic Value unwrapping.
QObject (parent) – Parent for QObjects created through this Context.
- name¶
- put(name, value, slot=None, request=None, timeout=5.0, process=None, wait=None, get=True)[source]¶
Write a new value to a single PV.
Returns an Operation instance which will emit either a success and error signal. If the slot argument is provided, this will be connected in a race free way.
The slot function will receive a python object which is either None (Success) or an Exception.
Note that the returned Operation will also be stored internally by the Context. So the caller is not required to store it as well. This internal storage will only keep the most recent put() Operation for each PV name. A previous incomplete put() will be cancelled if/when put() is called again.
- Parameters:
name – A single name string or list of name strings
values – A single value, a list of values, a dict, a
Value. May be modified by the constructor nt= argument.request – A
p4p.Valueor string to qualify this request, or None to use a default.slot – A callable object, such as a bound method, which can be passed to QObject.connect()
timeout (float) – Operation timeout in seconds
process (str) – Control remote processing. May be ‘true’, ‘false’, ‘passive’, or None.
wait (bool) – Wait for all server processing to complete.
get (bool) – Whether to do a Get before the Put. If True then the value passed to the builder callable will be initialized with recent PV values. eg. use this with NTEnum to find the enumeration list.
- monitor(name, slot, request=None, limitHz=10.0)[source]¶
Request subscription to named PV
Request notification to the provided slot when a PV is updated. Subscriptions are managed by an internal cache, so than multiple calls to monitor() with the same PV name may be satisfied through a single subscription.
limitHz, which must be provided, puts an upper limit on the rate at which the update signal will be emitted. Some update will be dropped in the PV updates more frequently. Reduction is done by discarding the second to last update. eg. It is guaranteed that the last update (present value) in the burst will be delivered.
- Parameters:
name (str) – PV name string
cb (callable) – Processing callback
slot – A callable object, such as a bound method, which can be passed to QObject.connect()
request – A
p4p.Valueor string to qualify this request, or None to use a default.float (limitHz) – Maximum rate at which signals will be emitted. In signals per second.
- Returns:
a
MCacheinstance
- rpc(name, value, slot, request=None, timeout=5.0, throw=True)[source]¶
Perform a Remote Procedure Call (RPC) operation
Returns an Operation instance which will emit either a success and error signal to the provided slot. This Operation instance must be stored by the caller or it will be implicitly cancelled.
The slot function will receive a python object which is either a Value or an Exception.
- Parameters:
name (str) – PV name string
value (Value) – Arguments. Must be Value instance
slot – A callable object, such as a bound method, which can be passed to QObject.connect()
request – A
p4p.Valueor string to qualify this request, or None to use a default.timeout (float) – Operation timeout in seconds
throw (bool) – When true, operation error throws an exception. If False then the Exception is returned instead of the Value
- Returns:
An Operation