55from collections .abc import Sequence
66from importlib .resources import as_file , files
77from typing import Any
8+ from weakref import finalize
89
910import pyvisa
1011import pyvisa .constants as vi_const
2223log = logging .getLogger (__name__ )
2324
2425
26+ def _close_visa_handle (
27+ handle : pyvisa .resources .MessageBasedResource , name : str
28+ ) -> None :
29+ log .info (
30+ "Closing VISA handle to %s as there are no non weak "
31+ "references to the instrument." ,
32+ name ,
33+ )
34+ handle .close ()
35+
2536class VisaInstrument (Instrument ):
2637
2738 """
@@ -100,17 +111,26 @@ def __init__(
100111 f"file { pyvisa_sim_file } from module: { module } "
101112 )
102113 visalib = f"{ str (sim_visalib_path )} @sim"
103- visa_handle , visabackend = self ._connect_and_handle_error (
104- address , visalib
105- )
114+ (
115+ visa_handle ,
116+ visabackend ,
117+ resource_manager ,
118+ ) = self ._connect_and_handle_error (address , visalib )
106119 else :
107- visa_handle , visabackend = self ._connect_and_handle_error (address , visalib )
120+ visa_handle , visabackend , resource_manager = self ._connect_and_handle_error (
121+ address , visalib
122+ )
123+ finalize (self , _close_visa_handle , visa_handle , str (self .name ))
108124
109125 self .visabackend : str = visabackend
110126 self .visa_handle : pyvisa .resources .MessageBasedResource = visa_handle
111127 """
112128 The VISA resource used by this instrument.
113129 """
130+ self .resource_manager = resource_manager
131+ """
132+ The VISA resource manager used by this instrument.
133+ """
114134 self .visalib : str | None = visalib
115135 self ._address = address
116136
@@ -122,18 +142,20 @@ def __init__(
122142
123143 def _connect_and_handle_error (
124144 self , address : str , visalib : str | None
125- ) -> tuple [pyvisa .resources .MessageBasedResource , str ]:
145+ ) -> tuple [pyvisa .resources .MessageBasedResource , str , pyvisa . ResourceManager ]:
126146 try :
127- visa_handle , visabackend = self ._open_resource (address , visalib )
147+ visa_handle , visabackend , resource_manager = self ._open_resource (
148+ address , visalib
149+ )
128150 except Exception as e :
129151 self .visa_log .exception (f"Could not connect at { address } " )
130152 self .close ()
131153 raise e
132- return visa_handle , visabackend
154+ return visa_handle , visabackend , resource_manager
133155
134156 def _open_resource (
135157 self , address : str , visalib : str | None
136- ) -> tuple [pyvisa .resources .MessageBasedResource , str ]:
158+ ) -> tuple [pyvisa .resources .MessageBasedResource , str , pyvisa . ResourceManager ]:
137159
138160 # in case we're changing the address - close the old handle first
139161 if getattr (self , "visa_handle" , None ):
@@ -156,7 +178,7 @@ def _open_resource(
156178 resource .close ()
157179 raise TypeError ("QCoDeS only support MessageBasedResource Visa resources" )
158180
159- return resource , visabackend
181+ return resource , visabackend , resource_manager
160182
161183 def set_address (self , address : str ) -> None :
162184 """
@@ -168,10 +190,13 @@ def set_address(self, address: str) -> None:
168190 change the backend for VISA, use the self.visalib attribute
169191 (and then call this function).
170192 """
171- resource , visabackend = self ._open_resource (address , self .visalib )
193+ resource , visabackend , resource_manager = self ._open_resource (
194+ address , self .visalib
195+ )
172196 self .visa_handle = resource
173197 self ._address = address
174198 self .visabackend = visabackend
199+ self .resource_manager = resource_manager
175200
176201 def device_clear (self ) -> None :
177202 """Clear the buffers of the device"""
@@ -231,6 +256,13 @@ def close(self) -> None:
231256 """Disconnect and irreversibly tear down the instrument."""
232257 if getattr (self , 'visa_handle' , None ):
233258 self .visa_handle .close ()
259+
260+ if getattr (self , "visabackend" , None ) == "sim" and getattr (
261+ self , "resource_manager" , None
262+ ):
263+ # work around for https://github.com/QCoDeS/Qcodes/issues/5356 and
264+ # https://github.com/pyvisa/pyvisa-sim/issues/82
265+ self .resource_manager .close ()
234266 super ().close ()
235267
236268 def write_raw (self , cmd : str ) -> None :
0 commit comments