pyvisa / pyvisa-py

A pure python PyVISA backend
https://pyvisa-py.readthedocs.io
MIT License
282 stars 120 forks source link

'Resource' object has no attribute 'write' #267

Closed BDuons closed 4 years ago

BDuons commented 4 years ago

Hi, I've just updated to the latest version of pyvisa and now get the following error:

Python 3.8.3 (tags/v3.8.3:6f8c832, May 13 2020, 22:37:02) [MSC v.1924 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import pyvisa
>>> rm = pyvisa.ResourceManager()
>>> rm.list_resources()
('ASRLCOM3::INSTR', 'ASRLCOM4::INSTR')
>>> my_instrument = rm.open_resource('ASRLCOM3::INSTR')
>>> print(my_instrument.query('*IDN?'))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'Resource' object has no attribute 'query'

I've noted this unusual output:

>>> print(my_instrument)
Resource at ASRLCOM3::INSTR

expected behaviour on readthedocs is along the lines of: <GPIBInstrument('GPIB::14')>

pyvisa-info PS C:\Users\mainuser\Documents\Python\sm1800> pyvisa-info Machine Details: Platform ID: Windows-10-10.0.19041-SP0 Processor: Intel64 Family 6 Model 142 Stepping 9, GenuineIntel

Python: Implementation: CPython Executable: c:\users\mainuser\appdata\local\programs\python\python38\python.exe Version: 3.8.3 Compiler: MSC v.1924 64 bit (AMD64) Bits: 64bit Build: May 13 2020 22:37:02 (#tags/v3.8.3:6f8c832) Unicode: UCS4

PyVISA Version: 1.11.0

Backends: ivi: Version: 1.11.0 (bundled with PyVISA) Binary library: Not found py: Version: 0.5.0 ASRL INSTR: Available via PySerial (3.4) USB INSTR: Please install PyUSB to use this resource type. No module named 'usb' USB RAW: Please install PyUSB to use this resource type. No module named 'usb' TCPIP INSTR: Available TCPIP SOCKET: Available GPIB INSTR: Please install linux-gpib (Linux) or gpib-ctypes (Windows, Linux) to use this resource type. Note that installing gpib-ctypes will give you access to a broader range of funcionality. No module named 'gpib'

MatthieuDartiailh commented 4 years ago

Your address format is invalid. For serial resources the proper format is simply ASRL4::INSTR. You do not need the COM.

BDuons commented 4 years ago

No dice, ASRL4::INSTR is not recognised as an instrument

Python 3.8.3 (tags/v3.8.3:6f8c832, May 13 2020, 22:37:02) [MSC v.1924 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import pyvisa
>>> rm = pyvisa.ResourceManager()
>>> rm.list_resources()
('ASRLCOM3::INSTR', 'ASRLCOM4::INSTR')
>>> my_instrument = rm.open_resource('ASRL4::INSTR')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Users\mainuser\AppData\Local\Programs\Python\Python38\lib\site-packages\pyvisa\highlevel.py", line 3294, in open_resource
    res.open(access_mode, open_timeout)
  File "C:\Users\mainuser\AppData\Local\Programs\Python\Python38\lib\site-packages\pyvisa\resources\resource.py", line 297, in open
    self.session, status = self._resource_manager.open_bare_resource(
  File "C:\Users\mainuser\AppData\Local\Programs\Python\Python38\lib\site-packages\pyvisa\highlevel.py", line 3222, in open_bare_resource
    return self.visalib.open(self.session, resource_name, access_mode, open_timeout)
  File "C:\Users\mainuser\AppData\Local\Programs\Python\Python38\lib\site-packages\pyvisa_py\highlevel.py", line 167, in open
    sess = cls(session, resource_name, parsed, open_timeout)
  File "C:\Users\mainuser\AppData\Local\Programs\Python\Python38\lib\site-packages\pyvisa_py\sessions.py", line 323, in __init__
    self.after_parsing()
  File "C:\Users\mainuser\AppData\Local\Programs\Python\Python38\lib\site-packages\pyvisa_py\serial.py", line 83, in after_parsing
    self.interface = cls(
  File "C:\Users\mainuser\AppData\Local\Programs\Python\Python38\lib\site-packages\serial\serialwin32.py", line 31, in __init__
    super(Serial, self).__init__(*args, **kwargs)
  File "C:\Users\mainuser\AppData\Local\Programs\Python\Python38\lib\site-packages\serial\serialutil.py", line 240, in __init__
    self.open()
  File "C:\Users\mainuser\AppData\Local\Programs\Python\Python38\lib\site-packages\serial\serialwin32.py", line 62, in open
    raise SerialException("could not open port {!r}: {!r}".format(self.portstr, ctypes.WinError()))
serial.serialutil.SerialException: could not open port '4': FileNotFoundError(2, 'The system cannot find the file specified.', None, 2)
IntegralWorks commented 4 years ago

Try

import pyvisa
rm = pyvisa.ResourceManager()
rm.list_resources()
('ASRLCOM3::INSTR', 'ASRLCOM4::INSTR')
inst = rm.list_resources()[0]
inst.query("*IDN?")

Or

import pyvisa
rm = pyvisa.ResourceManager()
inst = rm.list_resources()[0]
inst.query("*IDN?")
MatthieuDartiailh commented 4 years ago

@IntegralWorks this won't work since you just get addresses. This issue is actually something somebody else mentioned before and is specific to pyvisa-py on Windows. You can try the following:

import pyvisa
from pyvisa.resources.serial import SerialInstrument
rm = pyvisa.ResourceManager()
inst = rm.open_resource("ASRLCOM3::INSTR, resource_pyclass=SerialInstrument)

This will force pyvisa to give you a serial instrument.

I will try to move this issue to pyvisa-py later this week since it is where it belongs and may ask you to test a patch, once I have one (hopefully by Thursday).

IntegralWorks commented 4 years ago
C:\Users\someone\Desktop\zc\7.11\7.12\simulator\waveshare\utillities>python
Python 3.8.2 (tags/v3.8.2:7b3ab59, Feb 25 2020, 23:03:10) [MSC v.1916 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import pyvisa as visa
>>> rm = visa.ResourceManager()
>>> rm.list_resources()
('TCPIP0::169.254.8.227::inst0::INSTR', 'TCPIP0::169.254.7.101::inst0::INSTR', 'ASRL3::INSTR', 'ASRL10::INSTR')
>>> rm.list_resources()[0]
'TCPIP0::169.254.8.227::inst0::INSTR'
>>> rm.list_resources()[1]
'TCPIP0::169.254.7.101::inst0::INSTR'
>>> rm.list_resources()[2]
'ASRL3::INSTR'
>>> rm.list_resources()[3]
'ASRL10::INSTR'
>>> scopeA = rm.open(rm.list_resources()[0])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'ResourceManager' object has no attribute 'open'
>>> scopeA = rm.open_resource(rm.list_resources()[0])
>>> scopeB = rm.open_resource(rm.list_resources()[1])
>>> scopeA.query("*IDN?")
'TEKTRONIX,MDO3014,C047688,CF:91.1CT FV:v1.30\n'
>>> scopeB.query("*IDN?")
'TEKTRONIX,MDO3024,C046268,CF:91.1CT FV:v1.30\n'
>>>

Also I'd be glad to test a patch.

MatthieuDartiailh commented 4 years ago

To be able to test the patch you will need a windows machine running pyvisa-py. The issue is that pyserial report instruments on serial ports as "COM4" with gets mangled as ASRLCOM4::INSTR which is incorrect. We need a platform check to convert to and from COM4 <-> ASRL4::INSTR in pyvisa-py.

IntegralWorks commented 4 years ago

I unironically thought that was a feature, not a bug. For the longest time I've noticed a serial port is recognized as an instrument.

Every time I run

>>> rm.list_resources()
('TCPIP0::169.254.8.227::inst0::INSTR', 'TCPIP0::169.254.7.101::inst0::INSTR', 'ASRL3::INSTR', 'ASRL10::INSTR')

Those ASRL::INSTR are not instruments, they are just ports. I have a theory that "software-defined serial ports" (i.e. USB ports that are 'temporarily' made into serial ports through use of driver software) leave behind some kind of remnant code that PyVisa interprets as an instrument. This is really common for this kind of library because 99.99% of users will also be doing something like programming a microcontroller or FPGA. Since it's so common, most users probably think "oh, okay it's just some debugging quirk or whatever that my "software-defined serial ports" are pseudoinstruments".

MatthieuDartiailh commented 4 years ago

On windows it appears that all serial ports are reported by pyserial as COMX, while on other OS we just get the number. This makes pyvisa-py hard to use on windows for serial resources. This is usually not a big problem since Windows users have many options to install a VISA library for free, but still we should try to fix it.

IntegralWorks commented 4 years ago

Do you know what parts of the code are related to this? I'm new to open source but I want to make contributions.

MatthieuDartiailh commented 4 years ago

I would start by having a look at https://github.com/pyvisa/pyvisa-py/blob/master/pyvisa_py/serial.py#L69 (where you would need to cleanup the output of pyserial) and https://github.com/pyvisa/pyvisa-py/blob/master/pyvisa_py/serial.py#L84 (where we need to add back COM to the port I assume, but I do not have a system to test).

IntegralWorks commented 4 years ago

To be clear, we need to:

Another question: if we have a Serial device connected as USB. Should we consider that a Serial device or a USB device? Because a lot of my stuff at work uses Serial protocol over USB.

MatthieuDartiailh commented 4 years ago

We seem to have small misunderstanding here.

There is no way I am aware off to discriminate between serial port with or without a connection (nothing in the VISA standard helps here), and tools like NI-MAX will report all available serial ports. I don't see much value trying to outsmart them in PyVISA-py.

The issue is that went listing available ports pyserial return ["COM1", "COM4"] on windows and ["1", "4"] on other platform leading to invalid VISA addresses like ASRLCOM4::INSTR instead of ASRL4::INSTR. We just need to clean the names returned by pyserial and add back the COM I assume when opening again (but they may not even be necessary).

Instrument implementing serial over USB are seen as simply serial by VISA, and should be properly reported by pyserial I assume.

BDuons commented 4 years ago

The resource_pyclass=SerialInstrument trick doesn't seem to work for me. I've checked with both devices that I have. I did note that our HP34401 did beep, so something is happening. The result of printing the instrument looks a bit better as well: SerialInstrument at ASRLCOM3::INSTR

Just a suggestion for determining which serial ports have instruments, I iterate over all ports sending *IDN? and reading the replies to determine what ports everything is on. Probably not safe but it does the job.

>>> import pyvisa
>>> from pyvisa.resources.serial import SerialInstrument
>>> rm = pyvisa.ResourceManager()
>>> rm.list_resources()
('ASRLCOM3::INSTR', 'ASRLCOM4::INSTR')
>>> inst = rm.open_resource('ASRLCOM3::INSTR', resource_pyclass=SerialInstrument)
>>> print(inst.query('*IDN?'))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Users\mainuser\AppData\Local\Programs\Python\Python38\lib\site-packages\pyvisa\resources\messagebased.py", line 644, in query
    return self.read()
  File "C:\Users\mainuser\AppData\Local\Programs\Python\Python38\lib\site-packages\pyvisa\resources\messagebased.py", line 486, in read
    message = self._read_raw().decode(enco)
  File "C:\Users\mainuser\AppData\Local\Programs\Python\Python38\lib\site-packages\pyvisa\resources\messagebased.py", line 442, in _read_raw
    chunk, status = self.visalib.read(self.session, size)
  File "C:\Users\mainuser\AppData\Local\Programs\Python\Python38\lib\site-packages\pyvisa_py\highlevel.py", line 519, in read
    return data, self.handle_return_value(session, status_code)
  File "C:\Users\mainuser\AppData\Local\Programs\Python\Python38\lib\site-packages\pyvisa\highlevel.py", line 249, in handle_return_value
    raise errors.VisaIOError(rv)
pyvisa.errors.VisaIOError: VI_ERROR_TMO (-1073807339): Timeout expired before operation completed.
BDuons commented 4 years ago

Is there a good way of linking this issue to pyvisa-py? I'm happy to generate a new issue over there if necessary

MatthieuDartiailh commented 4 years ago

I transferred the issue @BDuons. The new error you are seeing can come from many different things including improperly configured termination characters, or improper serial parameters (baud_rate etc). Please have a look at https://pyvisa.readthedocs.io/en/latest/introduction/communication.html to get it right.

Note that not all instrument supports *IDN? and furthermore they may require different configuration and as a consequence this is far from a reliable method.

MatthieuDartiailh commented 4 years ago

I created #269 that should address that issue. If anybody that can check it works on a windows it would be great.

MatthieuDartiailh commented 4 years ago

Also note that with https://github.com/pyvisa/pyvisa/pull/547 in, you should not need to specify the resource class anymore.

greyltc commented 4 years ago

Also note that with pyvisa/pyvisa#547 in, you should not need to specify the resource class anymore.

When can we expect this is in a stable release? This bug broke all my stuff.

MatthieuDartiailh commented 4 years ago

I imagine and I am sorry about that. I am planning to release the bugfix next Wednesday and if people manage to test #269 before then I will also make a pyvisa-py release.

greyltc commented 4 years ago

Cool, thanks!