__init__.py does not find modules in same directory

Ray picture Ray · Jun 28, 2017 · Viewed 9.6k times · Source

I need assistance on how to organize source in a python package - I've already followed several tutorials on the web (especially this one) on how to do so, but it does not work as explained and how I imagined it.

I want to create a python package named binaryio. It should offer two classes named BinaryReader and BinaryWriter which I want users to be able to import with

from binaryio import BinaryReader
from binaryio import BinaryWriter

Thus I have created my repository and package directory structure as follows:

  • binaryio (repository root)
    • binaryio (package root)
      • __init__.py (s. below)
      • binaryreader.py (contains the BinaryReader class)
      • binarywriter.py (contains the BinaryWriter class)
    • setup.py (contains the setuptools.setup call)
    • .gitignore, README.md, LICENSE, ...

As you can see, the classes are in separate files as I'm used to this (coming from a C# background). I'm not sure if this is a good idea due to modules being the "unit" in Python - but otherwise cramping all classes into one huge file did not seem logical to me.

__init__.py looks as follows to import those classes, making (as I understood it) the from binaryio import BinaryReader imports possible for users later on:

from binaryreader import BinaryReader
from binarywriter import BinaryWriter

However, when I install the package locally (which seems to work fine) and try to import binaryio, I get the following error:

>>> import binaryio
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "D:\Projects\Git\binaryio\binaryio\__init__.py", line 1, in <module>
    from binaryreader import BinaryReader
ModuleNotFoundError: No module named 'binaryreader'

Apparently, something is wrong with my __init__.py file. I don't understand this, as a binaryreader.py file aka module exists in the same folder as you can see above. Funnily enough, my IDE (PyCharm, having set the package root as source folder) does not complain about the statements in it and can resolve all references.

What am I doing wrong here? According to the tutorial linked above, putting a file into xyz.py with a class named Abc and then write from xyz import Abc into __init__.py should work, but apparently it doesn't for me.

Answer

bakatrouble picture bakatrouble · Jun 28, 2017

Your code would work for Python 2.x, but not 3.x because of different relative imports syntax: without dot, Python 2.x would look for modules in module root and current package, and Python 3.x will look only in module root.

Import statements you want to use are these:

from binaryio.binaryreader import BinaryReader
from binaryio.binarywriter import BinaryWriter

Works in both Python 2.x and 3.x without "futures"