EPICS Controls Argonne National Laboratory

Experimental Physics and
Industrial Control System

1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  2014  2015  <20162017  2018  2019  2020  2021  2022  2023  2024  Index 1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  2014  2015  <20162017  2018  2019  2020  2021  2022  2023  2024 
<== Date ==> <== Thread ==>

Subject: Re: Is There A Way to Explicitly Close CA Connections in PyEpics?
From: Matt Newville <[email protected]>
To: Weiwei Lu <[email protected]>
Cc: tech-talk <[email protected]>
Date: Thu, 18 Aug 2016 13:04:41 -0500
Hi Weiwei,
On Thu, Aug 18, 2016 at 11:21 AM, Weiwei Lu <[email protected]> wrote:
>
> Hello,
>
> I am writing a Python (2.7.5) program and are using PyEpics in the program.  I wanted to explicitly close the CA connections after I created and used them, but found that once a CA connection was created, it stayed connected (the ioc server was up) until the program exited, and there seems to be no way to close it explicitly in the program.  I am new to the PyEpics and appreciate any help.


A couple of suggestions / meta-questions before answering your specific question:

First, Python 2.7.5 is slightly old (~3 years).  What version of pyepics are you using?

Second,  usually pyepics uses connection callbacks and so handles the ioc server going down and coming back without problem (that is, the PVs re-establish the connection).  I'm not sure it's really necessary to completely close the CA connections for particular PVs.  Why do you want to do this?

Pyepics tries hard to retain the connections for CA channels, including keeping connection callbacks,  and get callbacks in global state, and for each threading "context".    This is held in 'epics.ca._cache', a dictionary with keys that are the context (from ca.current_context()) and values that are also dictionaries, now keyed by channel name, with values that include several pieces of information, including pointers to connection callbacks (these are held globally so they cannot be garbage collected away).

> I tried epics.caget(); it created the CA connection and the connection stayed open until the program exited.


Yes, when any channel is created, it is entered into the epics.ca._cache.   This is generally useful as it means doing a caget() again does not establish a new connection, and may not even need to actually issue a request (as most of the time the PVs are monitored).   That is keeping "global state" about the connections to the individual channels.
 
>
> I tried pv = epics.PV() and then pv.disconnect(); the disconnect() method closed all the event monitors on the pv, but did not close the connection.


I'm not sure why that did not happen.  That definitely clears the cache, and tries to delete all references to all callbacks.  Perhaps it would be useful to try garbage collecting after disconnecting the PV:
    import gc
    gc.collect()

I'm not sure why (or how) that is different from the "ca" level approach below (except that it adds the magic needed to clear the cache and so not crash).
 
>
> I tried epics.ca.create_channel() and then epics.ca.clear_channel(); the clear_channel() indeed closed the CA connection.  But the problem with this approach is that the program would crash if I call epics.ca.create_channel() on the same pv again and try to get the state or value from the returned channel ID, as the following.
>
> >>> chid = epics.ca.create_channel('xxx')
> >>> epics.ca.clear_channel(chid)
> 1
> >>> chid = epics.ca.create_channel('xxx')
> >>> epics.ca.state(chid)
> (crash!)

Ah, yes, I think you need to clear the cache to do this.

    epics.ca.clear_channel(chid)
    ctx =epics.ca.current_context()
    epics.ca._cache[ctx].pop(pvname)

You can probably guess that not many people seem to need to do this.  But, it would certainly possible to add a convenience function (or perhaps even an on-by-default argument to ca.clear_channel()).

> Finally, calling epics.ca.destroy_context() and epics.ca.create_context() after epics.ca.clear_channel()
>  seems to allow a new connection to be created on the same pv, but that would also wipe out all the existing
> channels I want to keep.

Yes, that does clear the cache, but the entire entry for the context.

Hope that helps,

--Matt Newville

References:
Is There A Way to Explicitly Close CA Connections in PyEpics? Weiwei Lu

Navigate by Date:
Prev: Is There A Way to Explicitly Close CA Connections in PyEpics? Weiwei Lu
Next: Re: Michael Westfall
Index: 1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  2014  2015  <20162017  2018  2019  2020  2021  2022  2023  2024 
Navigate by Thread:
Prev: Is There A Way to Explicitly Close CA Connections in PyEpics? Weiwei Lu
Next: Re: Is There A Way to Explicitly Close CA Connections in PyEpics? Weiwei Lu
Index: 1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  2014  2015  <20162017  2018  2019  2020  2021  2022  2023  2024 
ANJ, 19 Aug 2016 Valid HTML 4.01! · Home · News · About · Base · Modules · Extensions · Distributions · Download ·
· Search · EPICS V4 · IRMIS · Talk · Bugs · Documents · Links · Licensing ·