Experimental Physics and
| |||||||||||||||||
|
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. --Matt Newville
| ||||||||||||||||
ANJ, 19 Aug 2016 |
·
Home
·
News
·
About
·
Base
·
Modules
·
Extensions
·
Distributions
·
Download
·
· Search · EPICS V4 · IRMIS · Talk · Bugs · Documents · Links · Licensing · |