Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Namespacing and classes

I'm trying to write some (in my opinion) readable code in Python. I need a module that will contain a number of classes. Theoretically I know everything that is needed to accomplish this: I can simply put class definitions in a single module file.

For readability purposes I want to put every class definition into separate file (they are starting to be quite lengthy!), and all these classes into one directory. Whenever I create new file although it's contents are visible where I need them, class definition that's inside is scoped with unneeded module.

How should I do it? What is 'Python' way to do that?

like image 759
samuil Avatar asked Feb 25 '11 12:02

samuil


2 Answers

Import them all within __init__.py, and then have the consumer import the package.

from .module1 import Class1
from .module2 import Class2
 ...
like image 112
Ignacio Vazquez-Abrams Avatar answered Sep 30 '22 04:09

Ignacio Vazquez-Abrams


If you want to avoid hardcoding module paths, file, class, and function names in many places, you could do something like the following which dynamically imports (almost) all the Python files it finds in a package's subdirectory.

The key is remembering that the __init__.py file is a largely unconstrained Python script itself, and is therefore free to perform fairly sophisticated processing of its own to determine what's in the package's namespace.

File package\__init__.py:

def _import_package_files():
    """ Dynamically import all the Python modules in this module's sub directory. """
    import os
    import sys
    import traceback

    package_path = os.path.split(__file__)[0]
    package_directory = os.path.split(package_path)[1]

    for fn in os.listdir(package_directory):
        globals_, locals_ = globals(), locals()
        # process all python files in directory that don't start with underscore
        if fn[0] != '_' and fn.split('.')[-1] in ('py', 'pyw'):
            modulename = fn.split('.')[0] # filename without extension
            subpackage = ".".join([package_directory, modulename])
            try:
                module = __import__(subpackage, globals_, locals_, [modulename])
            except:
                traceback.print_exc(file=sys.stdout)
                raise # reraise exception

_import_package_files()

File package\Class1.py:

class Class1(object):
    pass

File package\Class2.py:

class Class2(object):
    pass

File package\Class3.py:

class Class3(object):
    pass

File usepackage.py:

import package

print(package.Class1)
print(package.Class2)
print(package.Class3)

Output from running usepackage.py:

<module 'package.Class1' from 'C:\Files\package\Class1.pyc'>
<module 'package.Class2' from 'C:\Files\package\Class2.pyc'>
<module 'package.Class3' from 'C:\Files\package\Class3.pyc'>
like image 35
martineau Avatar answered Sep 30 '22 03:09

martineau