python-microscope / microscope

Python library for control of microscope devices, supporting hardware triggers and distribution of devices over the network for performance and flexibility.
https://www.python-microscope.org
GNU General Public License v3.0
73 stars 42 forks source link

TOPAS iBeam smart serial error #232

Closed jacopoabramo closed 2 years ago

jacopoabramo commented 2 years ago

Greetings,

I'm currently trying to integrate the TOPAS iBeam smart laser into ImSwitch, and to do so I wanted to try and take advantage of python microscope. I get an error when trying to test the laser with a small example as follows:

from microscope.lights.toptica import TopticaiBeam

laser = TopticaiBeam("COM3")

laser.enable()
laser.power = 15.0
print("Press any key to stop...")
input()
laser.power = 0
laser.disable()

The error is the following:

Traceback (most recent call last):
  File "C:\git\sandbox\sandbox.py", line 1, in <module>
    from microscope.lights.toptica import TopticaiBeam
  File "C:\Users\iScat_Lab\AppData\Local\Programs\Python\Python39\lib\site-packages\microscope\lights\toptica.py", line 27, in <module>
    import microscope._utils
  File "C:\Users\iScat_Lab\AppData\Local\Programs\Python\Python39\lib\site-packages\microscope\_utils.py", line 94, in <module>        
    class SharedSerial:
  File "C:\Users\iScat_Lab\AppData\Local\Programs\Python\Python39\lib\site-packages\microscope\_utils.py", line 97, in SharedSerial    
    def __init__(self, serial: serial.Serial) -> None:
AttributeError: module 'serial' has no attribute 'Serial'

I'm working with this setup:

OS: Windows 10 Python: 3.9.7 Device:

Let me know if more information is needed.

carandraug commented 2 years ago

This is very interesting. You have the serial module but that module does not have the Serial class. We expect the serial module/package to come from the pySerial package/distribution. I wonder if you have any package/distribution in the path that could be shadowing it.

What do you get when you run this?

import serial
print(serial.__file__)
dir(serial)

We expect something like:

>>> import serial
>>> serial.__file__
'/usr/lib/python3/dist-packages/serial/__init__.py'
>>> dir(serial)
['CR', 'EIGHTBITS', 'FIVEBITS', 'LF', 'PARITY_EVEN', 'PARITY_MARK', 'PARITY_NAMES', 'PARITY_NONE', 'PARITY_ODD', 'PARITY_SPACE', 'PosixPollSerial', 'SEVENBITS', 'SIXBITS', 'STOPBITS_ONE', 'STOPBITS_ONE_POINT_FIVE', 'STOPBITS_TWO', 'Serial', 'SerialBase', 'SerialException', 'SerialTimeoutException', 'Timeout', 'VERSION', 'VTIMESerial', 'XOFF', 'XON', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__path__', '__spec__', '__version__', 'basestring', 'importlib', 'io', 'iterbytes', 'os', 'portNotOpenError', 'protocol_handler_packages', 'serial_for_url', 'serialposix', 'serialutil', 'sys', 'time', 'to_bytes', 'unicode', 'writeTimeoutError']
jacopoabramo commented 2 years ago

Hi @carandraug , thanks for your reply.

This is what I get as output:

['abc', 'absolute_import', 'division', 'errors', 'generators', 'hooks', 'marshal', 'meta', 'model', 'nested_scopes', 'print_function', 'properties', 'request', 'test', 'unicode_literals', 'utilities', 'with_statement']

I uninstalled this serial package and tried to uninstall and reinstall microscope but I get the same thing as a result.

carandraug commented 2 years ago

The following message can be a bit confusing because in Python the word "package" is often used for different things. From the Python packaging glossary itself:

An import package is more commonly referred to with the single word “package”, but this guide will use the expanded term when more clarity is needed to prevent confusion with a Distribution Package which is also commonly called a “package”.

To making things clearer, I'll use the term "distribution package" (the thing in PyPI) and "import package" (the module that you import)


The issue is that both "distribution packages" serial and pyserial install an "import package" named serial.

Microscope lists the distribution package pyserial as requirement and I'm guessing you do have it installed (you didn't specify how you're installing Microscope --- can you clarify?). However, the import package you're getting is the one from the distribution package serial. My guess is that you either have both installed (but the distribution package serial comes before pyserial).

Can you please show the output for these:

  1. How are you installing microscope?
  2. How did you uninstall the distribution package serial?
  3. Are you sure you have the distribution package pyserial installed?
jacopoabramo commented 2 years ago

I apologize for the unclear information so far.

  1. I'm installing microscope through pypi as pip install microscope
  2. I uninstalled the distribution package serial through pip uninstall serial
  3. I just checked if the pyserial distribution package was installed and it was.

I don't know exactly how the issue solved itself but now it seems that I have the correct distribution package installed. I must have mixed up some installations through pypi somehow.

I ran again the code snippet I showed above, and now instead I get the following error:

Traceback (most recent call last):
  File "C:\git\sandbox\sandbox.py", line 3, in <module>
    laser = TopticaiBeam("COM3")
  File "C:\Users\iScat_Lab\AppData\Local\Programs\Python\Python39\lib\site-packages\microscope\lights\toptica.py", line 218, in __init__
    self._conn = _iBeamConnection(port)
  File "C:\Users\iScat_Lab\AppData\Local\Programs\Python\Python39\lib\site-packages\microscope\lights\toptica.py", line 101, in __init__
    self.command(b"")
  File "C:\Users\iScat_Lab\AppData\Local\Programs\Python\Python39\lib\site-packages\microscope\lights\toptica.py", line 131, in command
    answer = self._serial.read_until(b"\r\n[OK]\r\n")
  File "C:\Users\iScat_Lab\AppData\Local\Programs\Python\Python39\lib\site-packages\microscope\_utils.py", line 117, in read_until
    return self._serial.read_until(terminator=terminator, size=size)
TypeError: read_until() got an unexpected keyword argument 'terminator'
Exception in disable() during shutdown: 'TopticaiBeam' object has no attribute '_conn'
carandraug commented 2 years ago

I ran again the code snippet I showed above, and now instead I get the following error: [...]

This is a different issue so I have opened #233 for it.


Back to the original issue of "no attribute Serial" and pySerial vs serial distribution packages:

Not much we can do about this. There's nothing stopping different distribution packages to provide the different imported packages under the same name. I have added a check to microscope._utils, after importing serial, to check that it has the Serial class and provide a better error message if not. Closing as fixed.