:-$

Ryan's work blog

My Links

News

The WeatherPixie
Subscribe with Bloglines
About this blog

Tools I use:

Post Categories

Article Categories

Archives

Image Galleries

Blog Stats

Personal

Projects

Random Blogs

Random other

Reference

Web comics

Work

Python packages

So we're using Python to do the next version of our code generator, and so I've been learning a hell of a lot about this language recently. Notably, I've been fighting with a good way to reference things from different files. Coming from the C# world, where everything has its own type, specifying what you wanted to use wasn't difficult, but it was often very redundant. Specifying what you want in Python is a little looser. Here's the evolution of ways I found.
  1. Putting everything in the path and praying to the gods of naming conflicts
    In python, you have a sys.path, which is analogous to your system PATH variables. Python will search the sys.path variable for the class or variable, just like running "cmd" on a DOS prompt searches the %PATH% until it finds cmd.exe. So, with that in mind, I put this at the top of every file:
    import sys
    sys.path.append('./')
    sys.path.append('../')
       
    That way, things are always visible. Of course, after importing a few files, the sys.path had multiple entries for './' and '../', which seemed really dirty. Also, we're moving to this language to get more dynamism, and copy/pasting the same line of code everywhere was kinda defeating the purpose. Also, if I ever wanted to use the same name in two places, it would have a conflict and die. So, I hit up some mailing lists and documentation, and came up with a slightly safer way.
  2. Use a __init__.py to automatically add all the paths
    You can put a __init__.py in a directory, which makes that directory a package. In there I had a function that added a directory to sys.path, first checking if it existed already, so I wouldn't get any messy duplicates. This proved unreliable, and worked depending on where I started the python interpreter from. This also required copy/pasting about to ensure that all subdirectories would include everything properly. Still too much of a mess, so sent a request to the python tutor mailing list. After some helpful replies and sitting up with Nathan methodically testing things, we found something clean and promptly got drunk.
  3. Use __init__.py files and the __all__ variable to specify the contents of a package, and import using the full dotted module name.
    By sticking a __init__.py in each directory, that enables me to use the path to the file as a way to identify it. So, with the file structure:
    • /One
      • __init__.py
      • A.py
    • /Two
      • __init__.py
      • B.py
    In file A.py, I can reference things in B.py by saying:
    import Two.B
    In a nutshell, we need to walk the namespace hierarchy and import each file, so we can define an __all__ in the __init__.py file, and use that for our reflective needs. See the python docs for more info on __all__.
So, that is that, and now I'm ready to get back to actually programming. Woo!

posted on Monday, January 10, 2005 7:04 PM