Open dougthor42 opened 1 year ago
Sorry for the delay but I think we have no such thing. You may be able to use CLS to achieve something similar but we could also envision adding a custom method.
No worries! After all, I still haven't addressed https://github.com/pyvisa/pyvisa-py/issues/374 lol
I assume that, at it's core, pyvisa-sim
is a glorified dictionary where "queries" are the keys and "responses" are the values. It seems like we should just be able to empty that dictionary to reset things. Am I on the right track there?
Where is this dictionary-like data structure defined? I'd imagine that a custom method on the Resource Manager or perhaps the individual Resource is probably easy to implement.
Closing the [...] resource manager does not reset things (this might be related to #82).
Are you sure? I just tripped on this/#82 again, and closing the resource manager so far seems sufficient to clean up hidden state.
TLDR: calling resource_manager.visalib._init()
will reset all devices loaded from the same yaml file.
I spent a bit of time debugging why this happens. As far as I can see the state is kept in the Device class The device class is in turn stored as a member of the Devices class which is in turn kept in the SimVisaLibrary. SimVisaLibrary is a subclass of VisaLibraryBase which in turn implements a registry of loaded libraries here Which means that if a SimVisaLibrary for a given yaml path exists, it will be reused next time you load SimVisaLibrary for that yaml path.
As the Device is loaded via
_init only when SimVisaLibrary is created this in turn means that the device state is kept as long as an instance of SimVisaLibrary is kept alive. One can force a reload from disk by calling the private method _init
on the SimVisaLibrary class bound to a resource manager. Probably via resource_manager.visalib as resource_manager.visalib._init()
I did not trace all objects that keep a reference to the visa library but it could be that the resource_manager is the only object that does this so closing the resource manager would under some circumstances trigger the visalib to be garbage collected explaining the observations above (the mentioned registry in VisaLibraryBase is a WeakValueDict so it does it self add to the refcount)
Thanks for investigating this @jenshnielsen
Since it seems a needed feature, I would welcome a PR in that direction.
Is there a function/method that will reset a simulated instrument to the defaults defined in the yaml file?
What I'd like to be able to do is basically:
Does such a method exist? Closing the resource and/or the resource manager does not reset things (this might be related to #82).
Steps to Reproduce
Create this YAML file. I called it "doug_example.yaml":
```yaml --- spec: "1.1" devices: MyDevice: eom: ASRL INSTR: q: "\r" r: "\r\n" error: response: command_error: "invalid command. Update the yaml file." query_error: "empty buffer" dialogues: - q: ";LC:DONE?" r: "done" properties: echo: default: "0" setter: q: "echo {}" r: "OK" getter: q: "echo?" r: "{}" resources: "ASRL1::INSTR": device: "MyDevice" ```Create this Python file. I called it "doug_example.py":
```python import pathlib import pyvisa VISA_ADDR = "ASRL1::INSTR" SIM_BACKEND = str(pathlib.Path(__file__).parent / "doug_example.yaml@sim") def create_instr() -> tuple[pyvisa.ResourceManager, pyvisa.Resource]: rm = pyvisa.ResourceManager(visa_library=SIM_BACKEND) instr = rm.open_resource(VISA_ADDR) instr.read_termination = "\r\n" instr.write_termination = "\r" print(f"ResourceManager session: {rm.session}") return rm, instr rm, instr = create_instr() want = "0" got = instr.query("echo?") correct = got == want print(f"{got = }\t{want = }\t{correct = }") want = "OK" got = instr.query("echo 1") correct = got == want print(f"{got = }\t{want = }\t{correct = }") want = "1" got = instr.query("echo?") correct = got == want print(f"{got = }\t{want = }\t{correct = }") # Magic reset command print("Running reset") rm.close() print("Creating new resource manager and instrument") rm, instr = create_instr() want = "0" got = instr.query("echo?") correct = got == want print(f"{got = }\t{want = }\t{correct = }") ```Run
python doug_example.py
and get this output: