microsoft / Qcodes

Modular data acquisition framework
http://microsoft.github.io/Qcodes/
MIT License
324 stars 310 forks source link

Importing qcodes from MATLAB doesn't work #2102

Closed lankes-fzj closed 4 years ago

lankes-fzj commented 4 years ago

Since many projects in my institute are developed with MATLAB, I am currently trying to implement a MATLAB interface for our Qcodes instruments. This would allow the instruments to be used from MATLAB scripts.

In general, it's very easy to call Python-scripts from MATLAB or to import modules from Python into MATLAB. Unfortunately, this doesn't work with qcodes. I'm always getting the following error.

Error using __init__><module> (line 7)
Python Error: AttributeError: module 'qcodes' has no attribute 'configuration'

By __init__><module> here the qcodes.__init__ module is meant

If already tried to use different MATLAB versions and to reinstall Qcodes and its dependencies, but without any success. If I import Qcodes directly from Python (e.g. IPython console) it works fine.

Probably this is not Qcodes-problem, but problem with MATLAB's Python interface. But maybe someone here has had similar experiences and could give me some advice.

Steps to reproduce

  1. (Only when using Anaconda:) start MATLAB from your target conda-environment:
    conda activate <environment>
    matlab
  2. Setup Python environment in MATLAB with pyenv (MATLAB >= 2019b) or pyversion:
    pyenv("path/to/python.exe")
    % or
    pyversion("path/to/python.exe")

    After this you may have to restart MATLAB (remember starting it from the right conda-environment)

  3. Importing or use Qcodes
    
    qc = py.importlib.import_module("qcodes")
    % or some specific module of Qcodes
    qcinstr = py.importlib.import_module("qcodes.instrument.base")

Expected behaviour

I would expect MATLAB to import the certain module, as it does for other packages. This also works with Qcodes, but only with some sources, like some files from utils:

>> vals = py.importlib.import_module("qcodes.utils.validators")

vals = 

  Python module with properties:

            numbertypes: [1×1 py.typing._Union]
         PermissiveInts: [1×1 py.type]
              Multiples: [1×1 py.type]
                  OnOff: [1×1 py.type]
              Validator: [1×1 py.type]
                     np: [1×1 py.module]
                Numbers: [1×1 py.type]
                   Dict: [1×1 py.type]
                   math: [1×1 py.module]
                Nothing: [1×1 py.type]
                  Union: [1×1 py.typing._Union]
            collections: [1×1 py.module]
              BIGSTRING: [1×1 py.int]
               Callable: [1×1 py.type]
               Optional: [1×1 py.typing._Optional]
         ComplexNumbers: [1×1 py.type]
             shape_type: [1×1 py.typing._Union]
       shape_tuple_type: [1×1 py.typing._Union]
               Hashable: [1×1 py.abc.ABCMeta]
                  TList: [1×1 py.typing.GenericMeta]
                    Any: [1×1 py.typing._Any]
              MultiType: [1×1 py.type]
                 BIGINT: [1×1 py.int]
               Sequence: [1×1 py.type]
           validate_all: [1×1 py.function]
               Anything: [1×1 py.type]
                   Bool: [1×1 py.type]
              TSequence: [1×1 py.typing.GenericMeta]
                  Lists: [1×1 py.type]
                   Enum: [1×1 py.type]
                  Tuple: [1×1 py.typing.TupleMeta]
              TCallable: [1×1 py.typing.CallableMeta]
                Strings: [1×1 py.type]
                 Arrays: [1×1 py.type]
    PermissiveMultiples: [1×1 py.type]
              range_str: [1×1 py.function]
          complex_types: [1×6 py.tuple]
                   Ints: [1×1 py.type]

    <module 'qcodes.utils.validators' from 'C:\\Users\\l.lankes\\.conda\\envs\\pysqubic\\lib\\site-packages\\qcodes\\utils\\validators.py'>

Actual behaviour

Instead importing files on qcodes.configuration:

>> qc = py.importlib.import_module("qcodes")
Error using __init__><module> (line 7)
Python Error: AttributeError: module 'qcodes' has no attribute 'configuration'

Error in <frozen importlib>_call_with_frames_removed (line 219)

Error in <frozen importlib>exec_module (line 678)

Error in <frozen importlib>_load_unlocked (line 665)

Error in <frozen importlib>_find_and_load_unlocked (line 955)

Error in <frozen importlib>_find_and_load (line 971)

Error in <frozen importlib>_gcd_import (line 994)

Error in __init__>import_module (line 126)

System

operating system Windows 10 Pro 64-bit

qcodes branch master (latest version 0.16.0 from pip)

qcodes commit 66222eb8cc4ab1ab2cdadb94da827f94436b4af7

MATLAB 2018a Also tested with: 2020a

Python 3.6 Also tried with: 3.7

astafan8 commented 4 years ago

i would also submit this question to MATLAB via their support request system, out of curiousity.

I can't think of why this would happen... Out of curiosity, would you mind trying to change the line 7 in qcodes init.py file to from qcodes import configuration as qcconfig and try to import qcodes in matlab again?

lankes-fzj commented 4 years ago

I've tried your suggestion to change the import line and it works for this line, but the error now occurs at another line: import qcodes.utils.validators as vals. It looked like it might have something to do with the import ... as statements.

So I've changed all of them to from .. import .. as and now importing qcodes from MATLAB is working fine. Thank you for that 👍

For development this soultion is sufficient for me, but I will also try to setup my environment without Anaconda (in a vm to not mess up my host system) to see if this is the reason. I will give you an update, if it works.

Update

Using Python without Anaconda would also be solution to this problem. Maybe this is more suitable for other Qcodes users, but I think I still prefer astafan's workaround.

During testing I encountered another problem: The first import attempt always fails because h5py cannot load a DLL. The second import attempt, however, always seems to work. But this is not your problem, as there are already many issues about this problem in other projects using h5py. Therefore I will look for a solution there first.