This is work in progress - will keep working on it over the next few days
Which import statement format and what folder/package structure should one use for an application.
In my project I had all source code in one folder, over time this became to be a hassle. I have recently started on a major revision of my software and wanted to take advantage of organizing it better.
I wanted to structure things into packages to make it easier to find things and this will hopefully also force/push me into better code reuse.
It was relatively easy to come up with a folder and package structure (at least the basic stuff to get going).
That pretty quickly brought out the problem on how to import things, my initial reading suggested to use relative imports, this looked great to start with but I soon run into trouble with sub-package/inter-package imports, so back to reading and asking for help on the wxPython list.
As always the wxPython list members (special thanks to Chris Barker, Robin Dunn and Oliver Schoenborn) where very very helpful even so this topic is really more a Python issue and nothing specific to wxPython.
The folder/package structure
The structure should allow a good organization of the source code and it should be possible to run individual modules in sub-packages, e.g. to test layouts of such things as a panel etc.
Below is a sub-set of what I am starting to use and it should be enough to explain the import issues I run into and the solutions to them.
dev dev/aproject dev/aproject/setup_lib.py dev/aproject/aprojsrc/ dev/aproject/aprojsrc/__init__.py dev/aproject/aprojsrc/mypub.py dev/aproject/aprojsrc/mypubtopics.py dev/aproject/aprojsrc/libui dev/aproject/aprojsrc//libui/__init__.py dev/aproject/aprojsrc/libui/textctrl.py dev/aproject/aprojsrc/model/__init__.py dev/aproject/aprojsrc/model/m_masterdata.py
Obviously a real project would have some more folders for such things as documentation, scripts etc.
"aproject" is the top/root folder for this project, it then has the "aprojsrc" folder which contains the Python modules and packages (defined by having a __init__.py module in them).
As I mentioned above I tried first with relative imports but did not get very far, before I gave up and then went with absolute imports.
In the above case absolute imports means that all import statemtents start with "import aprojsrc." or "from aprojsrc." as "aprojsrc" is the top level package, unless your import is referencing a module within the package you are importing from, in which case you just use "import moduleinthispackage".
However the use of absolute imports will cause a problem if you try to run e.g. "libui/textctrl.py" directly as "aprojsrc" is not in the Python path and if textctrl.py contains e.g. "import aprojsrc.mypub it will fail.
The solution to this is to use the "develop" option of setuptools/distribute as shown below. After you create this setup_lib.py just run "python setup_lib.py develop" and it will create an egg in your site-packages folder and from then on you will be able to run textcrl.py in aprojsrc/libui as a standalone module and it will find "aprojsrc.pypub".
1 # -*- coding: utf-8 -*-# 2 #!/usr/bin/env python 3 4 from setuptools import setup 5 6 7 # This setup is suitable for "python setup.py develop". 8 9 setup( 10 name = "aprojsrc", 11 version = "0.1.1", 12 description='aprojsrc - just for running in development mode', 13 author='whoeverdid this', 14 firstname.lastname@example.org', 15 packages = ["aprojsrc"], 16 )
When using wx.lib.pubsub version 3 api as included in wxPython 188.8.131.52 and using "pub.importTopicTree("aprojsrc.mypubtopics")" will fail as it doesn't handle the "." notation, a fix has been found and will be included in an upcoming release. Should you need the fix before check the topic "OT - at least a bit - application package/folder structure" on the pubsub list.
intra package import
My application uses SQLAlchemy and I based my stuff on how things are done in TurboGears 2.x, which means the "__init__.py" in the model package sets up some stuff which is then needed in e.g. m_masterdata.py. I should also state that I subscribe to the notion that "from something import *" is not to be used or only in very very rare occasions, instead I normally do e.g. "import sqlalchemy as sa" or "import sqlalchemy.orm as sao" and so on.
In m_masterdata.py I would therefore have liked to do "import aprojsrc.model as db" but that doesn't work as I am trying to import things from the __init__.py which is obviously within the package I am importing from, so I have to use "from appsource.model import *" or "from appsource.model import (DeclarativeBase, DBSession, andwhateverelse)".
If you select to use "from appsource.model import *" you might want to look into the __all__ variable, it limits what "*" will import and I believe it also helps speeding up the import.
Following some links which I found useful.
Please feel free to comment on the above you can use the wxPython list or send me an email to werner.bruhin at free.fr or just add it here.