Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

__init__.py does not find modules in same directory [duplicate]

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.

like image 425
Ray Avatar asked Jun 28 '17 11:06

Ray


People also ask

What does __ init __ py do in Python?

The __init__.py files are required to make Python treat directories containing the file as packages. This prevents directories with a common name, such as string , unintentionally hiding valid modules that occur later on the module search path.

Should __ init __ py be empty?

Leaving an __init__.py file empty is considered normal and even a good practice, if the package's modules and sub-packages do not need to share any code.

What goes into __ init __ py?

The __init__.py file makes Python treat directories containing it as modules. Furthermore, this is the first file to be loaded in a module, so you can use it to execute code that you want to run each time a module is loaded, or specify the submodules to be exported.


1 Answers

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"

like image 128
bakatrouble Avatar answered Sep 22 '22 12:09

bakatrouble