Import Cython exposed class from another directory
Question: I have a Python project in which I want to make use of a `C++` class that I
exposed through Cython (really, I just need a specific instance of the class,
as the code below will demonstrate). Because there were a bunch of files
associated with the class I decided to put it in its own package.

In the `__init__.py` file of this package, I have what amounts to the
following code:

    
    
    from foo import Foo  # import the class
    
    bar = Foo(some_parameters)
    __all__ = ["bar"]
    

This works fine when I run `__init__.py` by itself. However, when I try to
access it from outside the directory:

    
    
    from qux import bar  # inside main.py in the parent directory
    

I get the error traced back to the _same_ `__init__.py`:

    
    
    File "D:\path\to\qux\\__init__.py", line 2, in <module>
    from foo import Foo
    ImportError: No module named 'foo'
    

Recall that `foo` is a Cython file, not pure Python code.

The directory structure looks like this:

    
    
    main_project\
      main.py
      (more supporting files here)
      qux\
        __init__.py
        cy_foo.cpp
        cy_foo.pyx
        foo.cpp
        foo.h
        foo.cp35-win_amd64.pyd
        (more supporting files here)
    

What's going on?


Answer: I don't think this has anything to do with `Cython` per se, rather, this issue
is due to the fact that when you execute `main.py` in the top level directory,
`Python` will execute `__init__.py` and search in the same directory failing
to locate the `foo` module inside `qux`.

As a solution, change the `import` statement in `__init__.py` to:

    
    
    from qux.foo import Foo
    

If for some reason you still need to run `__init__.py` as the `__main__`
script, you can use the oh so familiar `if` clause to check the `__name__`:

    
    
    if __name__ == "__main__":
        from foo import Foo
    else:
        from qux.foo import Foo
    
    bar = Foo("arguments")
    __all__ = ["bar"]
    

Now, if run as the `__main__` module, `__init__.py` will find `foo`, if not,
it allows others to find it.

