labscript-suite / labscript-utils

Shared modules used by the 𝘭𝘢𝘣𝘴𝘤𝘳𝘪𝘱𝘵 𝘴𝘶𝘪𝘵𝘦. Includes a graphical exception handler, debug tools, configuration management, cross platform filepath conversions, unit conversions and custom GUI widgets.
http://labscriptsuite.org
Other
2 stars 47 forks source link

When I'm trying to use FlyCapture2Camera,double import error in blacs. #87

Open Moriaty-TT opened 2 years ago

Moriaty-TT commented 2 years ago

The error is

Exception in worker - Thu May 12, 22:08:08 :
Traceback (most recent call last):
  File "c:\labscript\lib\site-packages\labscript_devices\IMAQdxCamera\blacs_workers.py", line 251, in init
    self.camera = self.get_camera()
RuntimeError: Double import! The same file has been imported under two different names, resulting in two copies of the module. This is almost certainly a mistake. If you are running a script from within a package and want to import another submodule of that package, import it by its full path: 'import module.submodule' instead of just 'import submodule.'

Path imported: C:\Users\Administrator\namespace

Traceback (first time imported, as user_devices):
------------
  File "C:\Python36\lib\runpy.py", line 193, in _run_module_as_main
    "__main__", mod_spec)
  File "C:\Python36\lib\runpy.py", line 85, in _run_code
    exec(code, run_globals)
  File "c:\labscript\lib\site-packages\zprocess\process_class_wrapper.py", line 86, in <module>
    _setup()
  File "c:\labscript\lib\site-packages\zprocess\process_class_wrapper.py", line 70, in _setup
    module = importlib.import_module(module_name)
  File "C:\Python36\lib\importlib\__init__.py", line 126, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "c:\labscript\lib\site-packages\labscript_devices\__init__.py", line 7, in <module>
    from labscript_utils.device_registry import *
  File "c:\labscript\lib\site-packages\labscript_utils\device_registry\__init__.py", line 1, in <module>
    from ._device_registry import *
  File "c:\labscript\lib\site-packages\labscript_utils\device_registry\_device_registry.py", line 84, in <module>
    LABSCRIPT_DEVICES_DIRS = _get_device_dirs()
  File "c:\labscript\lib\site-packages\labscript_utils\device_registry\_device_registry.py", line 81, in _get_device_dirs
    return _get_import_paths(['labscript_devices'] + user_devices)
  File "c:\labscript\lib\site-packages\labscript_utils\device_registry\_device_registry.py", line 66, in _get_import_paths
    spec = importlib.util.find_spec(name)
  File "C:\Python36\lib\importlib\util.py", line 91, in find_spec
    return _find_spec(fullname, None)
------------

Traceback (second time imported, as PyCapture2):
------------
  File "C:\Python36\lib\runpy.py", line 193, in _run_module_as_main
    "__main__", mod_spec)
  File "C:\Python36\lib\runpy.py", line 85, in _run_code
    exec(code, run_globals)
  File "c:\labscript\lib\site-packages\zprocess\process_class_wrapper.py", line 86, in <module>
    _setup()
  File "c:\labscript\lib\site-packages\zprocess\process_class_wrapper.py", line 83, in _setup
    instance._run()
  File "c:\labscript\lib\site-packages\zprocess\process_tree.py", line 1540, in _run
    _Process._run(self)
  File "c:\labscript\lib\site-packages\zprocess\process_tree.py", line 1121, in _run
    self.run(*args, **kwargs)
  File "c:\labscript\lib\site-packages\blacs\tab_base_classes.py", line 891, in run
    self.mainloop()
  File "c:\labscript\lib\site-packages\blacs\tab_base_classes.py", line 923, in mainloop
    results = func(*args,**kwargs)
  File "c:\labscript\lib\site-packages\labscript_devices\IMAQdxCamera\blacs_workers.py", line 251, in init
    self.camera = self.get_camera()
  File "c:\labscript\lib\site-packages\labscript_devices\IMAQdxCamera\blacs_workers.py", line 280, in get_camera
    return self.interface_class(self.serial_number)
  File "c:\labscript\lib\site-packages\labscript_devices\FlyCapture2Camera\blacs_workers.py", line 70, in __init__
    import PyCapture2
------------

Fatal exception in main process - Thu May 12, 22:08:08 :
 Traceback (most recent call last):
  File "c:\labscript\lib\site-packages\blacs\tab_base_classes.py", line 837, in mainloop
    next_yield = inmain(generator.send,results)
  File "c:\labscript\lib\site-packages\qtutils\invoke_in_main.py", line 88, in inmain
    return get_inmain_result(_in_main_later(fn, False, *args, **kwargs))
  File "c:\labscript\lib\site-packages\qtutils\invoke_in_main.py", line 150, in get_inmain_result
    raise value.with_traceback(traceback)
  File "c:\labscript\lib\site-packages\qtutils\invoke_in_main.py", line 46, in event
    result = event.fn(*event.args, **event.kwargs)
  File "c:\labscript\lib\site-packages\blacs\tab_base_classes.py", line 536, in _initialise_worker
    raise Exception('Device failed to initialise')
Exception: Device failed to initialise

@chrisjbillington @philipstarkey

chrisjbillington commented 2 years ago

Thanks for the report.

By any chance have you configured user_devices in your labconfig file, to point to the PyCapture2 module? If so, that is likely the cause of the problem.

Moriaty-TT commented 2 years ago

Thanks for the report.

By any chance have you configured user_devices in your labconfig file, to point to the PyCapture2 module? If so, that is likely the cause of the problem.

I didn't change other configurations in labconfig except apparatus_name. Here is part of my labconfig: user_devices = user_devices

Is it possible that my connection_table caused it? Here is my experiment connection_table:

from labscript import start,stop,add_time_marker, Trigger,DigitalOut
from labscript_devices.FlyCapture2Camera.labscript_devices import FlyCapture2Camera
from labscript_devices.NI_DAQmx.labscript_devices import NI_PXIe_6535
from labscript_devices.PrawnBlaster.labscript_devices import PrawnBlaster

PrawnBlaster(name='prawn', com_port='COM3',num_pseudoclocks=1)
NI_PXIe_6535(name='Dev1',MAX_name='Dev1',parent_device=prawn.clocklines[0],clock_terminal='/Dev1/PFI4')

DigitalOut(name='TmpTTL', parent_device=Dev1, connection='port0/line0')
Trigger(name='camera_trigger', parent_device=Dev1, connection='port1/line0')

FlyCapture2Camera('camera',camera_trigger,'trigger',serial_number='18427513',orientation='test')

if __name__=='__main__':
    start()
    stop(1.0)

It's for a test of camera connection to labscripts.

Moriaty-TT commented 2 years ago

By the way I want to konw What does python wrapper mean in https://github.com/labscript-suite/labscript-devices/blob/75b175d44c1fdca55b7cae30a898bbea59c2a5d7/docs/source/devices/flycapture2.rst#id1 . Is this error related to the FlyCapture2 SDK and python wrapper?

dihm commented 2 years ago

Python wrapper refers to the fact that the FlyCapture2 SDK (which controls the camera) is a C library, and the PyCapture2 python package is a wrapper around that library that allows us to use it from python.

The double import error occurs when the same python module is imported using two different names. Somehow PyCapture2 and user_devices names are being assigned to the same imported module. This is a sign something very unusual (and bad) is going on under the hood. I'll find sometime in the next few days to try compiling your script on my test rig to see if I can reproduce.

In the meantime, can you say something about where your labscript suite modules are installed? In particular, what actually resides in the user_devices folder (which lives in the labscript_suite userlib folder that is also defined in the config file)? Also, where does the FlyCapture2Camera code live (ie what folder is it in)?

Moriaty-TT commented 2 years ago

In the meantime, can you say something about where your labscript suite modules are installed? In particular, what actually resides in the user_devices folder (which lives in the labscript_suite userlib folder that is also defined in the config file)? Also, where does the FlyCapture2Camera code live (ie what folder is it in)?

@dihm Thanks for your reply. This is the path of my labscript suite: C:\Users\Administrator\labscript-suite

The contents of the user_devices folder are shown in the figure image The path of the FlyCapture2Camera code is: C:\labscript\Lib\site-packages\labscript_devices\FlyCapture2Camera

What's more,this is my labconfig setting:

 apparatus_name = camera_test
shared_drive = C:
experiment_shot_storage = %(shared_drive)s\Experiments\%(apparatus_name)s
userlib = %(labscript_suite)s\userlib
pythonlib = %(userlib)s\pythonlib
labscriptlib = %(userlib)s\labscriptlib\%(apparatus_name)s
analysislib = %(userlib)s\analysislib\%(apparatus_name)s
app_saved_configs = %(labscript_suite)s\app_saved_configs\%(apparatus_name)s
user_devices = user_devices

Thank you for taking the time to help me solve the problem。

dihm commented 2 years ago

Ah, I think I see the issue. PyCapture2 should not be installed into user_devices. That folder is strictly for labscript code (like the FlyCapture2Camera). The FlyCapture2 SDK and the PyCapture2 wrapper should be installed somewhere else. If I remember correctly, the SDK location needs to be added to the system path, and the PyCapture2 SDK should default install itself into the site-packages of the python environment you point it to during installation.

Not that it is hugely important, but if you are interested, the problem here is that labscript automatically adds python packages in user_devices to the labscript import search path (via the device_registry in labscript-utils). When you try to import PyCapture2 directly, it is done via a relative import of the standard python path. The result is that you have imported the same module in two different places using two different names, which triggers the double import denier.

Moriaty-TT commented 2 years ago

I have reconfirmed that we didn't have anything in the user_devices folder at first, and the problem of double import also occurred at that time. Now, after I clear the contents of this folder, this error still exists.Maybe there is no problem with the installation path of SDK and wrapper. Here is the latest error report

Exception in worker - Tue May 24, 09:35:53 :
Traceback (most recent call last):
  File "c:\labscript\lib\site-packages\labscript_devices\IMAQdxCamera\blacs_workers.py", line 251, in init
    self.camera = self.get_camera()
RuntimeError: Double import! The same file has been imported under two different names, resulting in two copies of the module. This is almost certainly a mistake. If you are running a script from within a package and want to import another submodule of that package, import it by its full path: 'import module.submodule' instead of just 'import submodule.'

Path imported: C:\Users\Administrator\namespace

Traceback (first time imported, as user_devices):
------------
  File "C:\Python36\Lib\runpy.py", line 193, in _run_module_as_main
    "__main__", mod_spec)
  File "C:\Python36\Lib\runpy.py", line 85, in _run_code
    exec(code, run_globals)
  File "c:\labscript\lib\site-packages\zprocess\process_class_wrapper.py", line 86, in <module>
    _setup()
  File "c:\labscript\lib\site-packages\zprocess\process_class_wrapper.py", line 70, in _setup
    module = importlib.import_module(module_name)
  File "C:\Python36\Lib\importlib\__init__.py", line 126, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "c:\labscript\lib\site-packages\labscript_devices\__init__.py", line 7, in <module>
    from labscript_utils.device_registry import *
  File "c:\labscript\lib\site-packages\labscript_utils\device_registry\__init__.py", line 1, in <module>
    from ._device_registry import *
  File "c:\labscript\lib\site-packages\labscript_utils\device_registry\_device_registry.py", line 84, in <module>
    LABSCRIPT_DEVICES_DIRS = _get_device_dirs()
  File "c:\labscript\lib\site-packages\labscript_utils\device_registry\_device_registry.py", line 81, in _get_device_dirs
    return _get_import_paths(['labscript_devices'] + user_devices)
  File "c:\labscript\lib\site-packages\labscript_utils\device_registry\_device_registry.py", line 66, in _get_import_paths
    spec = importlib.util.find_spec(name)
  File "C:\Python36\Lib\importlib\util.py", line 91, in find_spec
    return _find_spec(fullname, None)
------------

Traceback (second time imported, as PyCapture2):
------------
  File "C:\Python36\Lib\runpy.py", line 193, in _run_module_as_main
    "__main__", mod_spec)
  File "C:\Python36\Lib\runpy.py", line 85, in _run_code
    exec(code, run_globals)
  File "c:\labscript\lib\site-packages\zprocess\process_class_wrapper.py", line 86, in <module>
    _setup()
  File "c:\labscript\lib\site-packages\zprocess\process_class_wrapper.py", line 83, in _setup
    instance._run()
  File "c:\labscript\lib\site-packages\zprocess\process_tree.py", line 1540, in _run
    _Process._run(self)
  File "c:\labscript\lib\site-packages\zprocess\process_tree.py", line 1121, in _run
    self.run(*args, **kwargs)
  File "c:\labscript\lib\site-packages\blacs\tab_base_classes.py", line 891, in run
    self.mainloop()
  File "c:\labscript\lib\site-packages\blacs\tab_base_classes.py", line 923, in mainloop
    results = func(*args,**kwargs)
  File "c:\labscript\lib\site-packages\labscript_devices\IMAQdxCamera\blacs_workers.py", line 251, in init
    self.camera = self.get_camera()
  File "c:\labscript\lib\site-packages\labscript_devices\IMAQdxCamera\blacs_workers.py", line 280, in get_camera
    return self.interface_class(self.serial_number)
  File "c:\labscript\lib\site-packages\labscript_devices\FlyCapture2Camera\blacs_workers.py", line 70, in __init__
    import PyCapture2
------------

Fatal exception in main process - Tue May 24, 09:35:53 :
 Traceback (most recent call last):
  File "c:\labscript\lib\site-packages\blacs\tab_base_classes.py", line 837, in mainloop
    next_yield = inmain(generator.send,results)
  File "c:\labscript\lib\site-packages\qtutils\invoke_in_main.py", line 88, in inmain
    return get_inmain_result(_in_main_later(fn, False, *args, **kwargs))
  File "c:\labscript\lib\site-packages\qtutils\invoke_in_main.py", line 150, in get_inmain_result
    raise value.with_traceback(traceback)
  File "c:\labscript\lib\site-packages\qtutils\invoke_in_main.py", line 46, in event
    result = event.fn(*event.args, **event.kwargs)
  File "c:\labscript\lib\site-packages\blacs\tab_base_classes.py", line 536, in _initialise_worker
    raise Exception('Device failed to initialise')
Exception: Device failed to initialise
philipstarkey commented 2 years ago

I think this might be a bug in the double import denier.

Path imported: C:\Users\Administrator\namespace

This suggests the file path for the module is being detected as "namespace". That shouldn't be happening (namespace modules should have the file path set to None) but it is.

Do you have a non standard Python install?

@chrisjbillington what do you think. Catch this case in labscript utils and ignore anything with spec.origin=="namespace"?

Moriaty-TT commented 2 years ago

Do you have a non standard Python install? We have installed python-3.6.8-amd64 under the system path.

chrisjbillington commented 2 years ago

Good catch Phil. Looks like there was a change in Python where namespace packages have spec.origin = None since 3.8:

https://github.com/python/cpython/commit/bbbcf8693b876daae4469765aa62f8924f39a7d2

and prior to that had spec.origin = "namespace", since when I don't know.

So yes, let's have it ignore spec.origin=="namespace"

philipstarkey commented 2 years ago

I see. Looks like they tried to patch it on 3.6 but then reverted because too many packages were relying on the broken behaviour. They could have at least updated the documentation for 3.6 so it was consistent with the behaviour of the code!

@Moriaty-TT There are two options for you to solve this. If you have an editable labscript suite install, you should be able to patch this line to be: if spec is not None and spec.origin is not None and spec.origin != "built-in" and spec.origin != "namespace": If this works, please let us know!

Alternatively, you could upgrade your version of Python if you don't have any third party libraries you rely on that are stuck on Python 3.6 (Python 3.6 is officially end-of-life now according to the Python Software Foundation)

Moriaty-TT commented 2 years ago

you should be able to patch this line to be: if spec is not None and spec.origin is not None and spec.origin != "built-in" and spec.origin != "namespace":

Thanks very much. The problem of double import has been solved. But I have a new problem,I am trying to solve it. Here is my traceback

Exception in worker - Thu May 26, 22:05:37 :
Traceback (most recent call last):
  File "c:\labscript\lib\site-packages\labscript_devices\IMAQdxCamera\blacs_workers.py", line 251, in init
    self.camera = self.get_camera()
  File "c:\labscript\lib\site-packages\labscript_devices\IMAQdxCamera\blacs_workers.py", line 280, in get_camera
    return self.interface_class(self.serial_number)
  File "c:\labscript\lib\site-packages\labscript_devices\FlyCapture2Camera\blacs_workers.py", line 80, in __init__
    self.camera.connect(bus.getCameraFromSerialNumber(serial_number))
  File "src\cython\PyCapture2.pyx", line 3406, in PyCapture2.BusManager.getCameraFromSerialNumber
  File "src\cython\PyCapture2.pyx", line 3849, in PyCapture2.checkError
PyCapture2.Fc2error: b'Bus Master Failure.'

Fatal exception in main process - Thu May 26, 22:05:37 :
 Traceback (most recent call last):
  File "c:\labscript\lib\site-packages\blacs\tab_base_classes.py", line 837, in mainloop
    next_yield = inmain(generator.send,results)
  File "c:\labscript\lib\site-packages\qtutils\invoke_in_main.py", line 88, in inmain
    return get_inmain_result(_in_main_later(fn, False, *args, **kwargs))
  File "c:\labscript\lib\site-packages\qtutils\invoke_in_main.py", line 150, in get_inmain_result
    raise value.with_traceback(traceback)
  File "c:\labscript\lib\site-packages\qtutils\invoke_in_main.py", line 46, in event
    result = event.fn(*event.args, **event.kwargs)
  File "c:\labscript\lib\site-packages\blacs\tab_base_classes.py", line 536, in _initialise_worker
    raise Exception('Device failed to initialise')
Exception: Device failed to initialise

Thanks again for your help

philipstarkey commented 2 years ago

@Moriaty-TT great! I've split your new question off into a separate issue. I'm not familiar with PyCapture2 but hopefully someone who is can help you 🙂

philipstarkey commented 2 years ago

Sorry for the email spam. I transferred the issue between repositories and it seems to have triggered some email notifications (as will this!)