Organizing Python Applications

I just found again a python library that uses relative imports (the python 2.4 way) and star imports and two days ago mika asked my how to organize Python applications. Interestingly this topic is not often discussed and you can do it terrible wrong because of a fundamental design mistake in Python 2.

Basically the problem occurs as soon as you have more than just one module and make a package around them. This is a good thing. Python packages are an awesome thing, they don’t cause namespace clashes and they work well. But a folder with a __init__.py file in does not automatically make this package importable. Many developers solve that by importing the modules in that package with so-called relative imports (from mymodule import foobar). That works because Python currently looks also in the folder of the module for moduls, no matter how deep in the package structure. The correct way would be from mypackage.mymodule import foobar, but that requires mypackage being in the pythonpath which is not the case per default if the bootstrapping code is also part of the package. Confused? Basically there must be a special file for any python application that starts that application up. In case of a WSGI application this for example is a myapplication.fcgi or whatever. The module that imports all other stuff has a problem. That problem is called __main__. The module that starts up any python powered application is not imported with its normal import name (for example myapplication.main) but as __main__ and can be imported twice because of this. So just create a file called myapplication-bin or something like that, import myapplication.main and start the main function from there.

Now all modules in that package can do from myapplication.somemodule import something because the working directory is the the folder the package “myapplication” is located in and that folder is automatically part of the pythonpath.

Also an example file structure for a GTK application could look like this:

myapplication-bin
  lib/
    myapplication/
      __init__.py
      main.py
      something_else.py
    shipped_dependency/
      __init__.py
  shared
    some_files.glade

In that case the myapplication-bin must add the “lib” to the pythonpath (by appending that folder to sys.path) and notify the application when starting about the location of shared. This also allows moving the shared files to /usr/share, the application code to /usr/lib or /usr/share too and myapplication-bin into /usr/bin.

Leave a Reply

cogitations driven by wordpress