Common Lisp’s package system provides a simple way to avoid name clashes by means of separate namespace. No more, no less. Albeit having their shadowy corners, as illustrated in this excellent tutorial by E. Gat, packages are very easy to use and, most of the time, get the work done. Basically, think of a package as a map from strings to symbols, with associated lookup functions, and bindings resolved at read time.
But, simple as they are, packages in CL are second-class citizens: you cannot modify them at runtime, add new symbols, create new packages and pass them around as first-class values. For instance, Python modules are dictionary objects (and, as such directly manipulable as, say message receivers or function arguments). Languages in the ML family provide powerful module manipulation facilities, including functors, that is, parametric modules that take modules as arguments and generate new ones (see, for instance, a sample in Alice ML). This kind of trick is not limited to ML: PLT’s units offer the same functionality for Scheme (although i find them cumbersome).
Back to CL, i recently discovered Tim Bradshaw’s Conduits, a nice library adding very interesting functionality to the vanilla package system. For instance, you can define variants of pre-existing modules, or extend a given package including only a subset of the symbols defined by its parent. You can also clone existing packages. Tim’s hacks also include a hierarchical package system for CMUCL that mimics Allegro CL’s one.