Hi Matt,
Many thanks for the suggestions.
> What version of pyepics are you using?
I think I am using pyepics-3.2.1, but not 100% sure. Is there a command that can tell which version I am using?
> Why do you want to do this?
Well, just wanted to make the program more ioc friendly. Closing the unused connections releases the resources (file descriptors, memory) of the iocs. My program is a daemon program. If it does not close the connections it has opened and are no longer needed, those connections will remain open forever. Also how about the unresolved pv searches; will my program keeps searching those unresolved pvs forever if it does not close them explicitly? So I think by closing the unused or unresolved pvs, these problems can be avoided.
> import gc
> gc.collect()
Calling gc.collect() after executing pv = None, the connection remained open. So this does not work.
> epics.ca.clear_channel(chid)
> ctx =epics.ca.current_context()
> epics.ca._cache[ctx].pop(pvname)
Yes, this works! This clears the connection and also allows re-creation of a channel on the same pv.
Cheers,
William
----- Original Message -----
From: "Matt Newville" <[email protected]>
To: "weiwei" <[email protected]>
Cc: "tech-talk" <[email protected]>
Sent: Thursday, August 18, 2016 2:04:41 PM
Subject: Re: Is There A Way to Explicitly Close CA Connections in PyEpics?
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
- Replies:
- Re: Is There A Way to Explicitly Close CA Connections in PyEpics? Matt Newville
- References:
- Is There A Way to Explicitly Close CA Connections in PyEpics? Weiwei Lu
- Re: Is There A Way to Explicitly Close CA Connections in PyEpics? Matt Newville
- Navigate by Date:
- Prev:
RE: CARS:Modbus - function 06 (write single register) issue Nick Levchenko
- Next:
Re: MEDM 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
<2016>
2017
2018
2019
2020
2021
2022
2023
2024
- Navigate by Thread:
- Prev:
Re: Is There A Way to Explicitly Close CA Connections in PyEpics? Matt Newville
- Next:
Re: Is There A Way to Explicitly Close CA Connections in PyEpics? Matt Newville
- Index:
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
<2016>
2017
2018
2019
2020
2021
2022
2023
2024
|