Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use __init__.py in (sub-)modules to define namespaces?

my question is about writing Python (3.x) packages and (sub-)modules and the correct usage of __init__.py files to declare namespaces.
I used to code in C++, so I like to use a lot of separate files to organize projects. For example, (imo) if a module contains several classes, each of these should be in a separate file.

As I am inexperienced developing in Python, it is hard to formulate my thoughts in a simple question. So let's consider the following small python package as an example.

Directory layout

dir
 |
 +-- example
 |    |
 |    +-- script.py
 |
 +-- package
      |
      +-- __init__.py
      |
      +-- foo.py
      |
      +-- subpackage
           |
           +-- __init__.py
           |
           +-- bar.py

Let's have a look at the files.

File Content

package/foo.py:

def foo:
    print('foo')

package/subpackage/bar.py:

def bar:
    print('bar')

The following example/script.py works fine.

import sys
sys.path.insert(0, '..')

import package
import package.subpackage


package.foo.foo()
package.subpackage.bar.bar()

I don't like to use package.foo.foo() / package.subpackage.bar.bar() and would like to use package.foo() / package.subpackage.bar().

And I don't want to use from package.subpackage.bar import bar, as I don't want to mix the namespace of subpackage into script.

Solution

I used the __init__.py files to achieve that.

package/__init__.py:

from package.foo import foo

package/subpackage/__init__.py:

from package.subpackage.bar import bar

Questions

  • Is this a good python-like way to define namespaces? Or is there a better / common way to organize the file-system of a package in python. (I did not find a proper tutorial/example for this.)

  • In file package/subpackage/__init__.py, why does it have to be:

    from package.subpackage.bar import bar

    and not:

    from subpackage.bar import bar?

This would result in the error:

Traceback (most recent call last):
File "script.py", line x, in <module>
import package.subpackage
File "..\package\subpackage\__init__.py", line x, in <module>
from subpackage.bar import bar
ImportError: No module named 'subpackage'
like image 310
P. Siehr Avatar asked Jan 26 '17 10:01

P. Siehr


People also ask

How is __ init __ py used?

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.

How do you create a namespace in Python?

Practical Data Science using Python So if you want to create a namespace, you just need to call a function, instantiate an object, import a module or import a package. For example, we can create a class called Namespace and when you create an object of that class, you're basically creating a namespace.

What is __ init ___ py?

The __init__.py files are required to make Python treat the directories as containing packages; this is done to prevent directories with a common name, such as string, from unintentionally hiding valid modules that occur later on the module search path.

What should be put in __ 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

Is this a good python-like way to define namespaces? Or is there a better / common way to organize the file-system of a package in python. (I did not find a proper tutorial/example for this.)

This is an okay way to setup a Python package. Only okay and not 'good' because of the contents of foo.py and bar.py.

I don't like to use package.foo.foo() / package.subpackage.bar.bar() and would like to use package.foo() / package.subpackage.bar().

In this case, you can't. And not mixing the name spaces is good reason to not do from package.subpackage.bar import bar.

It would have been better if def foo(): ... and def bar(): ... were directly in __init__.py. That way, you could have done package.foo() and package.subpackage.bar(). It could also have been done by using __all__ in init but import * is also not considered good.

Or, the foo and bar packages should have had more in it like foo.function1, foo.other_func, bar.drink, etc. which gives it more human-friendly understandable organisation.

Examples and references are not within scope for good StackOverflow questions but here are some, for a well thought-out question:

  • Structuring Your Project — The Hitchhiker's Guide to Python
  • The Pythonic way of organizing modules and packages
  • How to organize a Python Project?
like image 135
aneroid Avatar answered Oct 11 '22 07:10

aneroid